Merge "Enhance Cell Location Api."
diff --git a/Android.mk b/Android.mk
index 5879bb5..d27dbab 100644
--- a/Android.mk
+++ b/Android.mk
@@ -110,6 +110,7 @@
 	core/java/android/content/pm/IPackageStatsObserver.aidl \
 	core/java/android/database/IContentObserver.aidl \
 	core/java/android/hardware/ISerialManager.aidl \
+	core/java/android/hardware/input/IInputManager.aidl \
 	core/java/android/hardware/usb/IUsbManager.aidl \
 	core/java/android/net/IConnectivityManager.aidl \
 	core/java/android/net/INetworkManagementEventObserver.aidl \
@@ -117,6 +118,7 @@
 	core/java/android/net/INetworkPolicyListener.aidl \
 	core/java/android/net/INetworkPolicyManager.aidl \
 	core/java/android/net/INetworkStatsService.aidl \
+	core/java/android/net/nsd/INsdManager.aidl \
 	core/java/android/nfc/INdefPushCallback.aidl \
 	core/java/android/nfc/INfcAdapter.aidl \
 	core/java/android/nfc/INfcAdapterExtras.aidl \
@@ -170,6 +172,7 @@
 	core/java/com/android/internal/view/IInputMethodClient.aidl \
 	core/java/com/android/internal/view/IInputMethodManager.aidl \
 	core/java/com/android/internal/view/IInputMethodSession.aidl \
+	core/java/com/android/internal/widget/ILockSettings.aidl \
 	core/java/com/android/internal/widget/IRemoteViewsFactory.aidl \
 	core/java/com/android/internal/widget/IRemoteViewsAdapterConnection.aidl \
 	keystore/java/android/security/IKeyChainAliasCallback.aidl \
diff --git a/NOTICE b/NOTICE
index 152be20..4e69963 100644
--- a/NOTICE
+++ b/NOTICE
@@ -56,6 +56,17 @@
    =========================================================================
    ==  NOTICE file corresponding to the section 4 d of                    ==
    ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the mDnsResponder code.                           ==
+   =========================================================================
+
+mDnsResponder TXTRecord
+This file is Copyright 2004 Apple Computer, Inc.  but released under
+the Apache2 License.
+
+
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
    ==  in this case for the TagSoup code.                                 ==
    =========================================================================
 
diff --git a/api/current.txt b/api/current.txt
index 3a63d78..f00911b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -570,6 +570,7 @@
     field public static final int itemIconDisabledAlpha = 16843057; // 0x1010131
     field public static final int itemPadding = 16843565; // 0x101032d
     field public static final int itemTextAppearance = 16843052; // 0x101012c
+    field public static final int kcm = 16843696; // 0x10103b0
     field public static final int keepScreenOn = 16843286; // 0x1010216
     field public static final int key = 16843240; // 0x10101e8
     field public static final int keyBackground = 16843315; // 0x1010233
@@ -596,7 +597,7 @@
     field public static final int layerType = 16843604; // 0x1010354
     field public static final int layout = 16842994; // 0x10100f2
     field public static final int layoutAnimation = 16842988; // 0x10100ec
-    field public static final int layoutDirection = 16843689; // 0x10103a9
+    field public static final int layoutDirection = 16843691; // 0x10103ab
     field public static final int layout_above = 16843140; // 0x1010184
     field public static final int layout_alignBaseline = 16843142; // 0x1010186
     field public static final int layout_alignBottom = 16843146; // 0x101018a
@@ -618,10 +619,10 @@
     field public static final int layout_height = 16842997; // 0x10100f5
     field public static final int layout_margin = 16842998; // 0x10100f6
     field public static final int layout_marginBottom = 16843002; // 0x10100fa
-    field public static final int layout_marginEnd = 16843693; // 0x10103ad
+    field public static final int layout_marginEnd = 16843695; // 0x10103af
     field public static final int layout_marginLeft = 16842999; // 0x10100f7
     field public static final int layout_marginRight = 16843001; // 0x10100f9
-    field public static final int layout_marginStart = 16843692; // 0x10103ac
+    field public static final int layout_marginStart = 16843694; // 0x10103ae
     field public static final int layout_marginTop = 16843000; // 0x10100f8
     field public static final int layout_row = 16843643; // 0x101037b
     field public static final int layout_rowSpan = 16843644; // 0x101037c
@@ -717,16 +718,17 @@
     field public static final int packageNames = 16843649; // 0x1010381
     field public static final int padding = 16842965; // 0x10100d5
     field public static final int paddingBottom = 16842969; // 0x10100d9
-    field public static final int paddingEnd = 16843691; // 0x10103ab
+    field public static final int paddingEnd = 16843693; // 0x10103ad
     field public static final int paddingLeft = 16842966; // 0x10100d6
     field public static final int paddingRight = 16842968; // 0x10100d8
-    field public static final int paddingStart = 16843690; // 0x10103aa
+    field public static final int paddingStart = 16843692; // 0x10103ac
     field public static final int paddingTop = 16842967; // 0x10100d7
     field public static final int panelBackground = 16842846; // 0x101005e
     field public static final int panelColorBackground = 16842849; // 0x1010061
     field public static final int panelColorForeground = 16842848; // 0x1010060
     field public static final int panelFullBackground = 16842847; // 0x101005f
     field public static final int panelTextAppearance = 16842850; // 0x1010062
+    field public static final int parentActivityName = 16843697; // 0x10103b1
     field public static final deprecated int password = 16843100; // 0x101015c
     field public static final int path = 16842794; // 0x101002a
     field public static final int pathPattern = 16842796; // 0x101002c
@@ -931,6 +933,7 @@
     field public static final int summaryColumn = 16843426; // 0x10102a2
     field public static final int summaryOff = 16843248; // 0x10101f0
     field public static final int summaryOn = 16843247; // 0x10101ef
+    field public static final int supportsRtl = 16843688; // 0x10103a8
     field public static final int supportsUploading = 16843419; // 0x101029b
     field public static final int switchMinWidth = 16843632; // 0x1010370
     field public static final int switchPadding = 16843633; // 0x1010371
@@ -961,6 +964,7 @@
     field public static final int tension = 16843370; // 0x101026a
     field public static final int testOnly = 16843378; // 0x1010272
     field public static final int text = 16843087; // 0x101014f
+    field public static final int textAlignment = 16843690; // 0x10103aa
     field public static final int textAllCaps = 16843660; // 0x101038c
     field public static final int textAppearance = 16842804; // 0x1010034
     field public static final int textAppearanceButton = 16843271; // 0x1010207
@@ -1000,7 +1004,7 @@
     field public static final int textColorTertiary = 16843282; // 0x1010212
     field public static final int textColorTertiaryInverse = 16843283; // 0x1010213
     field public static final int textCursorDrawable = 16843618; // 0x1010362
-    field public static final int textDirection = 16843688; // 0x10103a8
+    field public static final int textDirection = 16843689; // 0x10103a9
     field public static final int textEditNoPasteWindowLayout = 16843541; // 0x1010315
     field public static final int textEditPasteWindowLayout = 16843540; // 0x1010314
     field public static final int textEditSideNoPasteWindowLayout = 16843615; // 0x101035f
@@ -2576,6 +2580,7 @@
     method public java.lang.String getLocalClassName();
     method public android.view.MenuInflater getMenuInflater();
     method public final android.app.Activity getParent();
+    method public android.content.Intent getParentActivityIntent();
     method public android.content.SharedPreferences getPreferences(int);
     method public int getRequestedOrientation();
     method public int getTaskId();
@@ -2592,6 +2597,8 @@
     method public boolean isTaskRoot();
     method public final deprecated android.database.Cursor managedQuery(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
     method public boolean moveTaskToBack(boolean);
+    method public boolean navigateUpTo(android.content.Intent);
+    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 onActivityResult(int, int, android.content.Intent);
@@ -2608,6 +2615,7 @@
     method public java.lang.CharSequence onCreateDescription();
     method protected deprecated android.app.Dialog onCreateDialog(int);
     method protected deprecated android.app.Dialog onCreateDialog(int, android.os.Bundle);
+    method public void onCreateNavigateUpTaskStack(android.app.TaskStackBuilder);
     method public boolean onCreateOptionsMenu(android.view.Menu);
     method public boolean onCreatePanelMenu(int, android.view.Menu);
     method public android.view.View onCreatePanelView(int);
@@ -2625,6 +2633,8 @@
     method public void onLowMemory();
     method public boolean onMenuItemSelected(int, android.view.MenuItem);
     method public boolean onMenuOpened(int, android.view.Menu);
+    method public boolean onNavigateUp();
+    method public boolean onNavigateUpFromChild(android.app.Activity);
     method protected void onNewIntent(android.content.Intent);
     method public boolean onOptionsItemSelected(android.view.MenuItem);
     method public void onOptionsMenuClosed(android.view.Menu);
@@ -2634,6 +2644,7 @@
     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);
+    method public void onPrepareNavigateUpTaskStack(android.app.TaskStackBuilder);
     method public boolean onPrepareOptionsMenu(android.view.Menu);
     method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
     method protected void onRestart();
@@ -2684,6 +2695,7 @@
     method public void setTitleColor(int);
     method public void setVisible(boolean);
     method public final void setVolumeControlStream(int);
+    method public boolean shouldUpRecreateTask(android.content.Intent);
     method public final deprecated void showDialog(int);
     method public final deprecated boolean showDialog(int, android.os.Bundle);
     method public android.view.ActionMode startActionMode(android.view.ActionMode.Callback);
@@ -3930,6 +3942,18 @@
     method public void setDefaultTab(int);
   }
 
+  public class TaskStackBuilder implements java.lang.Iterable {
+    method public android.app.TaskStackBuilder addNextIntent(android.content.Intent);
+    method public android.app.TaskStackBuilder addParentStack(android.app.Activity);
+    method public android.app.TaskStackBuilder addParentStack(java.lang.Class<?>);
+    method public static android.app.TaskStackBuilder from(android.content.Context);
+    method public android.content.Intent getIntent(int);
+    method public int getIntentCount();
+    method public android.app.PendingIntent getPendingIntent(int, int);
+    method public java.util.Iterator<android.content.Intent> iterator();
+    method public void startActivities();
+  }
+
   public class TimePickerDialog extends android.app.AlertDialog implements android.content.DialogInterface.OnClickListener android.widget.TimePicker.OnTimeChangedListener {
     ctor public TimePickerDialog(android.content.Context, android.app.TimePickerDialog.OnTimeSetListener, int, int, boolean);
     ctor public TimePickerDialog(android.content.Context, int, android.app.TimePickerDialog.OnTimeSetListener, int, int, boolean);
@@ -5209,6 +5233,7 @@
     field public static final java.lang.String DOWNLOAD_SERVICE = "download";
     field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
     field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
+    field public static final java.lang.String INPUT_SERVICE = "input";
     field public static final java.lang.String KEYGUARD_SERVICE = "keyguard";
     field public static final java.lang.String LAYOUT_INFLATER_SERVICE = "layout_inflater";
     field public static final java.lang.String LOCATION_SERVICE = "location";
@@ -6100,6 +6125,7 @@
     field public int configChanges;
     field public int flags;
     field public int launchMode;
+    field public java.lang.String parentActivityName;
     field public java.lang.String permission;
     field public int screenOrientation;
     field public int softInputMode;
@@ -6131,6 +6157,7 @@
     field public static final int FLAG_STOPPED = 2097152; // 0x200000
     field public static final int FLAG_SUPPORTS_LARGE_SCREENS = 2048; // 0x800
     field public static final int FLAG_SUPPORTS_NORMAL_SCREENS = 1024; // 0x400
+    field public static final int FLAG_SUPPORTS_RTL = 4194304; // 0x400000
     field public static final int FLAG_SUPPORTS_SCREEN_DENSITIES = 8192; // 0x2000
     field public static final int FLAG_SUPPORTS_SMALL_SCREENS = 512; // 0x200
     field public static final int FLAG_SUPPORTS_XLARGE_SCREENS = 524288; // 0x80000
@@ -9792,6 +9819,15 @@
 
 }
 
+package android.hardware.input {
+
+  public final class InputManager {
+    field public static final java.lang.String ACTION_QUERY_KEYBOARD_LAYOUTS = "android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS";
+    field public static final java.lang.String META_DATA_KEYBOARD_LAYOUTS = "android.hardware.input.metadata.KEYBOARD_LAYOUTS";
+  }
+
+}
+
 package android.hardware.usb {
 
   public class UsbAccessory implements android.os.Parcelable {
@@ -12897,6 +12933,7 @@
     method public byte[] getHistoricalBytes();
     method public int getMaxTransceiveLength();
     method public int getTimeout();
+    method public boolean isExtendedLengthApduSupported();
     method public void setTimeout(int);
     method public byte[] transceive(byte[]) throws java.io.IOException;
   }
@@ -22221,6 +22258,7 @@
 
   public final class InputDevice implements android.os.Parcelable {
     method public int describeContents();
+    method public java.lang.String getDescriptor();
     method public static android.view.InputDevice getDevice(int);
     method public static int[] getDeviceIds();
     method public int getId();
@@ -23207,6 +23245,7 @@
     method public void buildLayer();
     method public boolean callOnClick();
     method public boolean canResolveLayoutDirection();
+    method public boolean canResolveTextAlignment();
     method public boolean canResolveTextDirection();
     method public boolean canScrollHorizontally(int);
     method public boolean canScrollVertically(int);
@@ -23309,6 +23348,8 @@
     method public final int getMeasuredState();
     method public final int getMeasuredWidth();
     method public final int getMeasuredWidthAndState();
+    method public int getMinimumHeight();
+    method public int getMinimumWidth();
     method public int getNextFocusDownId();
     method public int getNextFocusForwardId();
     method public int getNextFocusLeftId();
@@ -23327,6 +23368,7 @@
     method public float getPivotY();
     method public int getResolvedLayoutDirection();
     method public int getResolvedLayoutDirection(android.graphics.drawable.Drawable);
+    method public int getResolvedTextAlignment();
     method public int getResolvedTextDirection();
     method public android.content.res.Resources getResources();
     method public final int getRight();
@@ -23338,6 +23380,9 @@
     method public float getRotationY();
     method public float getScaleX();
     method public float getScaleY();
+    method public int getScrollBarDefaultDelayBeforeFade();
+    method public int getScrollBarFadeDuration();
+    method public int getScrollBarSize();
     method public int getScrollBarStyle();
     method public final int getScrollX();
     method public final int getScrollY();
@@ -23347,6 +23392,7 @@
     method public int getSystemUiVisibility();
     method public java.lang.Object getTag();
     method public java.lang.Object getTag(int);
+    method public int getTextAlignment();
     method public int getTextDirection();
     method public final int getTop();
     method protected float getTopFadingEdgeStrength();
@@ -23371,6 +23417,7 @@
     method public boolean hasFocus();
     method public boolean hasFocusable();
     method public boolean hasOnClickListeners();
+    method public boolean hasOverlappingRendering();
     method public boolean hasTransientState();
     method public boolean hasWindowFocus();
     method public static android.view.View inflate(android.content.Context, int, android.view.ViewGroup);
@@ -23406,6 +23453,7 @@
     method public boolean isPressed();
     method public boolean isSaveEnabled();
     method public boolean isSaveFromParentEnabled();
+    method public boolean isScrollContainer();
     method public boolean isScrollbarFadingEnabled();
     method public boolean isSelected();
     method public boolean isShown();
@@ -23453,6 +23501,8 @@
     method public void onPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method public void onResolvedLayoutDirectionChanged();
     method public void onResolvedLayoutDirectionReset();
+    method public void onResolvedTextAlignmentChanged();
+    method public void onResolvedTextAlignmentReset();
     method public void onResolvedTextDirectionChanged();
     method public void onResolvedTextDirectionReset();
     method protected void onRestoreInstanceState(android.os.Parcelable);
@@ -23493,11 +23543,13 @@
     method public boolean requestRectangleOnScreen(android.graphics.Rect);
     method public boolean requestRectangleOnScreen(android.graphics.Rect, boolean);
     method public void resetResolvedLayoutDirection();
+    method public void resetResolvedTextAlignment();
     method public void resetResolvedTextDirection();
     method public void resolveLayoutDirection();
     method public void resolvePadding();
     method public static int resolveSize(int, int);
     method public static int resolveSizeAndState(int, int, int);
+    method public void resolveTextAlignment();
     method public void resolveTextDirection();
     method public void restoreHierarchyState(android.util.SparseArray<android.os.Parcelable>);
     method public void saveHierarchyState(android.util.SparseArray<android.os.Parcelable>);
@@ -23510,8 +23562,9 @@
     method public void setActivated(boolean);
     method public void setAlpha(float);
     method public void setAnimation(android.view.animation.Animation);
+    method public void setBackground(android.graphics.drawable.Drawable);
     method public void setBackgroundColor(int);
-    method public void setBackgroundDrawable(android.graphics.drawable.Drawable);
+    method public deprecated void setBackgroundDrawable(android.graphics.drawable.Drawable);
     method public void setBackgroundResource(int);
     method public final void setBottom(int);
     method public void setCameraDistance(float);
@@ -23571,6 +23624,9 @@
     method public void setSaveFromParentEnabled(boolean);
     method public void setScaleX(float);
     method public void setScaleY(float);
+    method public void setScrollBarDefaultDelayBeforeFade(int);
+    method public void setScrollBarFadeDuration(int);
+    method public void setScrollBarSize(int);
     method public void setScrollBarStyle(int);
     method public void setScrollContainer(boolean);
     method public void setScrollX(int);
@@ -23581,6 +23637,7 @@
     method public void setSystemUiVisibility(int);
     method public void setTag(java.lang.Object);
     method public void setTag(int, java.lang.Object);
+    method public void setTextAlignment(int);
     method public void setTextDirection(int);
     method public final void setTop(int);
     method public void setTouchDelegate(android.view.TouchDelegate);
@@ -23691,6 +23748,15 @@
     field public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 1; // 0x1
     field public static final int SYSTEM_UI_FLAG_VISIBLE = 0; // 0x0
     field public static final int SYSTEM_UI_LAYOUT_FLAGS = 1536; // 0x600
+    field public static final int TEXT_ALIGNMENT_CENTER = 4; // 0x4
+    field protected static int TEXT_ALIGNMENT_DEFAULT;
+    field public static final int TEXT_ALIGNMENT_GRAVITY = 1; // 0x1
+    field public static final int TEXT_ALIGNMENT_INHERIT = 0; // 0x0
+    field public static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = 131072; // 0x20000
+    field public static final int TEXT_ALIGNMENT_TEXT_END = 3; // 0x3
+    field public static final int TEXT_ALIGNMENT_TEXT_START = 2; // 0x2
+    field public static final int TEXT_ALIGNMENT_VIEW_END = 6; // 0x6
+    field public static final int TEXT_ALIGNMENT_VIEW_START = 5; // 0x5
     field public static final int TEXT_DIRECTION_ANY_RTL = 2; // 0x2
     field protected static int TEXT_DIRECTION_DEFAULT;
     field public static final int TEXT_DIRECTION_FIRST_STRONG = 1; // 0x1
@@ -24116,15 +24182,18 @@
   }
 
   public final class ViewTreeObserver {
+    method public void addOnDrawListener(android.view.ViewTreeObserver.OnDrawListener);
     method public void addOnGlobalFocusChangeListener(android.view.ViewTreeObserver.OnGlobalFocusChangeListener);
     method public void addOnGlobalLayoutListener(android.view.ViewTreeObserver.OnGlobalLayoutListener);
     method public void addOnPreDrawListener(android.view.ViewTreeObserver.OnPreDrawListener);
     method public void addOnScrollChangedListener(android.view.ViewTreeObserver.OnScrollChangedListener);
     method public void addOnTouchModeChangeListener(android.view.ViewTreeObserver.OnTouchModeChangeListener);
+    method public final void dispatchOnDraw();
     method public final void dispatchOnGlobalLayout();
     method public final boolean dispatchOnPreDraw();
     method public boolean isAlive();
     method public deprecated void removeGlobalOnLayoutListener(android.view.ViewTreeObserver.OnGlobalLayoutListener);
+    method public void removeOnDrawListener(android.view.ViewTreeObserver.OnDrawListener);
     method public void removeOnGlobalFocusChangeListener(android.view.ViewTreeObserver.OnGlobalFocusChangeListener);
     method public void removeOnGlobalLayoutListener(android.view.ViewTreeObserver.OnGlobalLayoutListener);
     method public void removeOnPreDrawListener(android.view.ViewTreeObserver.OnPreDrawListener);
@@ -24132,6 +24201,10 @@
     method public void removeOnTouchModeChangeListener(android.view.ViewTreeObserver.OnTouchModeChangeListener);
   }
 
+  public static abstract interface ViewTreeObserver.OnDrawListener {
+    method public abstract void onDraw();
+  }
+
   public static abstract interface ViewTreeObserver.OnGlobalFocusChangeListener {
     method public abstract void onGlobalFocusChanged(android.view.View, android.view.View);
   }
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index b277efb..3e123ba 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -29,6 +29,8 @@
 import android.content.IntentSender;
 import android.content.SharedPreferences;
 import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -65,13 +67,13 @@
 import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.WindowManagerImpl;
 import android.view.View.OnCreateContextMenuListener;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.view.ViewManager;
 import android.view.Window;
 import android.view.WindowManager;
+import android.view.WindowManagerImpl;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.AdapterView;
 
@@ -704,6 +706,7 @@
     /*package*/ boolean mVisibleFromServer = false;
     /*package*/ boolean mVisibleFromClient = true;
     /*package*/ ActionBarImpl mActionBar = null;
+    private boolean mEnableDefaultActionBarUp;
 
     private CharSequence mTitle;
     private int mTitleColor = 0;
@@ -865,6 +868,13 @@
         if (mLastNonConfigurationInstances != null) {
             mAllLoaderManagers = mLastNonConfigurationInstances.loaders;
         }
+        if (mActivityInfo.parentActivityName != null) {
+            if (mActionBar == null) {
+                mEnableDefaultActionBarUp = true;
+            } else {
+                mActionBar.setDefaultDisplayHomeAsUpEnabled(true);
+            }
+        }
         if (savedInstanceState != null) {
             Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
             mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
@@ -1829,6 +1839,7 @@
         }
         
         mActionBar = new ActionBarImpl(this);
+        mActionBar.setDefaultDisplayHomeAsUpEnabled(mEnableDefaultActionBarUp);
     }
     
     /**
@@ -2630,7 +2641,7 @@
      * facilities.
      * 
      * <p>Derived classes should call through to the base class for it to
-     * perform the default menu handling.
+     * perform the default menu handling.</p>
      * 
      * @param item The menu item that was selected.
      * 
@@ -2643,10 +2654,105 @@
         if (mParent != null) {
             return mParent.onOptionsItemSelected(item);
         }
+        if (item.getItemId() == android.R.id.home && mActionBar != null &&
+                (mActionBar.getDisplayOptions() & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
+            if (mParent == null) {
+                onNavigateUp();
+            } else {
+                mParent.onNavigateUpFromChild(this);
+            }
+            return true;
+        }
         return false;
     }
 
     /**
+     * This method is called whenever the user chooses to navigate Up within your application's
+     * activity hierarchy from the action bar.
+     *
+     * <p>If the attribute {@link android.R.attr#parentActivityName parentActivityName}
+     * was specified in the manifest for this activity or an activity-alias to it,
+     * default Up navigation will be handled automatically. If any activity
+     * along the parent chain requires extra Intent arguments, the Activity subclass
+     * should override the method {@link #onPrepareNavigateUpTaskStack(TaskStackBuilder)}
+     * to supply those arguments.</p>
+     *
+     * <p>See <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back Stack</a>
+     * from the developer guide and <a href="{@docRoot}design/patterns/navigation.html">Navigation</a>
+     * from the design guide for more information about navigating within your app.</p>
+     *
+     * <p>See the {@link TaskStackBuilder} class and the Activity methods
+     * {@link #getParentActivityIntent()}, {@link #shouldUpRecreateTask(Intent)}, and
+     * {@link #navigateUpTo(Intent)} for help implementing custom Up navigation.
+     * The AppNavigation sample application in the Android SDK is also available for reference.</p>
+     *
+     * @return true if Up navigation completed successfully and this Activity was finished,
+     *         false otherwise.
+     */
+    public boolean onNavigateUp() {
+        // Automatically handle hierarchical Up navigation if the proper
+        // metadata is available.
+        Intent upIntent = getParentActivityIntent();
+        if (upIntent != null) {
+            if (shouldUpRecreateTask(upIntent)) {
+                TaskStackBuilder b = TaskStackBuilder.from(this);
+                onCreateNavigateUpTaskStack(b);
+                onPrepareNavigateUpTaskStack(b);
+                b.startActivities();
+                finish();
+            } else {
+                navigateUpTo(upIntent);
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * This is called when a child activity of this one attempts to navigate up.
+     * The default implementation simply calls onNavigateUp() on this activity (the parent).
+     *
+     * @param child The activity making the call.
+     */
+    public boolean onNavigateUpFromChild(Activity child) {
+        return onNavigateUp();
+    }
+
+    /**
+     * Define the synthetic task stack that will be generated during Up navigation from
+     * a different task.
+     *
+     * <p>The default implementation of this method adds the parent chain of this activity
+     * as specified in the manifest to the supplied {@link TaskStackBuilder}. Applications
+     * may choose to override this method to construct the desired task stack in a different
+     * way.</p>
+     *
+     * <p>Applications that wish to supply extra Intent parameters to the parent stack defined
+     * by the manifest should override {@link #onPrepareNavigateUpTaskStack(TaskStackBuilder)}.</p>
+     *
+     * @param builder An empty TaskStackBuilder - the application should add intents representing
+     *                the desired task stack
+     */
+    public void onCreateNavigateUpTaskStack(TaskStackBuilder builder) {
+        builder.addParentStack(this);
+    }
+
+    /**
+     * Prepare the synthetic task stack that will be generated during Up navigation
+     * from a different task.
+     *
+     * <p>This method receives the {@link TaskStackBuilder} with the constructed series of
+     * Intents as generated by {@link #onCreateNavigateUpTaskStack(TaskStackBuilder)}.
+     * If any extra data should be added to these intents before launching the new task,
+     * the application should override this method and add that data here.</p>
+     *
+     * @param builder A TaskStackBuilder that has been populated with Intents by
+     *                onCreateNavigateUpTaskStack.
+     */
+    public void onPrepareNavigateUpTaskStack(TaskStackBuilder builder) {
+    }
+
+    /**
      * 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).
      *  
@@ -4658,6 +4764,114 @@
     public void onActionModeFinished(ActionMode mode) {
     }
 
+    /**
+     * Returns true if the app should recreate the task when navigating 'up' from this activity
+     * by using targetIntent.
+     *
+     * <p>If this method returns false the app can trivially call
+     * {@link #navigateUpTo(Intent)} using the same parameters to correctly perform
+     * up navigation. If this method returns false, the app should synthesize a new task stack
+     * by using {@link TaskStackBuilder} or another similar mechanism to perform up navigation.</p>
+     *
+     * @param targetIntent An intent representing the target destination for up navigation
+     * @return true if navigating up should recreate a new task stack, false if the same task
+     *         should be used for the destination
+     */
+    public boolean shouldUpRecreateTask(Intent targetIntent) {
+        try {
+            PackageManager pm = getPackageManager();
+            ComponentName cn = targetIntent.getComponent();
+            if (cn == null) {
+                cn = targetIntent.resolveActivity(pm);
+            }
+            ActivityInfo info = pm.getActivityInfo(cn, 0);
+            if (info.taskAffinity == null) {
+                return false;
+            }
+            return !ActivityManagerNative.getDefault()
+                    .targetTaskAffinityMatchesActivity(mToken, info.taskAffinity);
+        } catch (RemoteException e) {
+            return false;
+        } catch (NameNotFoundException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Navigate from this activity to the activity specified by upIntent, finishing this activity
+     * in the process. If the activity indicated by upIntent already exists in the task's history,
+     * this activity and all others before the indicated activity in the history stack will be
+     * finished. If the indicated activity does not appear in the history stack, this is equivalent
+     * to simply calling finish() on this activity.
+     *
+     * <p>This method should be used when performing up navigation from within the same task
+     * as the destination. If up navigation should cross tasks in some cases, see
+     * {@link #shouldUpRecreateTask(Intent)}.</p>
+     *
+     * @param upIntent An intent representing the target destination for up navigation
+     *
+     * @return true if up navigation successfully reached the activity indicated by upIntent and
+     *         upIntent was delivered to it. false if an instance of the indicated activity could
+     *         not be found and this activity was simply finished normally.
+     */
+    public boolean navigateUpTo(Intent upIntent) {
+        if (mParent == null) {
+            ComponentName destInfo = upIntent.getComponent();
+            if (destInfo == null) {
+                destInfo = upIntent.resolveActivity(getPackageManager());
+                if (destInfo == null) {
+                    return false;
+                }
+                upIntent = new Intent(upIntent);
+                upIntent.setComponent(destInfo);
+            }
+            int resultCode;
+            Intent resultData;
+            synchronized (this) {
+                resultCode = mResultCode;
+                resultData = mResultData;
+            }
+            if (resultData != null) {
+                resultData.setAllowFds(false);
+            }
+            try {
+                return ActivityManagerNative.getDefault().navigateUpTo(mToken, upIntent,
+                        resultCode, resultData);
+            } catch (RemoteException e) {
+                return false;
+            }
+        } else {
+            return mParent.navigateUpToFromChild(this, upIntent);
+        }
+    }
+
+    /**
+     * This is called when a child activity of this one calls its
+     * {@link #navigateUpTo} method.  The default implementation simply calls
+     * navigateUpTo(upIntent) on this activity (the parent).
+     *
+     * @param child The activity making the call.
+     * @param upIntent An intent representing the target destination for up navigation
+     *
+     * @return true if up navigation successfully reached the activity indicated by upIntent and
+     *         upIntent was delivered to it. false if an instance of the indicated activity could
+     *         not be found and this activity was simply finished normally.
+     */
+    public boolean navigateUpToFromChild(Activity child, Intent upIntent) {
+        return navigateUpTo(upIntent);
+    }
+
+    /**
+     * Obtain an {@link Intent} that will launch an explicit target activity specified by
+     * this activity's logical parent. The logical parent is named in the application's manifest
+     * by the {@link android.R.attr#parentActivityName parentActivityName} attribute.
+     *
+     * @return a new Intent targeting the defined parent of this activity
+     */
+    public Intent getParentActivityIntent() {
+        return new Intent().setClassName(this, mActivityInfo.parentActivityName);
+    }
+
     // ------------------ Internal API ------------------
     
     final void setParent(Activity parent) {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 531a695..11b4c3a 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1774,5 +1774,4 @@
             return false;
         }
     }
-
 }
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 5917cbf..000abc5 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -17,10 +17,10 @@
 package android.app;
 
 import android.content.ComponentName;
+import android.content.IIntentReceiver;
+import android.content.IIntentSender;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.IIntentSender;
-import android.content.IIntentReceiver;
 import android.content.IntentSender;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ConfigurationInfo;
@@ -32,11 +32,11 @@
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Debug;
-import android.os.Parcelable;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
 import android.os.IBinder;
 import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
+import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.StrictMode;
 import android.text.TextUtils;
@@ -1605,6 +1605,31 @@
             return true;
         }
 
+        case TARGET_TASK_AFFINITY_MATCHES_ACTIVITY_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IBinder token = data.readStrongBinder();
+            String destAffinity = data.readString();
+            boolean res = targetTaskAffinityMatchesActivity(token, destAffinity);
+            reply.writeNoException();
+            reply.writeInt(res ? 1 : 0);
+            return true;
+        }
+
+        case NAVIGATE_UP_TO_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IBinder token = data.readStrongBinder();
+            Intent target = Intent.CREATOR.createFromParcel(data);
+            int resultCode = data.readInt();
+            Intent resultData = null;
+            if (data.readInt() != 0) {
+                resultData = Intent.CREATOR.createFromParcel(data);
+            }
+            boolean res = navigateUpTo(token, target, resultCode, resultData);
+            reply.writeNoException();
+            reply.writeInt(res ? 1 : 0);
+            return true;
+        }
+
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -3662,5 +3687,42 @@
         reply.recycle();
     }
 
+    public boolean targetTaskAffinityMatchesActivity(IBinder token, String destAffinity)
+            throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(token);
+        data.writeString(destAffinity);
+        mRemote.transact(TARGET_TASK_AFFINITY_MATCHES_ACTIVITY_TRANSACTION, data, reply, 0);
+        reply.readException();
+        boolean result = reply.readInt() != 0;
+        data.recycle();
+        reply.recycle();
+        return result;
+    }
+
+    public boolean navigateUpTo(IBinder token, Intent target, int resultCode, Intent resultData)
+            throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(token);
+        target.writeToParcel(data, 0);
+        data.writeInt(resultCode);
+        if (resultData != null) {
+            data.writeInt(1);
+            resultData.writeToParcel(data, 0);
+        } else {
+            data.writeInt(0);
+        }
+        mRemote.transact(NAVIGATE_UP_TO_TRANSACTION, data, reply, 0);
+        reply.readException();
+        boolean result = reply.readInt() != 0;
+        data.recycle();
+        reply.recycle();
+        return result;
+    }
+
     private IBinder mRemote;
 }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index d758ecae..9dde51c 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -45,6 +45,7 @@
 import android.hardware.ISerialManager;
 import android.hardware.SensorManager;
 import android.hardware.SerialManager;
+import android.hardware.input.InputManager;
 import android.hardware.usb.IUsbManager;
 import android.hardware.usb.UsbManager;
 import android.location.CountryDetector;
@@ -59,6 +60,8 @@
 import android.net.ThrottleManager;
 import android.net.IThrottleManager;
 import android.net.Uri;
+import android.net.nsd.INsdManager;
+import android.net.nsd.NsdManager;
 import android.net.wifi.IWifiManager;
 import android.net.wifi.WifiManager;
 import android.net.wifi.p2p.IWifiP2pManager;
@@ -321,6 +324,11 @@
                     return createDropBoxManager();
                 }});
 
+        registerService(INPUT_SERVICE, new ServiceFetcher() {
+            public Object createService(ContextImpl ctx) {
+                return new InputManager(ctx);
+            }});
+
         registerService(INPUT_METHOD_SERVICE, new ServiceFetcher() {
                 public Object createService(ContextImpl ctx) {
                     return InputMethodManager.getInstance(ctx);
@@ -372,6 +380,14 @@
                         ctx.mMainThread.getHandler());
                 }});
 
+        registerService(NSD_SERVICE, new ServiceFetcher() {
+                @Override
+                public Object createService(ContextImpl ctx) {
+                    IBinder b = ServiceManager.getService(NSD_SERVICE);
+                    INsdManager service = INsdManager.Stub.asInterface(b);
+                    return new NsdManager(service);
+                }});
+
         // Note: this was previously cached in a static variable, but
         // constructed using mMainThread.getHandler(), so converting
         // it to be a regular Context-cached service...
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index ad8d41f..dd58397 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -1097,6 +1097,18 @@
         }
     }
 
+    /** {@hide} */
+    public static boolean isActiveNetworkExpensive(Context context) {
+        // TODO: connect to NetworkPolicyManager
+        return false;
+    }
+
+    /** {@hide} */
+    public static long getActiveNetworkWarningBytes(Context context) {
+        // TODO: connect to NetworkPolicyManager
+        return -1;
+    }
+
     /**
      * Adds a file to the downloads database system, so it could appear in Downloads App
      * (and thus become eligible for management by the Downloads App).
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 2b1eb43..0f287c1 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -341,6 +341,12 @@
 
     public void dismissKeyguardOnNextActivity() throws RemoteException;
 
+    public boolean targetTaskAffinityMatchesActivity(IBinder token, String destAffinity)
+            throws RemoteException;
+
+    public boolean navigateUpTo(IBinder token, Intent target, int resultCode, Intent resultData)
+            throws RemoteException;
+
     /*
      * Private non-Binder interfaces
      */
@@ -578,4 +584,6 @@
     int GET_MY_MEMORY_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+142;
     int KILL_PROCESSES_BELOW_FOREGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+143;
     int GET_CURRENT_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+144;
+    int TARGET_TASK_AFFINITY_MATCHES_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+145;
+    int NAVIGATE_UP_TO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+146;
 }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 096af93..04c64a0 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -26,6 +26,7 @@
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.SystemClock;
 import android.text.TextUtils;
 import android.util.IntProperty;
 import android.util.Log;
@@ -808,6 +809,7 @@
     @Deprecated
     public void setLatestEventInfo(Context context,
             CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent) {
+        // TODO: rewrite this to use Builder
         RemoteViews contentView = new RemoteViews(context.getPackageName(),
                 R.layout.notification_template_base);
         if (this.icon != 0) {
@@ -820,6 +822,7 @@
             contentView.setTextViewText(R.id.text, contentText);
         }
         if (this.when != 0) {
+            contentView.setViewVisibility(R.id.time, View.VISIBLE);
             contentView.setLong(R.id.time, "setTime", when);
         }
 
@@ -942,6 +945,7 @@
         private ArrayList<Action> mActions = new ArrayList<Action>(3);
         private boolean mCanHasIntruder;
         private boolean mIntruderActionsShowText;
+        private boolean mUseChronometer;
 
         /**
          * Constructs a new Builder with the defaults:
@@ -983,6 +987,18 @@
         }
 
         /**
+         * @hide
+         * 
+         * Show the {@link Notification#when} field as a countdown (or count-up) timer instead of a timestamp.  
+         *
+         * @see Notification#when
+         */
+        public Builder setUsesChronometer(boolean b) {
+            mUseChronometer = b;
+            return this;
+        }
+
+        /**
          * Set the small icon resource, which will be used to represent the notification in the
          * status bar.
          *
@@ -1434,7 +1450,15 @@
                 }
             }
             if (mWhen != 0) {
-                contentView.setLong(R.id.time, "setTime", mWhen);
+                if (mUseChronometer) {
+                    contentView.setViewVisibility(R.id.chronometer, View.VISIBLE);
+                    contentView.setLong(R.id.chronometer, "setBase",
+                            mWhen + (SystemClock.elapsedRealtime() - System.currentTimeMillis()));
+                    contentView.setBoolean(R.id.chronometer, "setStarted", true);
+                } else {
+                    contentView.setViewVisibility(R.id.time, View.VISIBLE);
+                    contentView.setLong(R.id.time, "setTime", mWhen);
+                }
             }
             contentView.setViewVisibility(R.id.line3, hasLine3 ? View.VISIBLE : View.GONE);
             return contentView;
diff --git a/core/java/android/app/TaskStackBuilder.java b/core/java/android/app/TaskStackBuilder.java
new file mode 100644
index 0000000..ee7c6ad
--- /dev/null
+++ b/core/java/android/app/TaskStackBuilder.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * Utility class for constructing synthetic back stacks for cross-task navigation
+ * on Android 3.0 and newer.
+ *
+ * <p>In API level 11 (Android 3.0/Honeycomb) the recommended conventions for
+ * app navigation using the back key changed. The back key's behavior is local
+ * to the current task and does not capture navigation across different tasks.
+ * Navigating across tasks and easily reaching the previous task is accomplished
+ * through the "recents" UI, accessible through the software-provided Recents key
+ * on the navigation or system bar. On devices with the older hardware button configuration
+ * the recents UI can be accessed with a long press on the Home key.</p>
+ *
+ * <p>When crossing from one task stack to another post-Android 3.0,
+ * the application should synthesize a back stack/history for the new task so that
+ * the user may navigate out of the new task and back to the Launcher by repeated
+ * presses of the back key. Back key presses should not navigate across task stacks.</p>
+ *
+ * <p>TaskStackBuilder provides a way to obey the correct conventions
+ * around cross-task navigation.</p>
+ *
+ * <div class="special reference">
+ * <h3>About Navigation</h3>
+ * For more detailed information about tasks, the back stack, and navigation design guidelines,
+ * please read
+ * <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back Stack</a>
+ * from the developer guide and <a href="{@docRoot}design/patterns/navigation.html">Navigation</a>
+ * from the design guide.
+ * </div>
+ */
+public class TaskStackBuilder implements Iterable<Intent> {
+    private static final String TAG = "TaskStackBuilder";
+
+    private final ArrayList<Intent> mIntents = new ArrayList<Intent>();
+    private final Context mSourceContext;
+
+    private TaskStackBuilder(Context a) {
+        mSourceContext = a;
+    }
+
+    /**
+     * Return a new TaskStackBuilder for launching a fresh task stack consisting
+     * of a series of activities.
+     *
+     * @param context The context that will launch the new task stack or generate a PendingIntent
+     * @return A new TaskStackBuilder
+     */
+    public static TaskStackBuilder from(Context context) {
+        return new TaskStackBuilder(context);
+    }
+
+    /**
+     * Add a new Intent to the task stack. The most recently added Intent will invoke
+     * the Activity at the top of the final task stack.
+     *
+     * @param nextIntent Intent for the next Activity in the synthesized task stack
+     * @return This TaskStackBuilder for method chaining
+     */
+    public TaskStackBuilder addNextIntent(Intent nextIntent) {
+        mIntents.add(nextIntent);
+        return this;
+    }
+
+    /**
+     * Add the activity parent chain as specified by the
+     * {@link android.R.attr#parentActivityName parentActivityName} attribute of the activity
+     * (or activity-alias) element in the application's manifest to the task stack builder.
+     *
+     * @param sourceActivity All parents of this activity will be added
+     * @return This TaskStackBuilder for method chaining
+     */
+    public TaskStackBuilder addParentStack(Activity sourceActivity) {
+        final int insertAt = mIntents.size();
+        Intent parent = sourceActivity.getParentActivityIntent();
+        PackageManager pm = sourceActivity.getPackageManager();
+        while (parent != null) {
+            mIntents.add(insertAt, parent);
+            try {
+                ActivityInfo info = pm.getActivityInfo(parent.getComponent(), 0);
+                String parentActivity = info.parentActivityName;
+                if (parentActivity != null) {
+                    parent = new Intent().setComponent(
+                            new ComponentName(mSourceContext, parentActivity));
+                } else {
+                    parent = null;
+                }
+            } catch (NameNotFoundException e) {
+                Log.e(TAG, "Bad ComponentName while traversing activity parent metadata");
+                throw new IllegalArgumentException(e);
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Add the activity parent chain as specified by the
+     * {@link android.R.attr#parentActivityName parentActivityName} attribute of the activity
+     * (or activity-alias) element in the application's manifest to the task stack builder.
+     *
+     * @param sourceActivityClass All parents of this activity will be added
+     * @return This TaskStackBuilder for method chaining
+     */
+    public TaskStackBuilder addParentStack(Class<?> sourceActivityClass) {
+        final int insertAt = mIntents.size();
+        PackageManager pm = mSourceContext.getPackageManager();
+        try {
+            ActivityInfo info = pm.getActivityInfo(
+                    new ComponentName(mSourceContext, sourceActivityClass), 0);
+            String parentActivity = info.parentActivityName;
+            Intent parent = new Intent().setComponent(
+                    new ComponentName(mSourceContext, parentActivity));
+            while (parent != null) {
+                mIntents.add(insertAt, parent);
+                info = pm.getActivityInfo(parent.getComponent(), 0);
+                parentActivity = info.parentActivityName;
+                if (parentActivity != null) {
+                    parent = new Intent().setComponent(
+                            new ComponentName(mSourceContext, parentActivity));
+                } else {
+                    parent = null;
+                }
+            }
+        } catch (NameNotFoundException e) {
+            Log.e(TAG, "Bad ComponentName while traversing activity parent metadata");
+            throw new IllegalArgumentException(e);
+        }
+        return this;
+    }
+
+    /**
+     * @return the number of intents added so far.
+     */
+    public int getIntentCount() {
+        return mIntents.size();
+    }
+
+    /**
+     * Get the intent at the specified index.
+     * Useful if you need to modify the flags or extras of an intent that was previously added,
+     * for example with {@link #addParentStack(Activity)}.
+     *
+     * @param index Index from 0-getIntentCount()
+     * @return the intent at position index
+     */
+    public Intent getIntent(int index) {
+        return mIntents.get(index);
+    }
+
+    public Iterator<Intent> iterator() {
+        return mIntents.iterator();
+    }
+
+    /**
+     * Start the task stack constructed by this builder.
+     */
+    public void startActivities() {
+        if (mIntents.isEmpty()) {
+            throw new IllegalStateException(
+                    "No intents added to TaskStackBuilder; cannot startActivities");
+        }
+
+        Intent[] intents = mIntents.toArray(new Intent[mIntents.size()]);
+        intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+                Intent.FLAG_ACTIVITY_CLEAR_TASK |
+                Intent.FLAG_ACTIVITY_TASK_ON_HOME);
+        mSourceContext.startActivities(intents);
+    }
+
+    /**
+     * Obtain a {@link PendingIntent} for launching the task constructed by this builder so far.
+     *
+     * @param requestCode Private request code for the sender
+     * @param flags May be {@link PendingIntent#FLAG_ONE_SHOT},
+     *              {@link PendingIntent#FLAG_NO_CREATE}, {@link PendingIntent#FLAG_CANCEL_CURRENT},
+     *              {@link PendingIntent#FLAG_UPDATE_CURRENT}, or any of the flags supported by
+     *              {@link Intent#fillIn(Intent, int)} to control which unspecified parts of the
+     *              intent that can be supplied when the actual send happens.
+     * @return The obtained PendingIntent
+     */
+    public PendingIntent getPendingIntent(int requestCode, int flags) {
+        Intent[] intents = mIntents.toArray(new Intent[mIntents.size()]);
+        return PendingIntent.getActivities(mSourceContext, requestCode, intents, flags);
+    }
+}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 2902504..36638f9 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1769,6 +1769,18 @@
     public static final String WIFI_P2P_SERVICE = "wifip2p";
 
     /**
+     * Use with {@link #getSystemService} to retrieve a {@link
+     * android.net.NsdManager} for handling management of network service
+     * discovery
+     *
+     * @hide
+     * @see #getSystemService
+     * @see android.net.NsdManager
+     */
+    public static final String NSD_SERVICE = "servicediscovery";
+
+
+    /**
      * Use with {@link #getSystemService} to retrieve a
      * {@link android.media.AudioManager} for handling management of volume,
      * ringer modes and audio routing.
@@ -1907,6 +1919,15 @@
     public static final String SERIAL_SERVICE = "serial";
 
     /**
+     * Use with {@link #getSystemService} to retrieve a
+     * {@link android.hardware.input.InputManager} for interacting with input devices.
+     *
+     * @see #getSystemService
+     * @see android.hardware.input.InputManager
+     */
+    public static final String INPUT_SERVICE = "input";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 0e6694de..6b16e74 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -450,6 +450,11 @@
      */
     public static final int UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW = 1;
 
+    /**
+     * If defined, the activity named here is the logical parent of this activity.
+     */
+    public String parentActivityName;
+
     public ActivityInfo() {
     }
 
@@ -465,6 +470,7 @@
         configChanges = orig.configChanges;
         softInputMode = orig.softInputMode;
         uiOptions = orig.uiOptions;
+        parentActivityName = orig.parentActivityName;
     }
     
     /**
@@ -524,6 +530,7 @@
         dest.writeInt(configChanges);
         dest.writeInt(softInputMode);
         dest.writeInt(uiOptions);
+        dest.writeString(parentActivityName);
     }
 
     public static final Parcelable.Creator<ActivityInfo> CREATOR
@@ -548,5 +555,6 @@
         configChanges = source.readInt();
         softInputMode = source.readInt();
         uiOptions = source.readInt();
+        parentActivityName = source.readString();
     }
 }
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 65a8750..cbabc7c 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -291,6 +291,17 @@
     public static final int FLAG_STOPPED = 1<<21;
 
     /**
+     * Value for {@link #flags}: true  when the application is willing to support
+     * RTL (right to left). All activities will inherit this value.
+     *
+     * Set from the {@link android.R.attr#supportsRtl} attribute in the
+     * activity's manifest.
+     *
+     * Default value is false (no support for RTL).
+     */
+    public static final int FLAG_SUPPORTS_RTL = 1<<22;
+
+    /**
      * Value for {@link #flags}: Set to true if the application has been
      * installed using the forward lock option.
      *
@@ -466,8 +477,17 @@
         if (uiOptions != 0) {
             pw.println(prefix + "uiOptions=0x" + Integer.toHexString(uiOptions));
         }
+        pw.println(prefix + "supportsRtl=" + (hasRtlSupport() ? "true" : "false"));
         super.dumpBack(pw, prefix);
     }
+
+    /**
+     * @return true if "supportsRtl" has been set to true in the AndroidManifest
+     * @hide
+     */
+    public boolean hasRtlSupport() {
+        return (flags & FLAG_SUPPORTS_RTL) == FLAG_SUPPORTS_RTL;
+    }
     
     public static class DisplayNameComparator
             implements Comparator<ApplicationInfo> {
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index eb8536f..15ccda3 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1761,6 +1761,12 @@
             ai.flags |= ApplicationInfo.FLAG_LARGE_HEAP;
         }
 
+        if (sa.getBoolean(
+                com.android.internal.R.styleable.AndroidManifestApplication_supportsRtl,
+                false /* default is no RTL support*/)) {
+            ai.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
+        }
+
         String str;
         str = sa.getNonConfigurationString(
                 com.android.internal.R.styleable.AndroidManifestApplication_permission, 0);
@@ -2024,6 +2030,19 @@
                 com.android.internal.R.styleable.AndroidManifestActivity_uiOptions,
                 a.info.applicationInfo.uiOptions);
 
+        String parentName = sa.getNonConfigurationString(
+                com.android.internal.R.styleable.AndroidManifestActivity_parentActivityName, 0);
+        if (parentName != null) {
+            String parentClassName = buildClassName(a.info.packageName, parentName, outError);
+            if (outError[0] == null) {
+                a.info.parentActivityName = parentClassName;
+            } else {
+                Log.e(TAG, "Activity " + a.info.name + " specified invalid parentActivityName " +
+                        parentName);
+                outError[0] = null;
+            }
+        }
+
         String str;
         str = sa.getNonConfigurationString(
                 com.android.internal.R.styleable.AndroidManifestActivity_permission, 0);
@@ -2268,6 +2287,7 @@
         info.theme = target.info.theme;
         info.softInputMode = target.info.softInputMode;
         info.uiOptions = target.info.uiOptions;
+        info.parentActivityName = target.info.parentActivityName;
         
         Activity a = new Activity(mParseActivityAliasArgs, info);
         if (outError[0] != null) {
@@ -2289,6 +2309,20 @@
             a.info.permission = str.length() > 0 ? str.toString().intern() : null;
         }
 
+        String parentName = sa.getNonConfigurationString(
+                com.android.internal.R.styleable.AndroidManifestActivityAlias_parentActivityName,
+                0);
+        if (parentName != null) {
+            String parentClassName = buildClassName(a.info.packageName, parentName, outError);
+            if (outError[0] == null) {
+                a.info.parentActivityName = parentClassName;
+            } else {
+                Log.e(TAG, "Activity alias " + a.info.name +
+                        " specified invalid parentActivityName " + parentName);
+                outError[0] = null;
+            }
+        }
+
         sa.recycle();
 
         if (outError[0] != null) {
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
new file mode 100644
index 0000000..85061bb
--- /dev/null
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input;
+
+/** @hide */
+interface IInputManager {
+}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
new file mode 100755
index 0000000..6093404
--- /dev/null
+++ b/core/java/android/hardware/input/InputManager.java
@@ -0,0 +1,441 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input;
+
+import com.android.internal.util.XmlUtils;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+import android.view.KeyCharacterMap;
+import android.view.KeyCharacterMap.UnavailableException;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Provides information about input devices and available key layouts.
+ * <p>
+ * Get an instance of this class by calling
+ * {@link android.content.Context#getSystemService(java.lang.String)
+ * Context.getSystemService()} with the argument
+ * {@link android.content.Context#INPUT_SERVICE}.
+ * </p>
+ */
+public final class InputManager {
+    private static final String TAG = "InputManager";
+
+    private final Context mContext;
+
+    // Used to simulate a persistent data store.
+    // TODO: Replace with the real thing.
+    private static final HashMap<String, String> mFakeRegistry = new HashMap<String, String>();
+
+    /**
+     * Broadcast Action: Query available keyboard layouts.
+     * <p>
+     * The input manager service locates available keyboard layouts
+     * by querying broadcast receivers that are registered for this action.
+     * An application can offer additional keyboard layouts to the user
+     * by declaring a suitable broadcast receiver in its manifest.
+     * </p><p>
+     * Here is an example broadcast receiver declaration that an application
+     * might include in its AndroidManifest.xml to advertise keyboard layouts.
+     * The meta-data specifies a resource that contains a description of each keyboard
+     * layout that is provided by the application.
+     * <pre><code>
+     * &lt;receiver android:name=".InputDeviceReceiver">
+     *     &lt;intent-filter>
+     *         &lt;action android:name="android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS" />
+     *     &lt;/intent-filter>
+     *     &lt;meta-data android:name="android.hardware.input.metadata.KEYBOARD_LAYOUTS"
+     *             android:resource="@xml/keyboard_layouts" />
+     * &lt;/receiver>
+     * </code></pre>
+     * </p><p>
+     * In the above example, the <code>@xml/keyboard_layouts</code> resource refers to
+     * an XML resource whose root element is <code>&lt;keyboard-layouts></code> that
+     * contains zero or more <code>&lt;keyboard-layout></code> elements.
+     * Each <code>&lt;keyboard-layout></code> element specifies the name, label, and location
+     * of a key character map for a particular keyboard layout.
+     * <pre></code>
+     * &lt;?xml version="1.0" encoding="utf-8"?>
+     * &lt;keyboard-layouts xmlns:android="http://schemas.android.com/apk/res/android">
+     *     &lt;keyboard-layout android:name="keyboard_layout_english_us"
+     *             android:label="@string/keyboard_layout_english_us_label"
+     *             android:kcm="@raw/keyboard_layout_english_us" />
+     * &lt;/keyboard-layouts>
+     * </p><p>
+     * The <code>android:name</code> attribute specifies an identifier by which
+     * the keyboard layout will be known in the package.
+     * The <code>android:label</code> attributes specifies a human-readable descriptive
+     * label to describe the keyboard layout in the user interface, such as "English (US)".
+     * The <code>android:kcm</code> attribute refers to a
+     * <a href="http://source.android.com/tech/input/key-character-map-files.html">
+     * key character map</a> resource that defines the keyboard layout.
+     * </p>
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_QUERY_KEYBOARD_LAYOUTS =
+            "android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS";
+
+    /**
+     * Metadata Key: Keyboard layout metadata associated with
+     * {@link #ACTION_QUERY_KEYBOARD_LAYOUTS}.
+     * <p>
+     * Specifies the resource id of a XML resource that describes the keyboard
+     * layouts that are provided by the application.
+     * </p>
+     */
+    public static final String META_DATA_KEYBOARD_LAYOUTS =
+            "android.hardware.input.metadata.KEYBOARD_LAYOUTS";
+
+    /** @hide */
+    public InputManager(Context context) {
+        mContext = context;
+    }
+
+    /**
+     * Gets information about all supported keyboard layouts.
+     * <p>
+     * The input manager consults the built-in keyboard layouts as well
+     * as all keyboard layouts advertised by applications using a
+     * {@link #ACTION_QUERY_KEYBOARD_LAYOUTS} broadcast receiver.
+     * </p>
+     *
+     * @return A list of all supported keyboard layouts.
+     * @hide
+     */
+    public List<KeyboardLayout> getKeyboardLayouts() {
+        ArrayList<KeyboardLayout> list = new ArrayList<KeyboardLayout>();
+
+        final PackageManager pm = mContext.getPackageManager();
+        Intent intent = new Intent(ACTION_QUERY_KEYBOARD_LAYOUTS);
+        for (ResolveInfo resolveInfo : pm.queryBroadcastReceivers(intent,
+                PackageManager.GET_META_DATA)) {
+            loadKeyboardLayouts(pm, resolveInfo.activityInfo, list, null);
+        }
+        return list;
+    }
+
+    /**
+     * Gets the keyboard layout with the specified descriptor.
+     *
+     * @param keyboardLayoutDescriptor The keyboard layout descriptor, as returned by
+     * {@link KeyboardLayout#getDescriptor()}.
+     * @return The keyboard layout, or null if it could not be loaded.
+     *
+     * @hide
+     */
+    public KeyboardLayout getKeyboardLayout(String keyboardLayoutDescriptor) {
+        if (keyboardLayoutDescriptor == null) {
+            throw new IllegalArgumentException("keyboardLayoutDescriptor must not be null");
+        }
+
+        KeyboardLayoutDescriptor d = parseKeyboardLayoutDescriptor(keyboardLayoutDescriptor);
+        if (d == null) {
+            return null;
+        }
+
+        final PackageManager pm = mContext.getPackageManager();
+        try {
+            ActivityInfo receiver = pm.getReceiverInfo(
+                    new ComponentName(d.packageName, d.receiverName),
+                    PackageManager.GET_META_DATA);
+            return loadKeyboardLayouts(pm, receiver, null, d.keyboardLayoutName);
+        } catch (NameNotFoundException ex) {
+            Log.w(TAG, "Could not load keyboard layout '" + d.keyboardLayoutName
+                    + "' from receiver " + d.packageName + "/" + d.receiverName, ex);
+            return null;
+        }
+    }
+
+    /**
+     * Gets the keyboard layout descriptor for the specified input device.
+     *
+     * @param inputDeviceDescriptor The input device descriptor.
+     * @return The keyboard layout descriptor, or null if unknown or if the default
+     * keyboard layout will be used.
+     *
+     * @hide
+     */
+    public String getInputDeviceKeyboardLayoutDescriptor(String inputDeviceDescriptor) {
+        if (inputDeviceDescriptor == null) {
+            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
+        }
+
+        return mFakeRegistry.get(inputDeviceDescriptor);
+    }
+
+    /**
+     * Sets the keyboard layout descriptor for the specified input device.
+     * <p>
+     * This method may have the side-effect of causing the input device in question
+     * to be reconfigured.
+     * </p>
+     *
+     * @param inputDeviceDescriptor The input device descriptor.
+     * @param keyboardLayoutDescriptor The keyboard layout descriptor, or null to remove
+     * the mapping so that the default keyboard layout will be used for the input device.
+     *
+     * @hide
+     */
+    public void setInputDeviceKeyboardLayoutDescriptor(String inputDeviceDescriptor,
+            String keyboardLayoutDescriptor) {
+        if (inputDeviceDescriptor == null) {
+            throw new IllegalArgumentException("inputDeviceDescriptor must not be null");
+        }
+
+        mFakeRegistry.put(inputDeviceDescriptor, keyboardLayoutDescriptor);
+    }
+
+    private KeyboardLayout loadKeyboardLayouts(
+            PackageManager pm, ActivityInfo receiver,
+            List<KeyboardLayout> list, String keyboardName) {
+        Bundle metaData = receiver.metaData;
+        if (metaData == null) {
+            return null;
+        }
+
+        int configResId = metaData.getInt(META_DATA_KEYBOARD_LAYOUTS);
+        if (configResId == 0) {
+            Log.w(TAG, "Missing meta-data '" + META_DATA_KEYBOARD_LAYOUTS + "' on receiver "
+                    + receiver.packageName + "/" + receiver.name);
+            return null;
+        }
+
+        try {
+            Resources resources = pm.getResourcesForApplication(receiver.applicationInfo);
+            XmlResourceParser parser = resources.getXml(configResId);
+            try {
+                XmlUtils.beginDocument(parser, "keyboard-layouts");
+
+                for (;;) {
+                    XmlUtils.nextElement(parser);
+                    String element = parser.getName();
+                    if (element == null) {
+                        break;
+                    }
+                    if (element.equals("keyboard-layout")) {
+                        TypedArray a = resources.obtainAttributes(
+                                parser, com.android.internal.R.styleable.KeyboardLayout);
+                        try {
+                            String name = a.getString(
+                                    com.android.internal.R.styleable.KeyboardLayout_name);
+                            String label = a.getString(
+                                    com.android.internal.R.styleable.KeyboardLayout_label);
+                            int kcmResId = a.getResourceId(
+                                     com.android.internal.R.styleable.KeyboardLayout_kcm, 0);
+                            if (name == null || label == null || kcmResId == 0) {
+                                Log.w(TAG, "Missing required 'name', 'label' or 'kcm' "
+                                        + "attributes in keyboard layout "
+                                        + "resource from receiver "
+                                        + receiver.packageName + "/" + receiver.name);
+                            } else {
+                                String descriptor = makeKeyboardLayoutDescriptor(
+                                        receiver.packageName, receiver.name, name);
+                                KeyboardLayout c = new KeyboardLayout(
+                                        descriptor, label, kcmResId);
+                                if (keyboardName != null && name.equals(keyboardName)) {
+                                    return c;
+                                }
+                                if (list != null) {
+                                    list.add(c);
+                                }
+                            }
+                        } finally {
+                            a.recycle();
+                        }
+                    } else {
+                        Log.w(TAG, "Skipping unrecognized element '" + element
+                                + "' in keyboard layout resource from receiver "
+                                + receiver.packageName + "/" + receiver.name);
+                    }
+                }
+            } finally {
+                parser.close();
+            }
+        } catch (Exception ex) {
+            Log.w(TAG, "Could not load keyboard layout resource from receiver "
+                    + receiver.packageName + "/" + receiver.name, ex);
+            return null;
+        }
+        if (keyboardName != null) {
+            Log.w(TAG, "Could not load keyboard layout '" + keyboardName
+                    + "' from receiver " + receiver.packageName + "/" + receiver.name
+                    + " because it was not declared in the keyboard layout resource.");
+        }
+        return null;
+    }
+
+    private static String makeKeyboardLayoutDescriptor(String packageName,
+            String receiverName, String keyboardName) {
+        return packageName + "/" + receiverName + "/" + keyboardName;
+    }
+
+    private static KeyboardLayoutDescriptor parseKeyboardLayoutDescriptor(String descriptor) {
+        int pos = descriptor.indexOf('/');
+        if (pos < 0 || pos + 1 == descriptor.length()) {
+            return null;
+        }
+        int pos2 = descriptor.indexOf('/', pos + 1);
+        if (pos2 < pos + 2 || pos2 + 1 == descriptor.length()) {
+            return null;
+        }
+
+        KeyboardLayoutDescriptor result = new KeyboardLayoutDescriptor();
+        result.packageName = descriptor.substring(0, pos);
+        result.receiverName = descriptor.substring(pos + 1, pos2);
+        result.keyboardLayoutName = descriptor.substring(pos2 + 1);
+        return result;
+    }
+
+    /**
+     * Describes a keyboard layout.
+     *
+     * @hide
+     */
+    public static final class KeyboardLayout implements Parcelable,
+            Comparable<KeyboardLayout> {
+        private final String mDescriptor;
+        private final String mLabel;
+        private final int mKeyCharacterMapResId;
+
+        private KeyCharacterMap mKeyCharacterMap;
+
+        public static final Parcelable.Creator<KeyboardLayout> CREATOR =
+                new Parcelable.Creator<KeyboardLayout>() {
+            public KeyboardLayout createFromParcel(Parcel source) {
+                return new KeyboardLayout(source);
+            }
+            public KeyboardLayout[] newArray(int size) {
+                return new KeyboardLayout[size];
+            }
+        };
+
+        private KeyboardLayout(String descriptor,
+                String label, int keyCharacterMapResId) {
+            mDescriptor = descriptor;
+            mLabel = label;
+            mKeyCharacterMapResId = keyCharacterMapResId;
+        }
+
+        private KeyboardLayout(Parcel source) {
+            mDescriptor = source.readString();
+            mLabel = source.readString();
+            mKeyCharacterMapResId = source.readInt();
+        }
+
+        /**
+         * Gets the keyboard layout descriptor, which can be used to retrieve
+         * the keyboard layout again later using
+         * {@link InputManager#getKeyboardLayout(String)}.
+         *
+         * @return The keyboard layout descriptor.
+         */
+        public String getDescriptor() {
+            return mDescriptor;
+        }
+
+        /**
+         * Gets the keyboard layout descriptive label to show in the user interface.
+         * @return The keyboard layout descriptive label.
+         */
+        public String getLabel() {
+            return mLabel;
+        }
+
+        /**
+         * Loads the key character map associated with the keyboard layout.
+         *
+         * @param pm The package manager.
+         * @return The key character map, or null if it could not be loaded for any reason.
+         */
+        public KeyCharacterMap loadKeyCharacterMap(PackageManager pm) {
+            if (pm == null) {
+                throw new IllegalArgumentException("pm must not be null");
+            }
+
+            if (mKeyCharacterMap == null) {
+                KeyboardLayoutDescriptor d = parseKeyboardLayoutDescriptor(mDescriptor);
+                if (d == null) {
+                    Log.e(TAG, "Could not load key character map '" + mDescriptor
+                            + "' because the descriptor could not be parsed.");
+                    return null;
+                }
+
+                CharSequence cs = pm.getText(d.packageName, mKeyCharacterMapResId, null);
+                if (cs == null) {
+                    Log.e(TAG, "Could not load key character map '" + mDescriptor
+                            + "' because its associated resource could not be loaded.");
+                    return null;
+                }
+
+                try {
+                    mKeyCharacterMap = KeyCharacterMap.load(cs);
+                } catch (UnavailableException ex) {
+                    Log.e(TAG, "Could not load key character map '" + mDescriptor
+                            + "' due to an error while parsing.", ex);
+                    return null;
+                }
+            }
+            return mKeyCharacterMap;
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeString(mDescriptor);
+            dest.writeString(mLabel);
+            dest.writeInt(mKeyCharacterMapResId);
+        }
+
+        @Override
+        public int compareTo(KeyboardLayout another) {
+            return mLabel.compareToIgnoreCase(another.mLabel);
+        }
+
+        @Override
+        public String toString() {
+            return mLabel;
+        }
+    }
+
+    private static final class KeyboardLayoutDescriptor {
+        public String packageName;
+        public String receiverName;
+        public String keyboardLayoutName;
+    }
+}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 2eef8f4..de16985 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -20,6 +20,7 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.content.Context;
 import android.os.Binder;
 import android.os.Build.VERSION_CODES;
 import android.os.RemoteException;
@@ -610,6 +611,11 @@
         mService = checkNotNull(service, "missing IConnectivityManager");
     }
 
+    /** {@hide} */
+    public static ConnectivityManager from(Context context) {
+        return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+    }
+
     /**
      * {@hide}
      */
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index ee12989..4ac5e76 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -16,9 +16,13 @@
 
 package android.net;
 
+import static android.net.ConnectivityManager.TYPE_WIFI;
+import static android.net.ConnectivityManager.getNetworkTypeName;
 import static android.net.ConnectivityManager.isNetworkTypeMobile;
 
 import android.content.Context;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
 import android.os.Build;
 import android.telephony.TelephonyManager;
 
@@ -42,18 +46,21 @@
     final int mType;
     final int mSubType;
     final String mSubscriberId;
+    final String mNetworkId;
     final boolean mRoaming;
 
-    public NetworkIdentity(int type, int subType, String subscriberId, boolean roaming) {
-        this.mType = type;
-        this.mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType;
-        this.mSubscriberId = subscriberId;
-        this.mRoaming = roaming;
+    public NetworkIdentity(
+            int type, int subType, String subscriberId, String networkId, boolean roaming) {
+        mType = type;
+        mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType;
+        mSubscriberId = subscriberId;
+        mNetworkId = networkId;
+        mRoaming = roaming;
     }
 
     @Override
     public int hashCode() {
-        return Objects.hashCode(mType, mSubType, mSubscriberId, mRoaming);
+        return Objects.hashCode(mType, mSubType, mSubscriberId, mNetworkId, mRoaming);
     }
 
     @Override
@@ -61,27 +68,34 @@
         if (obj instanceof NetworkIdentity) {
             final NetworkIdentity ident = (NetworkIdentity) obj;
             return mType == ident.mType && mSubType == ident.mSubType && mRoaming == ident.mRoaming
-                    && Objects.equal(mSubscriberId, ident.mSubscriberId);
+                    && Objects.equal(mSubscriberId, ident.mSubscriberId)
+                    && Objects.equal(mNetworkId, ident.mNetworkId);
         }
         return false;
     }
 
     @Override
     public String toString() {
-        final String typeName = ConnectivityManager.getNetworkTypeName(mType);
-        final String subTypeName;
+        final StringBuilder builder = new StringBuilder("[");
+        builder.append("type=").append(getNetworkTypeName(mType));
+        builder.append(", subType=");
         if (COMBINE_SUBTYPE_ENABLED) {
-            subTypeName = "COMBINED";
+            builder.append("COMBINED");
         } else if (ConnectivityManager.isNetworkTypeMobile(mType)) {
-            subTypeName = TelephonyManager.getNetworkTypeName(mSubType);
+            builder.append(TelephonyManager.getNetworkTypeName(mSubType));
         } else {
-            subTypeName = Integer.toString(mSubType);
+            builder.append(mSubType);
         }
-
-        final String scrubSubscriberId = scrubSubscriberId(mSubscriberId);
-        final String roaming = mRoaming ? ", ROAMING" : "";
-        return "[type=" + typeName + ", subType=" + subTypeName + ", subscriberId="
-                + scrubSubscriberId + roaming + "]";
+        if (mSubscriberId != null) {
+            builder.append(", subscriberId=").append(scrubSubscriberId(mSubscriberId));
+        }
+        if (mNetworkId != null) {
+            builder.append(", networkId=").append(mNetworkId);
+        }
+        if (mRoaming) {
+            builder.append(", ROAMING");
+        }
+        return builder.append("]").toString();
     }
 
     public int getType() {
@@ -96,6 +110,10 @@
         return mSubscriberId;
     }
 
+    public String getNetworkId() {
+        return mNetworkId;
+    }
+
     public boolean getRoaming() {
         return mRoaming;
     }
@@ -106,8 +124,11 @@
     public static String scrubSubscriberId(String subscriberId) {
         if ("eng".equals(Build.TYPE)) {
             return subscriberId;
+        } else if (subscriberId != null) {
+            // TODO: parse this as MCC+MNC instead of hard-coding
+            return subscriberId.substring(0, Math.min(6, subscriberId.length())) + "...";
         } else {
-            return subscriberId != null ? "valid" : "null";
+            return "null";
         }
     }
 
@@ -122,8 +143,10 @@
         // TODO: consider moving subscriberId over to LinkCapabilities, so it
         // comes from an authoritative source.
 
-        final String subscriberId;
-        final boolean roaming;
+        String subscriberId = null;
+        String networkId = null;
+        boolean roaming = false;
+
         if (isNetworkTypeMobile(type)) {
             final TelephonyManager telephony = (TelephonyManager) context.getSystemService(
                     Context.TELEPHONY_SERVICE);
@@ -133,10 +156,13 @@
             } else {
                 subscriberId = telephony.getSubscriberId();
             }
-        } else {
-            subscriberId = null;
-            roaming = false;
+
+        } else if (type == TYPE_WIFI) {
+            final WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+            final WifiInfo info = wifi.getConnectionInfo();
+            networkId = info != null ? info.getSSID() : null;
         }
-        return new NetworkIdentity(type, subType, subscriberId, roaming);
+
+        return new NetworkIdentity(type, subType, subscriberId, networkId, roaming);
     }
 }
diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java
index c1f58a3..441db7a 100644
--- a/core/java/android/net/NetworkPolicy.java
+++ b/core/java/android/net/NetworkPolicy.java
@@ -30,6 +30,7 @@
  * @hide
  */
 public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
+    public static final int CYCLE_NONE = -1;
     public static final long WARNING_DISABLED = -1;
     public static final long LIMIT_DISABLED = -1;
     public static final long SNOOZE_NEVER = -1;
@@ -123,6 +124,13 @@
         lastLimitSnooze = SNOOZE_NEVER;
     }
 
+    /**
+     * Test if this policy has a cycle defined, after which usage should reset.
+     */
+    public boolean hasCycle() {
+        return cycleDay != CYCLE_NONE;
+    }
+
     @Override
     public int compareTo(NetworkPolicy another) {
         if (another == null || another.limitBytes == LIMIT_DISABLED) {
@@ -159,10 +167,17 @@
 
     @Override
     public String toString() {
-        return "NetworkPolicy[" + template + "]: cycleDay=" + cycleDay + ", cycleTimezone="
-                + cycleTimezone + ", warningBytes=" + warningBytes + ", limitBytes=" + limitBytes
-                + ", lastWarningSnooze=" + lastWarningSnooze + ", lastLimitSnooze="
-                + lastLimitSnooze + ", metered=" + metered + ", inferred=" + inferred;
+        final StringBuilder builder = new StringBuilder("NetworkPolicy");
+        builder.append("[").append(template).append("]:");
+        builder.append(" cycleDay=").append(cycleDay);
+        builder.append(", cycleTimezone=").append(cycleTimezone);
+        builder.append(", warningBytes=").append(warningBytes);
+        builder.append(", limitBytes=").append(limitBytes);
+        builder.append(", lastWarningSnooze=").append(lastWarningSnooze);
+        builder.append(", lastLimitSnooze=").append(lastLimitSnooze);
+        builder.append(", metered=").append(metered);
+        builder.append(", inferred=").append(inferred);
+        return builder.toString();
     }
 
     public static final Creator<NetworkPolicy> CREATOR = new Creator<NetworkPolicy>() {
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index c09c676..2b36131 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -17,6 +17,7 @@
 package android.net;
 
 import static android.content.pm.PackageManager.GET_SIGNATURES;
+import static android.net.NetworkPolicy.CYCLE_NONE;
 import static android.text.format.Time.MONTH_DAY;
 
 import android.content.Context;
@@ -66,27 +67,10 @@
         mService = service;
     }
 
-    public static NetworkPolicyManager getSystemService(Context context) {
+    public static NetworkPolicyManager from(Context context) {
         return (NetworkPolicyManager) context.getSystemService(Context.NETWORK_POLICY_SERVICE);
     }
 
-    /** {@hide} */
-    public void setNetworkPolicies(NetworkPolicy[] policies) {
-        try {
-            mService.setNetworkPolicies(policies);
-        } catch (RemoteException e) {
-        }
-    }
-
-    /** {@hide} */
-    public NetworkPolicy[] getNetworkPolicies() {
-        try {
-            return mService.getNetworkPolicies();
-        } catch (RemoteException e) {
-            return null;
-        }
-    }
-
     /**
      * Set policy flags for specific application.
      *
@@ -122,6 +106,36 @@
         }
     }
 
+    public void setNetworkPolicies(NetworkPolicy[] policies) {
+        try {
+            mService.setNetworkPolicies(policies);
+        } catch (RemoteException e) {
+        }
+    }
+
+    public NetworkPolicy[] getNetworkPolicies() {
+        try {
+            return mService.getNetworkPolicies();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    public void setRestrictBackground(boolean restrictBackground) {
+        try {
+            mService.setRestrictBackground(restrictBackground);
+        } catch (RemoteException e) {
+        }
+    }
+
+    public boolean getRestrictBackground() {
+        try {
+            return mService.getRestrictBackground();
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
     /**
      * Compute the last cycle boundary for the given {@link NetworkPolicy}. For
      * example, if cycle day is 20th, and today is June 15th, it will return May
@@ -131,6 +145,10 @@
      * @hide
      */
     public static long computeLastCycleBoundary(long currentTime, NetworkPolicy policy) {
+        if (policy.cycleDay == CYCLE_NONE) {
+            throw new IllegalArgumentException("Unable to compute boundary without cycleDay");
+        }
+
         final Time now = new Time(policy.cycleTimezone);
         now.set(currentTime);
 
@@ -157,6 +175,10 @@
 
     /** {@hide} */
     public static long computeNextCycleBoundary(long currentTime, NetworkPolicy policy) {
+        if (policy.cycleDay == CYCLE_NONE) {
+            throw new IllegalArgumentException("Unable to compute boundary without cycleDay");
+        }
+
         final Time now = new Time(policy.cycleTimezone);
         now.set(currentTime);
 
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index e1fbdcc..50432a1 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -43,15 +43,10 @@
  */
 public class NetworkTemplate implements Parcelable {
 
-    /** {@hide} */
     public static final int MATCH_MOBILE_ALL = 1;
-    /** {@hide} */
     public static final int MATCH_MOBILE_3G_LOWER = 2;
-    /** {@hide} */
     public static final int MATCH_MOBILE_4G = 3;
-    /** {@hide} */
     public static final int MATCH_WIFI = 4;
-    /** {@hide} */
     public static final int MATCH_ETHERNET = 5;
 
     /**
@@ -65,37 +60,50 @@
     }
 
     /**
-     * Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style
-     * networks together. Only uses statistics for requested IMSI.
+     * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
+     * the given IMSI.
      */
     public static NetworkTemplate buildTemplateMobileAll(String subscriberId) {
-        return new NetworkTemplate(MATCH_MOBILE_ALL, subscriberId);
+        return new NetworkTemplate(MATCH_MOBILE_ALL, subscriberId, null);
     }
 
     /**
-     * Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style
-     * networks together that roughly meet a "3G" definition, or lower. Only
-     * uses statistics for requested IMSI.
+     * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
+     * the given IMSI that roughly meet a "3G" definition, or lower.
      */
+    @Deprecated
     public static NetworkTemplate buildTemplateMobile3gLower(String subscriberId) {
-        return new NetworkTemplate(MATCH_MOBILE_3G_LOWER, subscriberId);
+        return new NetworkTemplate(MATCH_MOBILE_3G_LOWER, subscriberId, null);
     }
 
     /**
-     * Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style
-     * networks together that meet a "4G" definition. Only uses statistics for
-     * requested IMSI.
+     * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
+     * the given IMSI that roughly meet a "4G" definition.
      */
+    @Deprecated
     public static NetworkTemplate buildTemplateMobile4g(String subscriberId) {
-        return new NetworkTemplate(MATCH_MOBILE_4G, subscriberId);
+        return new NetworkTemplate(MATCH_MOBILE_4G, subscriberId, null);
     }
 
     /**
-     * Template to combine all {@link ConnectivityManager#TYPE_WIFI} style
-     * networks together.
+     * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks,
+     * regardless of SSID.
      */
+    public static NetworkTemplate buildTemplateWifiWildcard() {
+        return new NetworkTemplate(MATCH_WIFI, null, null);
+    }
+
+    @Deprecated
     public static NetworkTemplate buildTemplateWifi() {
-        return new NetworkTemplate(MATCH_WIFI, null);
+        return buildTemplateWifiWildcard();
+    }
+
+    /**
+     * Template to match {@link ConnectivityManager#TYPE_WIFI} networks with the
+     * given SSID.
+     */
+    public static NetworkTemplate buildTemplateWifi(String networkId) {
+        return new NetworkTemplate(MATCH_WIFI, null, networkId);
     }
 
     /**
@@ -103,44 +111,53 @@
      * networks together.
      */
     public static NetworkTemplate buildTemplateEthernet() {
-        return new NetworkTemplate(MATCH_ETHERNET, null);
+        return new NetworkTemplate(MATCH_ETHERNET, null, null);
     }
 
     private final int mMatchRule;
     private final String mSubscriberId;
+    private final String mNetworkId;
 
-    /** {@hide} */
-    public NetworkTemplate(int matchRule, String subscriberId) {
-        this.mMatchRule = matchRule;
-        this.mSubscriberId = subscriberId;
+    public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
+        mMatchRule = matchRule;
+        mSubscriberId = subscriberId;
+        mNetworkId = networkId;
     }
 
     private NetworkTemplate(Parcel in) {
         mMatchRule = in.readInt();
         mSubscriberId = in.readString();
+        mNetworkId = in.readString();
     }
 
-    /** {@inheritDoc} */
+    @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(mMatchRule);
         dest.writeString(mSubscriberId);
+        dest.writeString(mNetworkId);
     }
 
-    /** {@inheritDoc} */
+    @Override
     public int describeContents() {
         return 0;
     }
 
     @Override
     public String toString() {
-        final String scrubSubscriberId = scrubSubscriberId(mSubscriberId);
-        return "NetworkTemplate: matchRule=" + getMatchRuleName(mMatchRule) + ", subscriberId="
-                + scrubSubscriberId;
+        final StringBuilder builder = new StringBuilder("NetworkTemplate: ");
+        builder.append("matchRule=").append(getMatchRuleName(mMatchRule));
+        if (mSubscriberId != null) {
+            builder.append(", subscriberId=").append(scrubSubscriberId(mSubscriberId));
+        }
+        if (mNetworkId != null) {
+            builder.append(", networkId=").append(mNetworkId);
+        }
+        return builder.toString();
     }
 
     @Override
     public int hashCode() {
-        return Objects.hashCode(mMatchRule, mSubscriberId);
+        return Objects.hashCode(mMatchRule, mSubscriberId, mNetworkId);
     }
 
     @Override
@@ -148,21 +165,24 @@
         if (obj instanceof NetworkTemplate) {
             final NetworkTemplate other = (NetworkTemplate) obj;
             return mMatchRule == other.mMatchRule
-                    && Objects.equal(mSubscriberId, other.mSubscriberId);
+                    && Objects.equal(mSubscriberId, other.mSubscriberId)
+                    && Objects.equal(mNetworkId, other.mNetworkId);
         }
         return false;
     }
 
-    /** {@hide} */
     public int getMatchRule() {
         return mMatchRule;
     }
 
-    /** {@hide} */
     public String getSubscriberId() {
         return mSubscriberId;
     }
 
+    public String getNetworkId() {
+        return mNetworkId;
+    }
+
     /**
      * Test if given {@link NetworkIdentity} matches this template.
      */
@@ -237,8 +257,13 @@
     private boolean matchesWifi(NetworkIdentity ident) {
         switch (ident.mType) {
             case TYPE_WIFI:
+                if (mNetworkId == null) {
+                    return true;
+                } else {
+                    return Objects.equal(mNetworkId, ident.mNetworkId);
+                }
             case TYPE_WIFI_P2P:
-                return true;
+                return mNetworkId == null;
             default:
                 return false;
         }
@@ -279,10 +304,12 @@
     }
 
     public static final Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() {
+        @Override
         public NetworkTemplate createFromParcel(Parcel in) {
             return new NetworkTemplate(in);
         }
 
+        @Override
         public NetworkTemplate[] newArray(int size) {
             return new NetworkTemplate[size];
         }
diff --git a/core/java/android/net/nsd/DnsSdServiceInfo.java b/core/java/android/net/nsd/DnsSdServiceInfo.java
new file mode 100644
index 0000000..47d6ec6
--- /dev/null
+++ b/core/java/android/net/nsd/DnsSdServiceInfo.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.nsd;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+
+/**
+ * Defines a service based on DNS service discovery
+ * {@hide}
+ */
+public class DnsSdServiceInfo implements NetworkServiceInfo, Parcelable {
+
+    private String mServiceName;
+
+    private String mRegistrationType;
+
+    private DnsSdTxtRecord mTxtRecord;
+
+    private String mHostname;
+
+    private int mPort;
+
+    DnsSdServiceInfo() {
+    }
+
+    DnsSdServiceInfo(String sn, String rt, DnsSdTxtRecord tr) {
+        mServiceName = sn;
+        mRegistrationType = rt;
+        mTxtRecord = tr;
+    }
+
+    @Override
+    /** @hide */
+    public String getServiceName() {
+        return mServiceName;
+    }
+
+    @Override
+    /** @hide */
+    public void setServiceName(String s) {
+        mServiceName = s;
+    }
+
+    @Override
+    /** @hide */
+    public String getServiceType() {
+        return mRegistrationType;
+    }
+
+    @Override
+    /** @hide */
+    public void setServiceType(String s) {
+        mRegistrationType = s;
+    }
+
+    public DnsSdTxtRecord getTxtRecord() {
+        return mTxtRecord;
+    }
+
+    public void setTxtRecord(DnsSdTxtRecord t) {
+        mTxtRecord = new DnsSdTxtRecord(t);
+    }
+
+    public String getHostName() {
+        return mHostname;
+    }
+
+    public void setHostName(String s) {
+        mHostname = s;
+    }
+
+    public int getPort() {
+        return mPort;
+    }
+
+    public void setPort(int p) {
+        mPort = p;
+    }
+
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+
+        sb.append("name: ").append(mServiceName).
+            append("type: ").append(mRegistrationType).
+            append("txtRecord: ").append(mTxtRecord);
+        return sb.toString();
+    }
+
+    /** Implement the Parcelable interface */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mServiceName);
+        dest.writeString(mRegistrationType);
+        dest.writeParcelable(mTxtRecord, flags);
+        dest.writeString(mHostname);
+        dest.writeInt(mPort);
+    }
+
+    /** Implement the Parcelable interface */
+    public static final Creator<DnsSdServiceInfo> CREATOR =
+        new Creator<DnsSdServiceInfo>() {
+            public DnsSdServiceInfo createFromParcel(Parcel in) {
+                DnsSdServiceInfo info = new DnsSdServiceInfo();
+                info.mServiceName = in.readString();
+                info.mRegistrationType = in.readString();
+                info.mTxtRecord = in.readParcelable(null);
+                info.mHostname = in.readString();
+                info.mPort = in.readInt();
+                return info;
+            }
+
+            public DnsSdServiceInfo[] newArray(int size) {
+                return new DnsSdServiceInfo[size];
+            }
+        };
+
+}
diff --git a/core/java/android/net/nsd/DnsSdTxtRecord.java b/core/java/android/net/nsd/DnsSdTxtRecord.java
new file mode 100644
index 0000000..6d4342c
--- /dev/null
+++ b/core/java/android/net/nsd/DnsSdTxtRecord.java
@@ -0,0 +1,305 @@
+/* -*- Mode: Java; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+ To do:
+ - implement remove()
+ - fix set() to replace existing values
+ */
+
+package android.net.nsd;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+
+/**
+ * This class handles TXT record data for DNS based service discovery as specified at
+ * http://tools.ietf.org/html/draft-cheshire-dnsext-dns-sd-11
+ *
+ * DNS-SD specifies that a TXT record corresponding to an SRV record consist of
+ * a packed array of bytes, each preceded by a length byte. Each string
+ * is an attribute-value pair.
+ *
+ * The DnsSdTxtRecord object stores the entire TXT data as a single byte array, traversing it
+ * as need be to implement its various methods.
+ *
+ * @hide
+ */
+public class DnsSdTxtRecord implements Parcelable {
+    private static final byte mSeperator = '=';
+
+    private byte[] mData;
+
+    /** Constructs a new, empty TXT record. */
+    public DnsSdTxtRecord()  {
+        mData = new byte[0];
+    }
+
+    /** Constructs a new TXT record from a byte array in the standard format. */
+    public DnsSdTxtRecord(byte[] data) {
+        mData = (byte[]) data.clone();
+    }
+
+    /** Copy constructor */
+    public DnsSdTxtRecord(DnsSdTxtRecord src) {
+        if (src != null && src.mData != null) {
+            mData = (byte[]) src.mData.clone();
+        }
+    }
+
+    /**
+     * Set a key/value pair. Setting an existing key will replace its value.
+     * @param key Must be ascii with no '='
+     * @param value matching value to key
+     */
+    public void set(String key, String value) {
+        byte[] keyBytes;
+        byte[] valBytes;
+        int valLen;
+
+        if (value != null) {
+            valBytes = value.getBytes();
+            valLen = valBytes.length;
+        } else {
+            valBytes = null;
+            valLen = 0;
+        }
+
+        try {
+            keyBytes = key.getBytes("US-ASCII");
+        }
+        catch (java.io.UnsupportedEncodingException e) {
+            throw new IllegalArgumentException("key should be US-ASCII");
+        }
+
+        for (int i = 0; i < keyBytes.length; i++) {
+            if (keyBytes[i] == '=') {
+                throw new IllegalArgumentException("= is not a valid character in key");
+            }
+        }
+
+        if (keyBytes.length + valLen >= 255) {
+            throw new IllegalArgumentException("Key and Value length cannot exceed 255 bytes");
+        }
+
+        int currentLoc = remove(key);
+        if (currentLoc == -1)
+            currentLoc = keyCount();
+
+        insert(keyBytes, valBytes, currentLoc);
+    }
+
+    /**
+     * Get a value for a key
+     *
+     * @param key
+     * @return The value associated with the key
+     */
+    public String get(String key) {
+        byte[] val = this.getValue(key);
+        return val != null ? new String(val) : null;
+    }
+
+    /** Remove a key/value pair. If found, returns the index or -1 if not found */
+    public int remove(String key) {
+        int avStart = 0;
+
+        for (int i=0; avStart < mData.length; i++) {
+            int avLen = mData[avStart];
+            if (key.length() <= avLen &&
+                    (key.length() == avLen || mData[avStart + key.length() + 1] == mSeperator)) {
+                String s = new String(mData, avStart + 1, key.length());
+                if (0 == key.compareToIgnoreCase(s)) {
+                    byte[] oldBytes = mData;
+                    mData = new byte[oldBytes.length - avLen - 1];
+                    System.arraycopy(oldBytes, 0, mData, 0, avStart);
+                    System.arraycopy(oldBytes, avStart + avLen + 1, mData, avStart,
+                            oldBytes.length - avStart - avLen - 1);
+                    return i;
+                }
+            }
+            avStart += (0xFF & (avLen + 1));
+        }
+        return -1;
+    }
+
+    /** Return the count of keys */
+    public int keyCount() {
+        int count = 0, nextKey;
+        for (nextKey = 0; nextKey < mData.length; count++) {
+            nextKey += (0xFF & (mData[nextKey] + 1));
+        }
+        return count;
+    }
+
+    /** Return true if key is present, false if not. */
+    public boolean contains(String key) {
+        String s = null;
+        for (int i = 0; null != (s = this.getKey(i)); i++) {
+            if (0 == key.compareToIgnoreCase(s)) return true;
+        }
+        return false;
+    }
+
+    /* Gets the size in bytes */
+    public int size() {
+        return mData.length;
+    }
+
+    /* Gets the raw data in bytes */
+    public byte[] getRawData() {
+        return mData;
+    }
+
+    private void insert(byte[] keyBytes, byte[] value, int index) {
+        byte[] oldBytes = mData;
+        int valLen = (value != null) ? value.length : 0;
+        int insertion = 0;
+        int newLen, avLen;
+
+        for (int i = 0; i < index && insertion < mData.length; i++) {
+            insertion += (0xFF & (mData[insertion] + 1));
+        }
+
+        avLen = keyBytes.length + valLen + (value != null ? 1 : 0);
+        newLen = avLen + oldBytes.length + 1;
+
+        mData = new byte[newLen];
+        System.arraycopy(oldBytes, 0, mData, 0, insertion);
+        int secondHalfLen = oldBytes.length - insertion;
+        System.arraycopy(oldBytes, insertion, mData, newLen - secondHalfLen, secondHalfLen);
+        mData[insertion] = (byte) avLen;
+        System.arraycopy(keyBytes, 0, mData, insertion + 1, keyBytes.length);
+        if (value != null) {
+            mData[insertion + 1 + keyBytes.length] = mSeperator;
+            System.arraycopy(value, 0, mData, insertion + keyBytes.length + 2, valLen);
+        }
+    }
+
+    /** Return a key in the TXT record by zero-based index. Returns null if index exceeds the total number of keys. */
+    private String getKey(int index) {
+        int avStart = 0;
+
+        for (int i=0; i < index && avStart < mData.length; i++) {
+            avStart += mData[avStart] + 1;
+        }
+
+        if (avStart < mData.length) {
+            int avLen = mData[avStart];
+            int aLen = 0;
+
+            for (aLen=0; aLen < avLen; aLen++) {
+                if (mData[avStart + aLen + 1] == mSeperator) break;
+            }
+            return new String(mData, avStart + 1, aLen);
+        }
+        return null;
+    }
+
+    /**
+     * Look up a key in the TXT record by zero-based index and return its value.
+     * Returns null if index exceeds the total number of keys.
+     * Returns null if the key is present with no value.
+     */
+    private byte[] getValue(int index) {
+        int avStart = 0;
+        byte[] value = null;
+
+        for (int i=0; i < index && avStart < mData.length; i++) {
+            avStart += mData[avStart] + 1;
+        }
+
+        if (avStart < mData.length) {
+            int avLen = mData[avStart];
+            int aLen = 0;
+
+            for (aLen=0; aLen < avLen; aLen++) {
+                if (mData[avStart + aLen + 1] == mSeperator) {
+                    value = new byte[avLen - aLen - 1];
+                    System.arraycopy(mData, avStart + aLen + 2, value, 0, avLen - aLen - 1);
+                    break;
+                }
+            }
+        }
+        return value;
+    }
+
+    private String getValueAsString(int index) {
+        byte[] value = this.getValue(index);
+        return value != null ? new String(value) : null;
+    }
+
+    private byte[] getValue(String forKey) {
+        String s = null;
+        int i;
+
+        for (i = 0; null != (s = this.getKey(i)); i++) {
+            if (0 == forKey.compareToIgnoreCase(s)) {
+                return this.getValue(i);
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Return a string representation.
+     * Example : {key1=value1},{key2=value2}..
+     *
+     * For a key say like "key3" with null value
+     * {key1=value1},{key2=value2}{key3}
+     */
+    public String toString() {
+        String a, result = null;
+
+        for (int i = 0; null != (a = this.getKey(i)); i++) {
+            String av =  "{" + a;
+            String val = this.getValueAsString(i);
+            if (val != null)
+                av += "=" + val + "}";
+            else
+                av += "}";
+            if (result == null)
+                result = av;
+            else
+                result = result + ", " + av;
+        }
+        return result != null ? result : "";
+    }
+
+    /** Implement the Parcelable interface */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeByteArray(mData);
+    }
+
+    /** Implement the Parcelable interface */
+    public static final Creator<DnsSdTxtRecord> CREATOR =
+        new Creator<DnsSdTxtRecord>() {
+            public DnsSdTxtRecord createFromParcel(Parcel in) {
+                DnsSdTxtRecord info = new DnsSdTxtRecord();
+                in.readByteArray(info.mData);
+                return info;
+            }
+
+            public DnsSdTxtRecord[] newArray(int size) {
+                return new DnsSdTxtRecord[size];
+            }
+        };
+}
diff --git a/core/java/android/net/nsd/INsdManager.aidl b/core/java/android/net/nsd/INsdManager.aidl
new file mode 100644
index 0000000..077a675
--- /dev/null
+++ b/core/java/android/net/nsd/INsdManager.aidl
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.nsd;
+
+import android.os.Messenger;
+
+/**
+ * Interface that NsdService implements
+ *
+ * {@hide}
+ */
+interface INsdManager
+{
+    Messenger getMessenger();
+}
diff --git a/core/java/android/net/nsd/NetworkServiceInfo.java b/core/java/android/net/nsd/NetworkServiceInfo.java
new file mode 100644
index 0000000..34d83d1
--- /dev/null
+++ b/core/java/android/net/nsd/NetworkServiceInfo.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.nsd;
+
+/**
+ * Interface for a network service.
+ *
+ * {@hide}
+ */
+public interface NetworkServiceInfo {
+
+    String getServiceName();
+    void setServiceName(String s);
+
+    String getServiceType();
+    void setServiceType(String s);
+
+}
diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java
new file mode 100644
index 0000000..a109a98
--- /dev/null
+++ b/core/java/android/net/nsd/NsdManager.java
@@ -0,0 +1,394 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.nsd;
+
+import android.content.Context;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.Messenger;
+import android.util.Log;
+
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.Protocol;
+
+/**
+ * The Network Service Discovery Manager class provides the API for service
+ * discovery. Service discovery enables applications to discover and connect with services
+ * on a network. Example applications include a game application discovering another instance
+ * of the game application or a printer application discovering other printers on a network.
+ *
+ * <p> The API is asynchronous and responses to requests from an application are on listener
+ * callbacks provided by the application. The application needs to do an initialization with
+ * {@link #initialize} before doing any operation.
+ *
+ * <p> Android currently supports DNS based service discovery and it is limited to a local
+ * network with the use of multicast DNS. In future, this class will be
+ * extended to support other service discovery mechanisms.
+ *
+ * Get an instance of this class by calling {@link android.content.Context#getSystemService(String)
+ * Context.getSystemService(Context.NSD_SERVICE)}.
+ * @hide
+ *
+ */
+public class NsdManager {
+    private static final String TAG = "NsdManager";
+    INsdManager mService;
+
+    private static final int BASE = Protocol.BASE_NSD_MANAGER;
+
+    /** @hide */
+    public static final int DISCOVER_SERVICES                       = BASE + 1;
+    /** @hide */
+    public static final int DISCOVER_SERVICES_STARTED               = BASE + 2;
+    /** @hide */
+    public static final int DISCOVER_SERVICES_FAILED                = BASE + 3;
+    /** @hide */
+    public static final int SERVICE_FOUND                           = BASE + 4;
+    /** @hide */
+    public static final int SERVICE_LOST                            = BASE + 5;
+
+    /** @hide */
+    public static final int STOP_DISCOVERY                          = BASE + 6;
+    /** @hide */
+    public static final int STOP_DISCOVERY_FAILED                   = BASE + 7;
+    /** @hide */
+    public static final int STOP_DISCOVERY_SUCCEEDED                = BASE + 8;
+
+    /** @hide */
+    public static final int REGISTER_SERVICE                        = BASE + 9;
+    /** @hide */
+    public static final int REGISTER_SERVICE_FAILED                 = BASE + 10;
+    /** @hide */
+    public static final int REGISTER_SERVICE_SUCCEEDED              = BASE + 11;
+
+    /** @hide */
+    public static final int UPDATE_SERVICE                          = BASE + 12;
+    /** @hide */
+    public static final int UPDATE_SERVICE_FAILED                   = BASE + 13;
+    /** @hide */
+    public static final int UPDATE_SERVICE_SUCCEEDED                = BASE + 14;
+
+    /** @hide */
+    public static final int RESOLVE_SERVICE                         = BASE + 15;
+    /** @hide */
+    public static final int RESOLVE_SERVICE_FAILED                  = BASE + 16;
+    /** @hide */
+    public static final int RESOLVE_SERVICE_SUCCEEDED               = BASE + 17;
+
+    /**
+     * Create a new Nsd instance. Applications use
+     * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
+     * {@link android.content.Context#NSD_SERVICE Context.NSD_SERVICE}.
+     * @param service the Binder interface
+     * @hide - hide this because it takes in a parameter of type INsdManager, which
+     * is a system private class.
+     */
+    public NsdManager(INsdManager service) {
+        mService = service;
+    }
+
+    /**
+     * Indicates that the operation failed due to an internal error.
+     */
+    public static final int ERROR               = 0;
+
+    /**
+     * Indicates that the operation failed because service discovery is unsupported on the device.
+     */
+    public static final int UNSUPPORTED         = 1;
+
+    /**
+     * Indicates that the operation failed because the framework is busy and
+     * unable to service the request
+     */
+    public static final int BUSY                = 2;
+
+    /** Interface for callback invocation when framework channel is connected or lost */
+    public interface ChannelListener {
+        public void onChannelConnected(Channel c);
+        /**
+         * The channel to the framework has been disconnected.
+         * Application could try re-initializing using {@link #initialize}
+         */
+        public void onChannelDisconnected();
+    }
+
+    public interface ActionListener {
+
+        public void onFailure(int errorCode);
+
+        public void onSuccess();
+    }
+
+    public interface DnsSdDiscoveryListener {
+
+        public void onFailure(int errorCode);
+
+        public void onStarted(String registrationType);
+
+        public void onServiceFound(DnsSdServiceInfo serviceInfo);
+
+        public void onServiceLost(DnsSdServiceInfo serviceInfo);
+
+    }
+
+    public interface DnsSdRegisterListener {
+
+        public void onFailure(int errorCode);
+
+        public void onServiceRegistered(int registeredId, DnsSdServiceInfo serviceInfo);
+    }
+
+    public interface DnsSdUpdateRegistrationListener {
+
+        public void onFailure(int errorCode);
+
+        public void onServiceUpdated(int registeredId, DnsSdTxtRecord txtRecord);
+    }
+
+    public interface DnsSdResolveListener {
+
+        public void onFailure(int errorCode);
+
+        public void onServiceResolved(DnsSdServiceInfo serviceInfo);
+    }
+
+    /**
+     * A channel that connects the application to the NetworkService framework.
+     * Most service operations require a Channel as an argument. An instance of Channel is obtained
+     * by doing a call on {@link #initialize}
+     */
+    public static class Channel {
+        Channel(Looper looper, ChannelListener l) {
+            mAsyncChannel = new AsyncChannel();
+            mHandler = new ServiceHandler(looper);
+            mChannelListener = l;
+        }
+        private ChannelListener mChannelListener;
+        private DnsSdDiscoveryListener mDnsSdDiscoveryListener;
+        private ActionListener mDnsSdStopDiscoveryListener;
+        private DnsSdRegisterListener mDnsSdRegisterListener;
+        private DnsSdUpdateRegistrationListener mDnsSdUpdateListener;
+        private DnsSdResolveListener mDnsSdResolveListener;
+
+        AsyncChannel mAsyncChannel;
+        ServiceHandler mHandler;
+        class ServiceHandler extends Handler {
+            ServiceHandler(Looper looper) {
+                super(looper);
+            }
+
+            @Override
+            public void handleMessage(Message message) {
+                switch (message.what) {
+                    case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
+                        mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
+                        break;
+                    case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
+                        if (mChannelListener != null) {
+                            mChannelListener.onChannelConnected(Channel.this);
+                        }
+                        break;
+                    case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
+                        if (mChannelListener != null) {
+                            mChannelListener.onChannelDisconnected();
+                            mChannelListener = null;
+                        }
+                        break;
+                    case DISCOVER_SERVICES_STARTED:
+                        if (mDnsSdDiscoveryListener != null) {
+                            mDnsSdDiscoveryListener.onStarted((String) message.obj);
+                        }
+                        break;
+                    case DISCOVER_SERVICES_FAILED:
+                        if (mDnsSdDiscoveryListener != null) {
+                            mDnsSdDiscoveryListener.onFailure(message.arg1);
+                        }
+                        break;
+                    case SERVICE_FOUND:
+                        if (mDnsSdDiscoveryListener != null) {
+                            mDnsSdDiscoveryListener.onServiceFound(
+                                    (DnsSdServiceInfo) message.obj);
+                        }
+                        break;
+                    case SERVICE_LOST:
+                        if (mDnsSdDiscoveryListener != null) {
+                            mDnsSdDiscoveryListener.onServiceLost(
+                                    (DnsSdServiceInfo) message.obj);
+                        }
+                        break;
+                    case STOP_DISCOVERY_FAILED:
+                        if (mDnsSdStopDiscoveryListener != null) {
+                            mDnsSdStopDiscoveryListener.onFailure(message.arg1);
+                        }
+                        break;
+                    case STOP_DISCOVERY_SUCCEEDED:
+                        if (mDnsSdStopDiscoveryListener != null) {
+                            mDnsSdStopDiscoveryListener.onSuccess();
+                        }
+                        break;
+                    case REGISTER_SERVICE_FAILED:
+                        if (mDnsSdRegisterListener != null) {
+                            mDnsSdRegisterListener.onFailure(message.arg1);
+                        }
+                        break;
+                    case REGISTER_SERVICE_SUCCEEDED:
+                        if (mDnsSdRegisterListener != null) {
+                            mDnsSdRegisterListener.onServiceRegistered(message.arg1,
+                                    (DnsSdServiceInfo) message.obj);
+                        }
+                        break;
+                    case UPDATE_SERVICE_FAILED:
+                        if (mDnsSdUpdateListener != null) {
+                            mDnsSdUpdateListener.onFailure(message.arg1);
+                        }
+                        break;
+                    case UPDATE_SERVICE_SUCCEEDED:
+                        if (mDnsSdUpdateListener != null) {
+                            mDnsSdUpdateListener.onServiceUpdated(message.arg1,
+                                    (DnsSdTxtRecord) message.obj);
+                        }
+                        break;
+                    case RESOLVE_SERVICE_FAILED:
+                        if (mDnsSdResolveListener != null) {
+                            mDnsSdResolveListener.onFailure(message.arg1);
+                        }
+                        break;
+                    case RESOLVE_SERVICE_SUCCEEDED:
+                        if (mDnsSdResolveListener != null) {
+                            mDnsSdResolveListener.onServiceResolved(
+                                    (DnsSdServiceInfo) message.obj);
+                        }
+                        break;
+                    default:
+                        Log.d(TAG, "Ignored " + message);
+                        break;
+                }
+            }
+        }
+   }
+
+    /**
+     * Registers the application with the service discovery framework. This function
+     * must be the first to be called before any other operations are performed. No service
+     * discovery operations must be performed until the ChannelListener callback notifies
+     * that the channel is connected
+     *
+     * @param srcContext is the context of the source
+     * @param srcLooper is the Looper on which the callbacks are receivied
+     * @param listener for callback at loss of framework communication.
+     */
+    public void initialize(Context srcContext, Looper srcLooper, ChannelListener listener) {
+        Messenger messenger = getMessenger();
+        if (messenger == null) throw new RuntimeException("Failed to initialize");
+        if (listener == null) throw new IllegalArgumentException("ChannelListener cannot be null");
+
+        Channel c = new Channel(srcLooper, listener);
+        c.mAsyncChannel.connect(srcContext, c.mHandler, messenger);
+    }
+
+    /**
+     * Set the listener for service discovery. Can be null.
+     */
+    public void setDiscoveryListener(Channel c, DnsSdDiscoveryListener b) {
+        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+        c.mDnsSdDiscoveryListener = b;
+    }
+
+    /**
+     * Set the listener for stop service discovery. Can be null.
+     */
+    public void setStopDiscoveryListener(Channel c, ActionListener a) {
+        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+        c.mDnsSdStopDiscoveryListener = a;
+    }
+
+    /**
+     * Set the listener for service registration. Can be null.
+     */
+    public void setRegisterListener(Channel c, DnsSdRegisterListener b) {
+        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+        c.mDnsSdRegisterListener = b;
+    }
+
+    /**
+     * Set the listener for service registration. Can be null.
+     */
+    public void setUpdateRegistrationListener(Channel c, DnsSdUpdateRegistrationListener b) {
+        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+        c.mDnsSdUpdateListener = b;
+    }
+
+    /**
+     * Set the listener for service resolution. Can be null.
+     */
+    public void setResolveListener(Channel c, DnsSdResolveListener b) {
+        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+        c.mDnsSdResolveListener = b;
+    }
+
+    public void registerService(Channel c, DnsSdServiceInfo serviceInfo) {
+        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+        if (serviceInfo == null) throw new IllegalArgumentException("Null serviceInfo");
+        c.mAsyncChannel.sendMessage(REGISTER_SERVICE, serviceInfo);
+    }
+
+    public void updateService(Channel c, int registeredId, DnsSdTxtRecord txtRecord) {
+        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+        c.mAsyncChannel.sendMessage(UPDATE_SERVICE, registeredId, 0, txtRecord);
+    }
+
+    public void discoverServices(Channel c, String serviceType) {
+        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+        if (c.mDnsSdDiscoveryListener == null) throw new
+                IllegalStateException("Discovery listener needs to be set first");
+        DnsSdServiceInfo s = new DnsSdServiceInfo();
+        s.setServiceType(serviceType);
+        c.mAsyncChannel.sendMessage(DISCOVER_SERVICES, s);
+    }
+
+    public void stopServiceDiscovery(Channel c) {
+        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+        c.mAsyncChannel.sendMessage(STOP_DISCOVERY);
+    }
+
+    public void resolveService(Channel c, DnsSdServiceInfo serviceInfo) {
+        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+        if (serviceInfo == null) throw new IllegalArgumentException("Null serviceInfo");
+        if (c.mDnsSdResolveListener == null) throw new
+                IllegalStateException("Resolve listener needs to be set first");
+        c.mAsyncChannel.sendMessage(RESOLVE_SERVICE, serviceInfo);
+    }
+
+    /**
+     * Get a reference to NetworkService handler. This is used to establish
+     * an AsyncChannel communication with the service
+     *
+     * @return Messenger pointing to the NetworkService handler
+     */
+    private Messenger getMessenger() {
+        try {
+            return mService.getMessenger();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+}
diff --git a/core/java/android/nfc/INdefPushCallback.aidl b/core/java/android/nfc/INdefPushCallback.aidl
index e60a5b0..4e79822 100644
--- a/core/java/android/nfc/INdefPushCallback.aidl
+++ b/core/java/android/nfc/INdefPushCallback.aidl
@@ -17,6 +17,7 @@
 package android.nfc;
 
 import android.nfc.NdefMessage;
+import android.net.Uri;
 
 /**
  * @hide
@@ -24,5 +25,7 @@
 interface INdefPushCallback
 {
     NdefMessage createMessage();
+    Uri getUri();
+    String getMimeType();
     void onNdefPushComplete();
 }
diff --git a/core/java/android/nfc/INfcTag.aidl b/core/java/android/nfc/INfcTag.aidl
index 2223255..3ac1dcc 100644
--- a/core/java/android/nfc/INfcTag.aidl
+++ b/core/java/android/nfc/INfcTag.aidl
@@ -45,4 +45,5 @@
     void resetTimeouts();
     boolean canMakeReadOnly(int ndefType);
     int getMaxTransceiveLength(int technology);
+    boolean getExtendedLengthApdusSupported();
 }
diff --git a/core/java/android/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java
index 2c73056..f80dae4 100644
--- a/core/java/android/nfc/NfcActivityManager.java
+++ b/core/java/android/nfc/NfcActivityManager.java
@@ -18,6 +18,7 @@
 
 import android.app.Activity;
 import android.app.Application;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.util.Log;
@@ -107,10 +108,16 @@
         NdefMessage ndefMessage = null;  // static NDEF message
         NfcAdapter.CreateNdefMessageCallback ndefMessageCallback = null;
         NfcAdapter.OnNdefPushCompleteCallback onNdefPushCompleteCallback = null;
+        Uri uri = null;
+        String mimeType = null;
         public NfcActivityState(Activity activity) {
             if (activity.getWindow().isDestroyed()) {
                 throw new IllegalStateException("activity is already destroyed");
             }
+            // Check if activity is resumed right now, as we will not
+            // immediately get a callback for that.
+            resumed = activity.isResumed();
+
             this.activity = activity;
             registerApplication(activity.getApplication());
         }
@@ -121,12 +128,14 @@
             ndefMessage = null;
             ndefMessageCallback = null;
             onNdefPushCompleteCallback = null;
+            uri = null;
+            mimeType = null;
         }
         @Override
         public String toString() {
             StringBuilder s = new StringBuilder("[").append(" ");
             s.append(ndefMessage).append(" ").append(ndefMessageCallback).append(" ");
-            s.append(onNdefPushCompleteCallback).append("]");
+            s.append(onNdefPushCompleteCallback).append(" ").append(uri).append("]");
             return s.toString();
         }
     }
@@ -175,6 +184,19 @@
         mDefaultEvent = new NfcEvent(mAdapter);
     }
 
+    public void setNdefPushContentUri(Activity activity, String mimeType, Uri uri) {
+        boolean isResumed;
+        synchronized (NfcActivityManager.this) {
+            NfcActivityState state = getActivityState(activity);
+            state.uri = uri;
+            state.mimeType = mimeType;
+            isResumed = state.resumed;
+        }
+        if (isResumed) {
+            requestNfcServiceCallback(true);
+        }
+    }
+
     public void setNdefPushMessage(Activity activity, NdefMessage message) {
         boolean isResumed;
         synchronized (NfcActivityManager.this) {
@@ -249,6 +271,26 @@
 
     /** Callback from NFC service, usually on binder thread */
     @Override
+    public Uri getUri() {
+        synchronized (NfcActivityManager.this) {
+            NfcActivityState state = findResumedActivityState();
+            if (state == null) return null;
+
+            return state.uri;
+        }
+    }
+    /** Callback from NFC service, usually on binder thread */
+    @Override
+    public String getMimeType() {
+        synchronized (NfcActivityManager.this) {
+            NfcActivityState state = findResumedActivityState();
+            if (state == null) return null;
+
+            return state.mimeType;
+        }
+    }
+    /** Callback from NFC service, usually on binder thread */
+    @Override
     public void onNdefPushComplete() {
         NfcAdapter.OnNdefPushCompleteCallback callback;
         synchronized (NfcActivityManager.this) {
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index b7a7bd5..917751c 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -28,6 +28,7 @@
 import android.content.IntentFilter;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
+import android.net.Uri;
 import android.nfc.tech.MifareClassic;
 import android.nfc.tech.Ndef;
 import android.nfc.tech.NfcA;
@@ -555,6 +556,18 @@
         }
     }
 
+    //TODO: Consider a callback alternative
+    //TOOD: See if we get rid of mimeType
+    //TODO: make sure NFC service has permission for URI
+    //TODO: javadoc
+    /** @hide */
+    public void setBeamPushUri(String mimeType, Uri uri, Activity activity) {
+        if (activity == null) {
+            throw new NullPointerException("activity cannot be null");
+        }
+        mNfcActivityManager.setNdefPushContentUri(activity, mimeType, uri);
+    }
+
     /**
      * Set a static {@link NdefMessage} to send using Android Beam (TM).
      *
@@ -580,7 +593,18 @@
      * and/or {@link #setNdefPushMessageCallback} is called with a null callback,
      * then NDEF push will be completely disabled for the specified activity(s).
      * This also disables any default NDEF message the Android OS would have
-     * otherwise sent on your behalf.
+     * otherwise sent on your behalf for those activity(s).
+     *
+     * <p>If you want to prevent the Android OS from sending default NDEF
+     * messages completely (for all activities), you can include a
+     * <code><meta-data></code> element inside the <code><application></code>
+     * element of your AndroidManifest.xml file, like this:
+     * <pre>{@code
+     *  <application ...>
+     *      <meta-data android:name="android.nfc.disable_beam_default"
+     *          android:value="true" />
+     *  </application>
+     * }</pre>
      *
      * <p>The API allows for multiple activities to be specified at a time,
      * but it is strongly recommended to just register one at a time,
@@ -664,7 +688,18 @@
      * and/or {@link #setNdefPushMessageCallback} is called with a null callback,
      * then NDEF push will be completely disabled for the specified activity(s).
      * This also disables any default NDEF message the Android OS would have
-     * otherwise sent on your behalf.
+     * otherwise sent on your behalf for those activity(s).
+     *
+     * <p>If you want to prevent the Android OS from sending default NDEF
+     * messages completely (for all activities), you can include a
+     * <code><meta-data></code> element inside the <code><application></code>
+     * element of your AndroidManifest.xml file, like this:
+     * <pre>{@code
+     *  <application ...>
+     *      <meta-data android:name="android.nfc.disable_beam_default"
+     *          android:value="true" />
+     *  </application>
+     * }</pre>
      *
      * <p>The API allows for multiple activities to be specified at a time,
      * but it is strongly recommended to just register one at a time,
diff --git a/core/java/android/nfc/tech/IsoDep.java b/core/java/android/nfc/tech/IsoDep.java
index 1859877..089b159 100644
--- a/core/java/android/nfc/tech/IsoDep.java
+++ b/core/java/android/nfc/tech/IsoDep.java
@@ -179,4 +179,27 @@
     public int getMaxTransceiveLength() {
         return getMaxTransceiveLengthInternal();
     }
+
+    /**
+     * <p>Standard APDUs have a 1-byte length field, allowing a maximum of
+     * 255 payload bytes, which results in a maximum APDU length of 261 bytes.
+     *
+     * <p>Extended length APDUs have a 3-byte length field, allowing 65535
+     * payload bytes.
+     *
+     * <p>Some NFC adapters, like the one used in the Nexus S and the Galaxy Nexus
+     * do not support extended length APDUs. They are expected to be well-supported
+     * in the future though. Use this method to check for extended length APDU
+     * support.
+     *
+     * @return whether the NFC adapter on this device supports extended length APDUs.
+     */
+    public boolean isExtendedLengthApduSupported() {
+        try {
+            return mTag.getTagService().getExtendedLengthApdusSupported();
+        } catch (RemoteException e) {
+            Log.e(TAG, "NFC service dead", e);
+            return false;
+        }
+    }
 }
diff --git a/core/java/android/nfc/tech/MifareClassic.java b/core/java/android/nfc/tech/MifareClassic.java
index 9d1e6a1..8c92288 100644
--- a/core/java/android/nfc/tech/MifareClassic.java
+++ b/core/java/android/nfc/tech/MifareClassic.java
@@ -150,6 +150,7 @@
         mIsEmulated = false;
 
         switch (a.getSak()) {
+        case 0x01:
         case 0x08:
             mType = TYPE_CLASSIC;
             mSize = SIZE_1K;
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index 74a376d..8df4339 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -497,27 +497,30 @@
      * @see #onCreateView(ViewGroup)
      */
     protected void onBindView(View view) {
-        TextView textView = (TextView) view.findViewById(com.android.internal.R.id.title); 
-        if (textView != null) {
-            textView.setText(getTitle());
-        }
-        
-        textView = (TextView) view.findViewById(com.android.internal.R.id.summary);
-        if (textView != null) {
-            final CharSequence summary = getSummary();
-            if (!TextUtils.isEmpty(summary)) {
-                if (textView.getVisibility() != View.VISIBLE) {
-                    textView.setVisibility(View.VISIBLE);
-                }
-                
-                textView.setText(getSummary());
+        final TextView titleView = (TextView) view.findViewById(
+                com.android.internal.R.id.title);
+        if (titleView != null) {
+            final CharSequence title = getTitle();
+            if (!TextUtils.isEmpty(title)) {
+                titleView.setText(title);
+                titleView.setVisibility(View.VISIBLE);
             } else {
-                if (textView.getVisibility() != View.GONE) {
-                    textView.setVisibility(View.GONE);
-                }
+                titleView.setVisibility(View.GONE);
             }
         }
-        
+
+        final TextView summaryView = (TextView) view.findViewById(
+                com.android.internal.R.id.summary);
+        if (summaryView != null) {
+            final CharSequence summary = getSummary();
+            if (!TextUtils.isEmpty(summary)) {
+                summaryView.setText(summary);
+                summaryView.setVisibility(View.VISIBLE);
+            } else {
+                summaryView.setVisibility(View.GONE);
+            }
+        }
+
         ImageView imageView = (ImageView) view.findViewById(com.android.internal.R.id.icon);
         if (imageView != null) {
             if (mIconResId != 0 || mIcon != null) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d74ccb8..371e2a1 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -36,14 +36,19 @@
 import android.net.wifi.WifiManager;
 import android.os.BatteryManager;
 import android.os.Bundle;
+import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.SystemProperties;
+import android.os.UserId;
 import android.speech.tts.TextToSpeech;
 import android.text.TextUtils;
 import android.util.AndroidException;
 import android.util.Log;
 import android.view.WindowOrientationListener;
 
+import com.android.internal.widget.ILockSettings;
+
 import java.net.URISyntaxException;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -1506,13 +1511,22 @@
         public static final String VOLUME_MASTER = "volume_master";
 
         /**
-         * Whether the notifications should use the ring volume (value of 1) or a separate
-         * notification volume (value of 0). In most cases, users will have this enabled so the
-         * notification and ringer volumes will be the same. However, power users can disable this
-         * and use the separate notification volume control.
+         * Master volume mute (int 1 = mute, 0 = not muted).
+         *
+         * @hide
+         */
+        public static final String VOLUME_MASTER_MUTE = "volume_master_mute";
+
+        /**
+         * Whether the notifications should use the ring volume (value of 1) or
+         * a separate notification volume (value of 0). In most cases, users
+         * will have this enabled so the notification and ringer volumes will be
+         * the same. However, power users can disable this and use the separate
+         * notification volume control.
          * <p>
-         * Note: This is a one-off setting that will be removed in the future when there is profile
-         * support. For this reason, it is kept hidden from the public APIs.
+         * Note: This is a one-off setting that will be removed in the future
+         * when there is profile support. For this reason, it is kept hidden
+         * from the public APIs.
          *
          * @hide
          * @deprecated
@@ -2244,6 +2258,16 @@
         // Populated lazily, guarded by class object:
         private static NameValueCache sNameValueCache = null;
 
+        private static ILockSettings sLockSettings = null;
+
+        private static final HashSet<String> MOVED_TO_LOCK_SETTINGS;
+        static {
+            MOVED_TO_LOCK_SETTINGS = new HashSet<String>(3);
+            MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_ENABLED);
+            MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_VISIBLE);
+            MOVED_TO_LOCK_SETTINGS.add(Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED);
+        }
+
         /**
          * Look up a name in the database.
          * @param resolver to access the database with
@@ -2255,6 +2279,19 @@
                 sNameValueCache = new NameValueCache(SYS_PROP_SETTING_VERSION, CONTENT_URI,
                                                      CALL_METHOD_GET_SECURE);
             }
+
+            if (sLockSettings == null) {
+                sLockSettings = ILockSettings.Stub.asInterface(
+                        (IBinder) ServiceManager.getService("lock_settings"));
+            }
+            if (sLockSettings != null && MOVED_TO_LOCK_SETTINGS.contains(name)) {
+                try {
+                    return sLockSettings.getString(name, "0", UserId.getCallingUserId());
+                } catch (RemoteException re) {
+                    // Fall through
+                }
+            }
+
             return sNameValueCache.getString(resolver, name);
         }
 
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
index 33631b7..fba73fbd 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/view/DisplayList.java
@@ -149,6 +149,15 @@
     public abstract void setAlpha(float alpha);
 
     /**
+     * Sets whether the DisplayList renders content which overlaps. Non-overlapping rendering
+     * can use a fast path for alpha that avoids rendering to an offscreen buffer.
+     *
+     * @param hasOverlappingRendering
+     * @see android.view.View#hasOverlappingRendering()
+     */
+    public abstract void setHasOverlappingRendering(boolean hasOverlappingRendering);
+
+    /**
      * Sets the translationX value for the DisplayList
      *
      * @param translationX The translationX value of the DisplayList
diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java
index bc3bce0..f3618eb 100644
--- a/core/java/android/view/GLES20DisplayList.java
+++ b/core/java/android/view/GLES20DisplayList.java
@@ -147,6 +147,15 @@
     }
 
     @Override
+    public void setHasOverlappingRendering(boolean hasOverlappingRendering) {
+        try {
+            nSetHasOverlappingRendering(getNativeDisplayList(), hasOverlappingRendering);
+        } catch (IllegalStateException e) {
+            // invalid DisplayList okay: we'll set current values the next time we render to it
+        }
+    }
+
+    @Override
     public void setTranslationX(float translationX) {
         try {
             nSetTranslationX(getNativeDisplayList(), translationX);
@@ -335,6 +344,8 @@
     private static native void nSetClipChildren(int displayList, boolean clipChildren);
     private static native void nSetApplicationScale(int displayList, float scale);
     private static native void nSetAlpha(int displayList, float alpha);
+    private static native void nSetHasOverlappingRendering(int displayList,
+            boolean hasOverlappingRendering);
     private static native void nSetTranslationX(int displayList, float translationX);
     private static native void nSetTranslationY(int displayList, float translationY);
     private static native void nSetRotation(int displayList, float rotation);
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index b100a0c..b8c692a 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -87,7 +87,7 @@
     /**
      * System property used to enable or disable hardware rendering profiling.
      * The default value of this property is assumed to be false.
-     * 
+     *
      * When profiling is enabled, the adb shell dumpsys gfxinfo command will
      * output extra information about the time taken to execute by the last
      * frames.
@@ -99,6 +99,20 @@
     static final String PROFILE_PROPERTY = "hwui.profile";
 
     /**
+     * System property used to specify the number of frames to be used
+     * when doing hardware rendering profiling.
+     * The default value of this property is #PROFILE_MAX_FRAMES.
+     *
+     * When profiling is enabled, the adb shell dumpsys gfxinfo command will
+     * output extra information about the time taken to execute by the last
+     * frames.
+     *
+     * Possible values:
+     * "60", to set the limit of frames to 60
+     */
+    static final String PROFILE_MAXFRAMES_PROPERTY = "hwui.profile.maxframes";
+
+    /**
      * System property used to debug EGL configuration choice.
      * 
      * Possible values:
@@ -579,7 +593,13 @@
             }
 
             if (mProfileEnabled) {
-                mProfileData = new float[PROFILE_MAX_FRAMES * PROFILE_FRAME_DATA_COUNT];
+                property = SystemProperties.get(PROFILE_MAXFRAMES_PROPERTY,
+                        Integer.toString(PROFILE_MAX_FRAMES));
+                int maxProfileFrames = Integer.valueOf(property);
+                mProfileData = new float[maxProfileFrames * PROFILE_FRAME_DATA_COUNT];
+                for (int i = 0; i < mProfileData.length; i += PROFILE_FRAME_DATA_COUNT) {
+                    mProfileData[i] = mProfileData[i + 1] = mProfileData[i + 2] = -1;
+                }
             } else {
                 mProfileData = null;
             }
@@ -596,9 +616,14 @@
             if (mProfileEnabled) {
                 pw.printf("\n\tDraw\tProcess\tExecute\n");
                 for (int i = 0; i < mProfileData.length; i += PROFILE_FRAME_DATA_COUNT) {
+                    if (mProfileData[i] < 0) {
+                        break;
+                    }
                     pw.printf("\t%3.2f\t%3.2f\t%3.2f\n", mProfileData[i], mProfileData[i + 1],
                             mProfileData[i + 2]);
+                    mProfileData[i] = mProfileData[i + 1] = mProfileData[i + 2] = -1;
                 }
+                mProfileCurrentFrame = mProfileData.length;
             }
         }
 
@@ -1046,10 +1071,6 @@
                                 Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- getDisplayList() took " +
                                         total + "ms");
                             }
-                            if (View.USE_DISPLAY_LIST_PROPERTIES) {
-                                Log.d("DLProperties", "getDisplayList():\t" +
-                                        mProfileData[mProfileCurrentFrame]);
-                            }
                         }
 
                         if (displayList != null) {
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 14cd48f..eb030de 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -62,8 +62,8 @@
     void setForcedDisplaySize(int longDimen, int shortDimen);
     void clearForcedDisplaySize();
 
-    // Is device configured with a hideable status bar or a tablet system bar?
-    boolean canStatusBarHide();
+    // Is the device configured to have a full system bar for larger screens?
+    boolean hasSystemNavBar();
 
     // These can only be called when injecting events to your own window,
     // or by holding the INJECT_EVENTS permission.  These methods may block
@@ -171,8 +171,10 @@
      * @param alwaysSendConfiguration Flag to force a new configuration to
      * be evaluated.  This can be used when there are other parameters in
      * configuration that are changing.
+     * @param forceRelayout If true, the window manager will always do a relayout
+     * of its windows even if the rotation hasn't changed.
      */
-    void updateRotation(boolean alwaysSendConfiguration);
+    void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout);
 
     /**
      * Retrieve the current screen orientation, constants as per
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 8115b36..91e47e6 100755
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -26,7 +26,7 @@
 /**
  * Describes the capabilities of a particular input device.
  * <p>
- * Each input device may support multiple classes of input.  For example, a multifunction
+ * Each input device may support multiple classes of input.  For example, a multi-function
  * keyboard may compose the capabilities of a standard keyboard together with a track pad mouse
  * or other pointing device.
  * </p><p>
@@ -118,7 +118,11 @@
     
     /**
      * The input source is a keyboard.
-     * 
+     *
+     * This source indicates pretty much anything that has buttons.  Use
+     * {@link #getKeyboardType()} to determine whether the keyboard has alphabetic keys
+     * and can be used to enter text.
+     *
      * @see #SOURCE_CLASS_BUTTON
      */
     public static final int SOURCE_KEYBOARD = 0x00000100 | SOURCE_CLASS_BUTTON;
@@ -319,15 +323,37 @@
                     "Could not get input device ids from Window Manager.", ex);
         }
     }
-    
+
     /**
      * Gets the input device id.
+     * <p>
+     * Each input device receives a unique id when it is first configured
+     * by the system.  The input device id may change when the system is restarted or if the
+     * input device is disconnected, reconnected or reconfigured at any time.
+     * If you require a stable identifier for a device that persists across
+     * boots and reconfigurations, use {@link #getDescriptor()}.
+     * </p>
+     *
      * @return The input device id.
      */
     public int getId() {
         return mId;
     }
-    
+
+    /**
+     * Gets the input device descriptor, which is a stable identifier for an input device.
+     * <p>
+     * An input device descriptor uniquely identifies an input device.  Its value
+     * is intended to be persistent across system restarts, and should not change even
+     * if the input device is disconnected, reconnected or reconfigured at any time.
+     * </p>
+     *
+     * @return The input device descriptor.
+     */
+    public String getDescriptor() {
+        return "PLACEHOLDER"; // TODO: implement for real
+    }
+
     /**
      * Gets the name of this input device.
      * @return The input device name.
diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java
index 575af3b..98cce5efe 100644
--- a/core/java/android/view/KeyCharacterMap.java
+++ b/core/java/android/view/KeyCharacterMap.java
@@ -22,6 +22,7 @@
 import android.os.RemoteException;
 import android.util.SparseArray;
 
+import java.io.Reader;
 import java.lang.Character;
 
 /**
@@ -196,6 +197,14 @@
     }
 
     /**
+     * TODO implement this
+     * @hide
+     */
+    public static KeyCharacterMap load(CharSequence contents) {
+        return null;
+    }
+
+    /**
      * Gets the Unicode character generated by the specified key and meta
      * key state combination.
      * <p>
@@ -456,7 +465,8 @@
 
     /**
      * Gets the keyboard type.
-     * Returns {@link #NUMERIC}, {@link #PREDICTIVE}, {@link #ALPHA} or {@link #FULL}.
+     * Returns {@link #NUMERIC}, {@link #PREDICTIVE}, {@link #ALPHA}, {@link #FULL}
+     * or {@link #SPECIAL_FUNCTION}.
      * <p>
      * Different keyboard types have different semantics.  Refer to the documentation
      * associated with the keyboard type constants for details.
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 69d7655..5d7c8cd 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -71,6 +71,7 @@
 import android.widget.ScrollBarDrawable;
 
 import static android.os.Build.VERSION_CODES.*;
+import static java.lang.Math.max;
 
 import com.android.internal.R;
 import com.android.internal.util.Predicate;
@@ -126,7 +127,7 @@
  * example, all views will let you set a listener to be notified when the view
  * gains or loses focus. You can register such a listener using
  * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
- * Other view subclasses offer more specialized listeners. For example, a Button 
+ * Other view subclasses offer more specialized listeners. For example, a Button
  * exposes a listener to notify clients when the button is clicked.</li>
  * <li><strong>Set visibility:</strong> You can hide or show views using
  * {@link #setVisibility(int)}.</li>
@@ -579,6 +580,7 @@
  * @attr ref android.R.styleable#View_duplicateParentState
  * @attr ref android.R.styleable#View_id
  * @attr ref android.R.styleable#View_requiresFadingEdge
+ * @attr ref android.R.styleable#View_fadeScrollbars
  * @attr ref android.R.styleable#View_fadingEdgeLength
  * @attr ref android.R.styleable#View_filterTouchesWhenObscured
  * @attr ref android.R.styleable#View_fitsSystemWindows
@@ -624,6 +626,7 @@
  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
  * @attr ref android.R.styleable#View_soundEffectsEnabled
  * @attr ref android.R.styleable#View_tag
+ * @attr ref android.R.styleable#View_textAlignment
  * @attr ref android.R.styleable#View_transformPivotX
  * @attr ref android.R.styleable#View_transformPivotY
  * @attr ref android.R.styleable#View_translationX
@@ -1827,17 +1830,17 @@
     public static final int TEXT_DIRECTION_LOCALE = 5;
 
     /**
+     * Default text direction is inherited
+     */
+    protected static int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
+
+    /**
      * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
      * @hide
      */
     static final int TEXT_DIRECTION_MASK_SHIFT = 6;
 
     /**
-     * Default text direction is inherited
-     */
-    protected static int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
-
-    /**
      * Mask for use with private flags indicating bits used for text direction.
      * @hide
      */
@@ -1882,6 +1885,113 @@
     static final int TEXT_DIRECTION_RESOLVED_DEFAULT =
             TEXT_DIRECTION_FIRST_STRONG << TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
 
+    /*
+     * Default text alignment. The text alignment of this View is inherited from its parent.
+     * Use with {@link #setTextAlignment(int)}
+     */
+    public static final int TEXT_ALIGNMENT_INHERIT = 0;
+
+    /**
+     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
+     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
+     *
+     * Use with {@link #setTextAlignment(int)}
+     */
+    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
+
+    /**
+     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
+     *
+     * Use with {@link #setTextAlignment(int)}
+     */
+    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
+
+    /**
+     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
+     *
+     * Use with {@link #setTextAlignment(int)}
+     */
+    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
+
+    /**
+     * Center the paragraph, e.g. ALIGN_CENTER.
+     *
+     * Use with {@link #setTextAlignment(int)}
+     */
+    public static final int TEXT_ALIGNMENT_CENTER = 4;
+
+    /**
+     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
+     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
+     *
+     * Use with {@link #setTextAlignment(int)}
+     */
+    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
+
+    /**
+     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
+     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
+     *
+     * Use with {@link #setTextAlignment(int)}
+     */
+    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
+
+    /**
+     * Default text alignment is inherited
+     */
+    protected static int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
+
+    /**
+      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
+      * @hide
+      */
+    static final int TEXT_ALIGNMENT_MASK_SHIFT = 13;
+
+    /**
+      * Mask for use with private flags indicating bits used for text alignment.
+      * @hide
+      */
+    static final int TEXT_ALIGNMENT_MASK = 0x00000007 << TEXT_ALIGNMENT_MASK_SHIFT;
+
+    /**
+     * Array of text direction flags for mapping attribute "textAlignment" to correct
+     * flag value.
+     * @hide
+     */
+    private static final int[] TEXT_ALIGNMENT_FLAGS = {
+            TEXT_ALIGNMENT_INHERIT << TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_GRAVITY << TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_TEXT_START << TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_TEXT_END << TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_CENTER << TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_VIEW_START << TEXT_ALIGNMENT_MASK_SHIFT,
+            TEXT_ALIGNMENT_VIEW_END << TEXT_ALIGNMENT_MASK_SHIFT
+    };
+
+    /**
+     * Indicates whether the view text alignment has been resolved.
+     * @hide
+     */
+    static final int TEXT_ALIGNMENT_RESOLVED = 0x00000008 << TEXT_ALIGNMENT_MASK_SHIFT;
+
+    /**
+     * Bit shift to get the resolved text alignment.
+     * @hide
+     */
+    static final int TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
+
+    /**
+     * Mask for use with private flags indicating bits used for text alignment.
+     * @hide
+     */
+    static final int TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007 << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
+
+    /**
+     * Indicates whether if the view text alignment has been resolved to gravity
+     */
+    public static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT =
+            TEXT_ALIGNMENT_GRAVITY << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
+
 
     /* End of masks for mPrivateFlags2 */
 
@@ -1926,7 +2036,7 @@
      * system UI to enter an unobtrusive "low profile" mode.
      *
      * <p>This is for use in games, book readers, video players, or any other
-     * "immersive" application where the usual system chrome is deemed too distracting. 
+     * "immersive" application where the usual system chrome is deemed too distracting.
      *
      * <p>In low profile mode, the status bar and/or navigation icons may dim.
      *
@@ -1942,7 +2052,7 @@
      * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
      * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
      * those to disappear. This is useful (in conjunction with the
-     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and 
+     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
      * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
      * window flags) for displaying content using every last pixel on the display.
      *
@@ -2339,7 +2449,7 @@
          */
         private int mPrevWidth = -1;
         private int mPrevHeight = -1;
-        
+
         /**
          * The degrees rotation around the vertical axis through the pivot point.
          */
@@ -2546,7 +2656,7 @@
      */
     int mOldHeightMeasureSpec = Integer.MIN_VALUE;
 
-    private Drawable mBGDrawable;
+    private Drawable mBackground;
 
     private int mBackgroundResource;
     private boolean mBackgroundSizeChanged;
@@ -2620,7 +2730,7 @@
 
     /**
      * Set to true when drawing cache is enabled and cannot be created.
-     * 
+     *
      * @hide
      */
     public boolean mCachingFailed;
@@ -2830,19 +2940,6 @@
     private boolean mSendingHoverAccessibilityEvents;
 
     /**
-     * Delegate for injecting accessiblity functionality.
-     */
-    AccessibilityDelegate mAccessibilityDelegate;
-
-    /**
-     * Consistency verifier for debugging purposes.
-     * @hide
-     */
-    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
-            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
-                    new InputEventConsistencyVerifier(this, 0) : null;
-
-    /**
      * Simple constructor to use when creating a view from code.
      *
      * @param context The Context the view is running in, through which it can
@@ -2854,7 +2951,8 @@
         mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
         // Set layout and text direction defaults
         mPrivateFlags2 = (LAYOUT_DIRECTION_DEFAULT << LAYOUT_DIRECTION_MASK_SHIFT) |
-                (TEXT_DIRECTION_DEFAULT << TEXT_DIRECTION_MASK_SHIFT);
+                (TEXT_DIRECTION_DEFAULT << TEXT_DIRECTION_MASK_SHIFT) |
+                (TEXT_ALIGNMENT_DEFAULT << TEXT_ALIGNMENT_MASK_SHIFT);
         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
         setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
         mUserPaddingStart = -1;
@@ -2863,6 +2961,19 @@
     }
 
     /**
+     * Delegate for injecting accessiblity functionality.
+     */
+    AccessibilityDelegate mAccessibilityDelegate;
+
+    /**
+     * Consistency verifier for debugging purposes.
+     * @hide
+     */
+    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
+            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
+                    new InputEventConsistencyVerifier(this, 0) : null;
+
+    /**
      * Constructor that is called when inflating a view from XML. This is called
      * when a view is being constructed from an XML file, supplying attributes
      * that were specified in the XML file. This version uses a default style of
@@ -3222,6 +3333,13 @@
                         mPrivateFlags2 |= TEXT_DIRECTION_FLAGS[textDirection];
                     }
                     break;
+                case R.styleable.View_textAlignment:
+                    // Clear any text alignment flag already set
+                    mPrivateFlags2 &= ~TEXT_ALIGNMENT_MASK;
+                    // Set the text alignment flag depending on the value of the attribute
+                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
+                    mPrivateFlags2 |= TEXT_ALIGNMENT_FLAGS[textAlignment];
+                    break;
             }
         }
 
@@ -3230,7 +3348,7 @@
         setOverScrollMode(overScrollMode);
 
         if (background != null) {
-            setBackgroundDrawable(background);
+            setBackground(background);
         }
 
         // Cache user padding as we cannot fully resolve padding here (we dont have yet the resolved
@@ -3494,6 +3612,11 @@
         }
     }
 
+    private ScrollabilityCache getScrollCache() {
+        initScrollCache();
+        return mScrollCache;
+    }
+
     /**
      * Set the position of the vertical scroll bar. Should be one of
      * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
@@ -3909,8 +4032,9 @@
      * <p>
      * <strong>Note:</strong> When a View clears focus the framework is trying
      * to give focus to the first focusable View from the top. Hence, if this
-     * View is the first from the top that can take focus, then its focus will
-     * not be cleared nor will the focus change callback be invoked.
+     * View is the first from the top that can take focus, then all callbacks
+     * related to clearing focus will be invoked after wich the framework will
+     * give focus to this view.
      * </p>
      */
     public void clearFocus() {
@@ -3927,25 +4051,22 @@
 
             onFocusChanged(false, 0, null);
             refreshDrawableState();
+
+            ensureInputFocusOnFirstFocusable();
         }
     }
 
-    /**
-     * Called to clear the focus of a view that is about to be removed.
-     * Doesn't call clearChildFocus, which prevents this view from taking
-     * focus again before it has been removed from the parent
-     */
-    void clearFocusForRemoval() {
-        if ((mPrivateFlags & FOCUSED) != 0) {
-            mPrivateFlags &= ~FOCUSED;
-
-            onFocusChanged(false, 0, null);
-            refreshDrawableState();
-
-            // The view cleared focus and invoked the callbacks, so  now is the
-            // time to give focus to the the first focusable from the top to
-            // ensure that the gain focus is announced after clear focus.
-            getRootView().requestFocus(FOCUS_FORWARD);
+    void ensureInputFocusOnFirstFocusable() {
+        View root = getRootView();
+        if (root != null) {
+            // Find the first focusble from the top.
+            View next = root.focusSearch(FOCUS_FORWARD);
+            if (next != null) {
+                // Giving focus to the found focusable will not
+                // perform a search since we found a view that is
+                // guaranteed to be able to take focus.
+                next.requestFocus(FOCUS_FORWARD);
+            }
         }
     }
 
@@ -4562,11 +4683,26 @@
     }
 
     /**
+     * Indicates whether this view is one of the set of scrollable containers in
+     * its window.
+     *
+     * @return whether this view is one of the set of scrollable containers in
+     * its window
+     *
+     * @attr ref android.R.styleable#View_isScrollContainer
+     */
+    public boolean isScrollContainer() {
+        return (mPrivateFlags & SCROLL_CONTAINER_ADDED) != 0;
+    }
+
+    /**
      * Change whether this view is one of the set of scrollable containers in
      * its window.  This will be used to determine whether the window can
      * resize or must pan when a soft input area is open -- scrollable
      * containers allow the window to use resize mode since the container
      * will appropriately shrink.
+     *
+     * @attr ref android.R.styleable#View_isScrollContainer
      */
     public void setScrollContainer(boolean isScrollContainer) {
         if (isScrollContainer) {
@@ -4898,7 +5034,7 @@
     @RemotableViewMethod
     public void setVisibility(int visibility) {
         setFlags(visibility, VISIBILITY_MASK);
-        if (mBGDrawable != null) mBGDrawable.setVisible(visibility == VISIBLE, false);
+        if (mBackground != null) mBackground.setVisible(visibility == VISIBLE, false);
     }
 
     /**
@@ -5279,7 +5415,7 @@
      * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
      * the pressed state.
      *
-     * @see #setPressed(boolean) 
+     * @see #setPressed(boolean)
      * @see #isClickable()
      * @see #setClickable(boolean)
      *
@@ -5965,7 +6101,7 @@
     /**
      * Dispatch a hover event.
      * <p>
-     * Do not call this method directly. 
+     * Do not call this method directly.
      * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
      * </p>
      *
@@ -6152,7 +6288,7 @@
      *
      * @param visibility The new visibility of the window.
      *
-     * @see #onWindowVisibilityChanged(int) 
+     * @see #onWindowVisibilityChanged(int)
      */
     public void dispatchWindowVisibilityChanged(int visibility) {
         onWindowVisibilityChanged(visibility);
@@ -6228,7 +6364,7 @@
      *
      * @param newConfig The new resource configuration.
      *
-     * @see #onConfigurationChanged(android.content.res.Configuration) 
+     * @see #onConfigurationChanged(android.content.res.Configuration)
      */
     public void dispatchConfigurationChanged(Configuration newConfig) {
         onConfigurationChanged(newConfig);
@@ -7096,7 +7232,7 @@
 
         if ((changed & DRAW_MASK) != 0) {
             if ((mViewFlags & WILL_NOT_DRAW) != 0) {
-                if (mBGDrawable != null) {
+                if (mBackground != null) {
                     mPrivateFlags &= ~SKIP_DRAW;
                     mPrivateFlags |= ONLY_DRAWS_BACKGROUND;
                 } else {
@@ -7484,39 +7620,39 @@
      * views are drawn) from the camera to this view. The camera's distance
      * affects 3D transformations, for instance rotations around the X and Y
      * axis. If the rotationX or rotationY properties are changed and this view is
-     * large (more than half the size of the screen), it is recommended to always 
+     * large (more than half the size of the screen), it is recommended to always
      * use a camera distance that's greater than the height (X axis rotation) or
      * the width (Y axis rotation) of this view.</p>
-     * 
+     *
      * <p>The distance of the camera from the view plane can have an affect on the
      * perspective distortion of the view when it is rotated around the x or y axis.
      * For example, a large distance will result in a large viewing angle, and there
      * will not be much perspective distortion of the view as it rotates. A short
-     * distance may cause much more perspective distortion upon rotation, and can 
+     * distance may cause much more perspective distortion upon rotation, and can
      * also result in some drawing artifacts if the rotated view ends up partially
      * behind the camera (which is why the recommendation is to use a distance at
      * least as far as the size of the view, if the view is to be rotated.)</p>
-     * 
+     *
      * <p>The distance is expressed in "depth pixels." The default distance depends
      * on the screen density. For instance, on a medium density display, the
      * default distance is 1280. On a high density display, the default distance
      * is 1920.</p>
-     * 
+     *
      * <p>If you want to specify a distance that leads to visually consistent
      * results across various densities, use the following formula:</p>
      * <pre>
      * float scale = context.getResources().getDisplayMetrics().density;
      * view.setCameraDistance(distance * scale);
      * </pre>
-     * 
+     *
      * <p>The density scale factor of a high density display is 1.5,
      * and 1920 = 1280 * 1.5.</p>
-     * 
+     *
      * @param distance The distance in "depth pixels", if negative the opposite
      *        value is used
-     * 
-     * @see #setRotationX(float) 
-     * @see #setRotationY(float) 
+     *
+     * @see #setRotationX(float)
+     * @see #setRotationY(float)
      */
     public void setCameraDistance(float distance) {
         invalidateViewProperty(true, false);
@@ -7541,10 +7677,10 @@
     /**
      * The degrees that the view is rotated around the pivot point.
      *
-     * @see #setRotation(float) 
+     * @see #setRotation(float)
      * @see #getPivotX()
      * @see #getPivotY()
-     * 
+     *
      * @return The degrees of rotation.
      */
     @ViewDebug.ExportedProperty(category = "drawing")
@@ -7557,12 +7693,12 @@
      * result in clockwise rotation.
      *
      * @param rotation The degrees of rotation.
-     * 
-     * @see #getRotation() 
+     *
+     * @see #getRotation()
      * @see #getPivotX()
      * @see #getPivotY()
-     * @see #setRotationX(float) 
-     * @see #setRotationY(float) 
+     * @see #setRotationX(float)
+     * @see #setRotationY(float)
      *
      * @attr ref android.R.styleable#View_rotation
      */
@@ -7586,8 +7722,8 @@
      *
      * @see #getPivotX()
      * @see #getPivotY()
-     * @see #setRotationY(float) 
-     * 
+     * @see #setRotationY(float)
+     *
      * @return The degrees of Y rotation.
      */
     @ViewDebug.ExportedProperty(category = "drawing")
@@ -7599,18 +7735,18 @@
      * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
      * Increasing values result in counter-clockwise rotation from the viewpoint of looking
      * down the y axis.
-     * 
+     *
      * When rotating large views, it is recommended to adjust the camera distance
      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
      *
      * @param rotationY The degrees of Y rotation.
-     * 
-     * @see #getRotationY() 
+     *
+     * @see #getRotationY()
      * @see #getPivotX()
      * @see #getPivotY()
      * @see #setRotation(float)
-     * @see #setRotationX(float) 
-     * @see #setCameraDistance(float) 
+     * @see #setRotationX(float)
+     * @see #setCameraDistance(float)
      *
      * @attr ref android.R.styleable#View_rotationY
      */
@@ -7633,8 +7769,8 @@
      *
      * @see #getPivotX()
      * @see #getPivotY()
-     * @see #setRotationX(float) 
-     * 
+     * @see #setRotationX(float)
+     *
      * @return The degrees of X rotation.
      */
     @ViewDebug.ExportedProperty(category = "drawing")
@@ -7646,18 +7782,18 @@
      * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
      * Increasing values result in clockwise rotation from the viewpoint of looking down the
      * x axis.
-     * 
+     *
      * When rotating large views, it is recommended to adjust the camera distance
      * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
      *
      * @param rotationX The degrees of X rotation.
-     * 
-     * @see #getRotationX() 
+     *
+     * @see #getRotationX()
      * @see #getPivotX()
      * @see #getPivotY()
      * @see #setRotation(float)
-     * @see #setRotationY(float) 
-     * @see #setCameraDistance(float) 
+     * @see #setRotationY(float)
+     * @see #setCameraDistance(float)
      *
      * @attr ref android.R.styleable#View_rotationX
      */
@@ -7762,6 +7898,8 @@
      * @see #getScaleY()
      * @see #getPivotY()
      * @return The x location of the pivot point.
+     *
+     * @attr ref android.R.styleable#View_transformPivotX
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getPivotX() {
@@ -7807,6 +7945,8 @@
      * @see #getScaleY()
      * @see #getPivotY()
      * @return The y location of the pivot point.
+     *
+     * @attr ref android.R.styleable#View_transformPivotY
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getPivotY() {
@@ -7855,6 +7995,23 @@
     }
 
     /**
+     * Returns whether this View has content which overlaps. This function, intended to be
+     * overridden by specific View types, is an optimization when alpha is set on a view. If
+     * rendering overlaps in a view with alpha < 1, that view is drawn to an offscreen buffer
+     * and then composited it into place, which can be expensive. If the view has no overlapping
+     * rendering, the view can draw each primitive with the appropriate alpha value directly.
+     * An example of overlapping rendering is a TextView with a background image, such as a
+     * Button. An example of non-overlapping rendering is a TextView with no background, or
+     * an ImageView with only the foreground image. The default implementation returns true;
+     * subclasses should override if they have cases which can be optimized.
+     *
+     * @return true if the content in this view might overlap, false otherwise.
+     */
+    public boolean hasOverlappingRendering() {
+        return true;
+    }
+
+    /**
      * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
      * completely transparent and 1 means the view is completely opaque.</p>
      *
@@ -9005,7 +9162,7 @@
         //   - Background is opaque
         //   - Doesn't have scrollbars or scrollbars are inside overlay
 
-        if (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE) {
+        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
             mPrivateFlags |= OPAQUE_BACKGROUND;
         } else {
             mPrivateFlags &= ~OPAQUE_BACKGROUND;
@@ -9053,7 +9210,7 @@
     /**
      * <p>Causes the Runnable to be added to the message queue.
      * The runnable will be run on the user interface thread.</p>
-     * 
+     *
      * <p>This method can be invoked from outside of the UI thread
      * only when this View is attached to a window.</p>
      *
@@ -9077,7 +9234,7 @@
      * <p>Causes the Runnable to be added to the message queue, to be run
      * after the specified amount of time elapses.
      * The runnable will be run on the user interface thread.</p>
-     * 
+     *
      * <p>This method can be invoked from outside of the UI thread
      * only when this View is attached to a window.</p>
      *
@@ -9151,7 +9308,7 @@
 
     /**
      * <p>Removes the specified Runnable from the message queue.</p>
-     * 
+     *
      * <p>This method can be invoked from outside of the UI thread
      * only when this View is attached to a window.</p>
      *
@@ -9183,7 +9340,7 @@
      *
      * <p>This method can be invoked from outside of the UI thread
      * only when this View is attached to a window.</p>
-     * 
+     *
      * @see #invalidate()
      */
     public void postInvalidate() {
@@ -9193,7 +9350,7 @@
     /**
      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
      * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
-     * 
+     *
      * <p>This method can be invoked from outside of the UI thread
      * only when this View is attached to a window.</p>
      *
@@ -9212,7 +9369,7 @@
     /**
      * <p>Cause an invalidate to happen on a subsequent cycle through the event
      * loop. Waits for the specified amount of time.</p>
-     * 
+     *
      * <p>This method can be invoked from outside of the UI thread
      * only when this View is attached to a window.</p>
      *
@@ -9231,7 +9388,7 @@
     /**
      * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
      * through the event loop. Waits for the specified amount of time.</p>
-     * 
+     *
      * <p>This method can be invoked from outside of the UI thread
      * only when this View is attached to a window.</p>
      *
@@ -9341,6 +9498,7 @@
      *         otherwise
      *
      * @see #setHorizontalFadingEdgeEnabled(boolean)
+     *
      * @attr ref android.R.styleable#View_requiresFadingEdge
      */
     public boolean isHorizontalFadingEdgeEnabled() {
@@ -9356,6 +9514,7 @@
      *                                    horizontally
      *
      * @see #isHorizontalFadingEdgeEnabled()
+     *
      * @attr ref android.R.styleable#View_requiresFadingEdge
      */
     public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
@@ -9376,6 +9535,7 @@
      *         otherwise
      *
      * @see #setVerticalFadingEdgeEnabled(boolean)
+     *
      * @attr ref android.R.styleable#View_requiresFadingEdge
      */
     public boolean isVerticalFadingEdgeEnabled() {
@@ -9391,6 +9551,7 @@
      *                                  vertically
      *
      * @see #isVerticalFadingEdgeEnabled()
+     *
      * @attr ref android.R.styleable#View_requiresFadingEdge
      */
     public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
@@ -9533,6 +9694,7 @@
      *
      * @param fadeScrollbars wheter to enable fading
      *
+     * @attr ref android.R.styleable#View_fadeScrollbars
      */
     public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
         initScrollCache();
@@ -9550,12 +9712,86 @@
      * Returns true if scrollbars will fade when this view is not scrolling
      *
      * @return true if scrollbar fading is enabled
+     *
+     * @attr ref android.R.styleable#View_fadeScrollbars
      */
     public boolean isScrollbarFadingEnabled() {
         return mScrollCache != null && mScrollCache.fadeScrollBars;
     }
 
     /**
+     *
+     * Returns the delay before scrollbars fade.
+     *
+     * @return the delay before scrollbars fade
+     *
+     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
+     */
+    public int getScrollBarDefaultDelayBeforeFade() {
+        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
+                mScrollCache.scrollBarDefaultDelayBeforeFade;
+    }
+
+    /**
+     * Define the delay before scrollbars fade.
+     *
+     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
+     *
+     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
+     */
+    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
+        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
+    }
+
+    /**
+     *
+     * Returns the scrollbar fade duration.
+     *
+     * @return the scrollbar fade duration
+     *
+     * @attr ref android.R.styleable#View_scrollbarFadeDuration
+     */
+    public int getScrollBarFadeDuration() {
+        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
+                mScrollCache.scrollBarFadeDuration;
+    }
+
+    /**
+     * Define the scrollbar fade duration.
+     *
+     * @param scrollBarFadeDuration - the scrollbar fade duration
+     *
+     * @attr ref android.R.styleable#View_scrollbarFadeDuration
+     */
+    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
+        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
+    }
+
+    /**
+     *
+     * Returns the scrollbar size.
+     *
+     * @return the scrollbar size
+     *
+     * @attr ref android.R.styleable#View_scrollbarSize
+     */
+    public int getScrollBarSize() {
+        return mScrollCache == null ? ViewConfiguration.getScrollBarSize() :
+                mScrollCache.scrollBarSize;
+    }
+
+    /**
+     * Define the scrollbar size.
+     *
+     * @param scrollBarSize - the scrollbar size
+     *
+     * @attr ref android.R.styleable#View_scrollbarSize
+     */
+    public void setScrollBarSize(int scrollBarSize) {
+        getScrollCache().scrollBarSize = scrollBarSize;
+    }
+
+    /**
      * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
      * inset. When inset, they add to the padding of the view. And the scrollbars
      * can be drawn inside the padding area or on the edge of the view. For example,
@@ -9571,6 +9807,8 @@
      * @see #SCROLLBARS_INSIDE_INSET
      * @see #SCROLLBARS_OUTSIDE_OVERLAY
      * @see #SCROLLBARS_OUTSIDE_INSET
+     *
+     * @attr ref android.R.styleable#View_scrollbarStyle
      */
     public void setScrollBarStyle(int style) {
         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
@@ -9587,6 +9825,8 @@
      * @see #SCROLLBARS_INSIDE_INSET
      * @see #SCROLLBARS_OUTSIDE_OVERLAY
      * @see #SCROLLBARS_OUTSIDE_INSET
+     *
+     * @attr ref android.R.styleable#View_scrollbarStyle
      */
     @ViewDebug.ExportedProperty(mapping = {
             @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
@@ -9972,6 +10212,7 @@
         resolveLayoutDirection();
         resolvePadding();
         resolveTextDirection();
+        resolveTextAlignment();
         if (isFocused()) {
             InputMethodManager imm = InputMethodManager.peekInstance();
             imm.focusIn(this);
@@ -9998,6 +10239,13 @@
     }
 
     /**
+     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
+     */
+    private boolean hasRtlSupport() {
+        return mContext.getApplicationInfo().hasRtlSupport();
+    }
+
+    /**
      * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
      * that the parent directionality can and will be resolved before its children.
      * Will call {@link View#onResolvedLayoutDirectionChanged} when resolution is done.
@@ -10006,30 +10254,32 @@
         // Clear any previous layout direction resolution
         mPrivateFlags2 &= ~LAYOUT_DIRECTION_RESOLVED_MASK;
 
-        // Set resolved depending on layout direction
-        switch (getLayoutDirection()) {
-            case LAYOUT_DIRECTION_INHERIT:
-                // If this is root view, no need to look at parent's layout dir.
-                if (canResolveLayoutDirection()) {
-                    ViewGroup viewGroup = ((ViewGroup) mParent);
+        if (hasRtlSupport()) {
+            // Set resolved depending on layout direction
+            switch (getLayoutDirection()) {
+                case LAYOUT_DIRECTION_INHERIT:
+                    // If this is root view, no need to look at parent's layout dir.
+                    if (canResolveLayoutDirection()) {
+                        ViewGroup viewGroup = ((ViewGroup) mParent);
 
-                    if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
+                        if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
+                            mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
+                        }
+                    } else {
+                        // Nothing to do, LTR by default
+                    }
+                    break;
+                case LAYOUT_DIRECTION_RTL:
+                    mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
+                    break;
+                case LAYOUT_DIRECTION_LOCALE:
+                    if(isLayoutDirectionRtl(Locale.getDefault())) {
                         mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
                     }
-                } else {
+                    break;
+                default:
                     // Nothing to do, LTR by default
-                }
-                break;
-            case LAYOUT_DIRECTION_RTL:
-                mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
-                break;
-            case LAYOUT_DIRECTION_LOCALE:
-                if(isLayoutDirectionRtl(Locale.getDefault())) {
-                    mPrivateFlags2 |= LAYOUT_DIRECTION_RESOLVED_RTL;
-                }
-                break;
-            default:
-                // Nothing to do, LTR by default
+            }
         }
 
         // Set to resolved
@@ -10192,6 +10442,7 @@
         mCurrentAnimation = null;
 
         resetResolvedLayoutDirection();
+        resetResolvedTextAlignment();
     }
 
     /**
@@ -10322,9 +10573,9 @@
      *
      * @param container The SparseArray in which to save the view's state.
      *
-     * @see #restoreHierarchyState(android.util.SparseArray) 
-     * @see #dispatchSaveInstanceState(android.util.SparseArray) 
-     * @see #onSaveInstanceState() 
+     * @see #restoreHierarchyState(android.util.SparseArray)
+     * @see #dispatchSaveInstanceState(android.util.SparseArray)
+     * @see #onSaveInstanceState()
      */
     public void saveHierarchyState(SparseArray<Parcelable> container) {
         dispatchSaveInstanceState(container);
@@ -10337,9 +10588,9 @@
      *
      * @param container The SparseArray in which to save the view's state.
      *
-     * @see #dispatchRestoreInstanceState(android.util.SparseArray) 
-     * @see #saveHierarchyState(android.util.SparseArray) 
-     * @see #onSaveInstanceState() 
+     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
+     * @see #saveHierarchyState(android.util.SparseArray)
+     * @see #onSaveInstanceState()
      */
     protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
         if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
@@ -10373,9 +10624,9 @@
      * @return Returns a Parcelable object containing the view's current dynamic
      *         state, or null if there is nothing interesting to save. The
      *         default implementation returns null.
-     * @see #onRestoreInstanceState(android.os.Parcelable) 
-     * @see #saveHierarchyState(android.util.SparseArray) 
-     * @see #dispatchSaveInstanceState(android.util.SparseArray) 
+     * @see #onRestoreInstanceState(android.os.Parcelable)
+     * @see #saveHierarchyState(android.util.SparseArray)
+     * @see #dispatchSaveInstanceState(android.util.SparseArray)
      * @see #setSaveEnabled(boolean)
      */
     protected Parcelable onSaveInstanceState() {
@@ -10388,9 +10639,9 @@
      *
      * @param container The SparseArray which holds previously frozen states.
      *
-     * @see #saveHierarchyState(android.util.SparseArray) 
-     * @see #dispatchRestoreInstanceState(android.util.SparseArray) 
-     * @see #onRestoreInstanceState(android.os.Parcelable) 
+     * @see #saveHierarchyState(android.util.SparseArray)
+     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
+     * @see #onRestoreInstanceState(android.os.Parcelable)
      */
     public void restoreHierarchyState(SparseArray<Parcelable> container) {
         dispatchRestoreInstanceState(container);
@@ -10404,9 +10655,9 @@
      *
      * @param container The SparseArray which holds previously saved state.
      *
-     * @see #dispatchSaveInstanceState(android.util.SparseArray) 
-     * @see #restoreHierarchyState(android.util.SparseArray) 
-     * @see #onRestoreInstanceState(android.os.Parcelable) 
+     * @see #dispatchSaveInstanceState(android.util.SparseArray)
+     * @see #restoreHierarchyState(android.util.SparseArray)
+     * @see #onRestoreInstanceState(android.os.Parcelable)
      */
     protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
         if (mID != NO_ID) {
@@ -10432,9 +10683,9 @@
      * @param state The frozen state that had previously been returned by
      *        {@link #onSaveInstanceState}.
      *
-     * @see #onSaveInstanceState() 
-     * @see #restoreHierarchyState(android.util.SparseArray) 
-     * @see #dispatchRestoreInstanceState(android.util.SparseArray) 
+     * @see #onSaveInstanceState()
+     * @see #restoreHierarchyState(android.util.SparseArray)
+     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
      */
     protected void onRestoreInstanceState(Parcelable state) {
         mPrivateFlags |= SAVE_STATE_CALLED;
@@ -10588,7 +10839,7 @@
      *         {@link #LAYER_TYPE_HARDWARE}
      *
      * @see #setLayerType(int, android.graphics.Paint)
-     * @see #buildLayer() 
+     * @see #buildLayer()
      * @see #LAYER_TYPE_NONE
      * @see #LAYER_TYPE_SOFTWARE
      * @see #LAYER_TYPE_HARDWARE
@@ -10601,14 +10852,14 @@
      * Forces this view's layer to be created and this view to be rendered
      * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
      * invoking this method will have no effect.
-     * 
+     *
      * This method can for instance be used to render a view into its layer before
      * starting an animation. If this view is complex, rendering into the layer
      * before starting the animation will avoid skipping frames.
-     * 
+     *
      * @throws IllegalStateException If this view is not attached to a window
-     * 
-     * @see #setLayerType(int, android.graphics.Paint) 
+     *
+     * @see #setLayerType(int, android.graphics.Paint)
      */
     public void buildLayer() {
         if (mLayerType == LAYER_TYPE_NONE) return;
@@ -10630,7 +10881,7 @@
                 break;
         }
     }
-    
+
     // Make sure the HardwareRenderer.validate() was invoked before calling this method
     void flushLayer() {
         if (mLayerType == LAYER_TYPE_HARDWARE && mHardwareLayer != null) {
@@ -10649,7 +10900,7 @@
                 !mAttachInfo.mHardwareRenderer.isEnabled()) {
             return null;
         }
-        
+
         if (!mAttachInfo.mHardwareRenderer.validate()) return null;
 
         final int width = mRight - mLeft;
@@ -10683,10 +10934,10 @@
 
     /**
      * Destroys this View's hardware layer if possible.
-     * 
+     *
      * @return True if the layer was destroyed, false otherwise.
-     * 
-     * @see #setLayerType(int, android.graphics.Paint) 
+     *
+     * @see #setLayerType(int, android.graphics.Paint)
      * @see #LAYER_TYPE_HARDWARE
      */
     boolean destroyLayer(boolean valid) {
@@ -10710,11 +10961,11 @@
      * Destroys all hardware rendering resources. This method is invoked
      * when the system needs to reclaim resources. Upon execution of this
      * method, you should free any OpenGL resources created by the view.
-     * 
+     *
      * Note: you <strong>must</strong> call
      * <code>super.destroyHardwareResources()</code> when overriding
      * this method.
-     * 
+     *
      * @hide
      */
     protected void destroyHardwareResources() {
@@ -11425,17 +11676,17 @@
         if (offsetRequired) top += getTopPaddingOffset();
         return top;
     }
-    
+
     /**
      * @hide
      * @param offsetRequired
      */
     protected int getFadeHeight(boolean offsetRequired) {
         int padding = mPaddingTop;
-        if (offsetRequired) padding += getTopPaddingOffset();        
+        if (offsetRequired) padding += getTopPaddingOffset();
         return mBottom - mTop - mPaddingBottom - padding;
     }
-    
+
     /**
      * <p>Indicates whether this view is attached to a hardware accelerated
      * window or not.</p>
@@ -11525,6 +11776,7 @@
     void setDisplayListProperties(DisplayList displayList) {
         if (USE_DISPLAY_LIST_PROPERTIES && displayList != null) {
             displayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
+            displayList.setHasOverlappingRendering(hasOverlappingRendering());
             if (mParent instanceof ViewGroup) {
                 displayList.setClipChildren(
                         (((ViewGroup)mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0);
@@ -11935,7 +12187,7 @@
         int saveCount;
 
         if (!dirtyOpaque) {
-            final Drawable background = mBGDrawable;
+            final Drawable background = mBackground;
             if (background != null) {
                 final int scrollX = mScrollX;
                 final int scrollY = mScrollY;
@@ -12009,7 +12261,7 @@
         }
 
         final ScrollabilityCache scrollabilityCache = mScrollCache;
-        final float fadeHeight = scrollabilityCache.fadingEdgeLength;        
+        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
         int length = (int) fadeHeight;
 
         // clip the fade length if top and bottom fades overlap
@@ -12116,8 +12368,8 @@
      * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
      * should be set to 0xFF.
      *
-     * @see #setVerticalFadingEdgeEnabled(boolean) 
-     * @see #setHorizontalFadingEdgeEnabled(boolean) 
+     * @see #setVerticalFadingEdgeEnabled(boolean)
+     * @see #setHorizontalFadingEdgeEnabled(boolean)
      *
      * @return The known solid color background for this view, or 0 if the color may vary
      */
@@ -12466,7 +12718,7 @@
     * @param who the Drawable to query
     */
     public int getResolvedLayoutDirection(Drawable who) {
-        return (who == mBGDrawable) ? getResolvedLayoutDirection() : LAYOUT_DIRECTION_DEFAULT;
+        return (who == mBackground) ? getResolvedLayoutDirection() : LAYOUT_DIRECTION_DEFAULT;
     }
 
     /**
@@ -12485,11 +12737,11 @@
      * @return boolean If true than the Drawable is being displayed in the
      *         view; else false and it is not allowed to animate.
      *
-     * @see #unscheduleDrawable(android.graphics.drawable.Drawable) 
-     * @see #drawableStateChanged() 
+     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
+     * @see #drawableStateChanged()
      */
     protected boolean verifyDrawable(Drawable who) {
-        return who == mBGDrawable;
+        return who == mBackground;
     }
 
     /**
@@ -12499,10 +12751,10 @@
      * <p>Be sure to call through to the superclass when overriding this
      * function.
      *
-     * @see Drawable#setState(int[]) 
+     * @see Drawable#setState(int[])
      */
     protected void drawableStateChanged() {
-        Drawable d = mBGDrawable;
+        Drawable d = mBackground;
         if (d != null && d.isStateful()) {
             d.setState(getDrawableState());
         }
@@ -12532,9 +12784,9 @@
      *
      * @return The current drawable state
      *
-     * @see Drawable#setState(int[]) 
-     * @see #drawableStateChanged() 
-     * @see #onCreateDrawableState(int) 
+     * @see Drawable#setState(int[])
+     * @see #drawableStateChanged()
+     * @see #onCreateDrawableState(int)
      */
     public final int[] getDrawableState() {
         if ((mDrawableState != null) && ((mPrivateFlags & DRAWABLE_STATE_DIRTY) == 0)) {
@@ -12559,7 +12811,7 @@
      * @return Returns an array holding the current {@link Drawable} state of
      * the view.
      *
-     * @see #mergeDrawableStates(int[], int[]) 
+     * @see #mergeDrawableStates(int[], int[])
      */
     protected int[] onCreateDrawableState(int extraSpace) {
         if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
@@ -12635,7 +12887,7 @@
      * @return As a convenience, the <var>baseState</var> array you originally
      * passed into the function is returned.
      *
-     * @see #onCreateDrawableState(int) 
+     * @see #onCreateDrawableState(int)
      */
     protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
         final int N = baseState.length;
@@ -12652,8 +12904,8 @@
      * on all Drawable objects associated with this view.
      */
     public void jumpDrawablesToCurrentState() {
-        if (mBGDrawable != null) {
-            mBGDrawable.jumpToCurrentState();
+        if (mBackground != null) {
+            mBackground.jumpToCurrentState();
         }
     }
 
@@ -12663,10 +12915,10 @@
      */
     @RemotableViewMethod
     public void setBackgroundColor(int color) {
-        if (mBGDrawable instanceof ColorDrawable) {
-            ((ColorDrawable) mBGDrawable).setColor(color);
+        if (mBackground instanceof ColorDrawable) {
+            ((ColorDrawable) mBackground).setColor(color);
         } else {
-            setBackgroundDrawable(new ColorDrawable(color));
+            setBackground(new ColorDrawable(color));
         }
     }
 
@@ -12674,6 +12926,7 @@
      * Set the background to a given resource. The resource should refer to
      * a Drawable object or 0 to remove the background.
      * @param resid The identifier of the resource.
+     *
      * @attr ref android.R.styleable#View_background
      */
     @RemotableViewMethod
@@ -12686,7 +12939,7 @@
         if (resid != 0) {
             d = mResources.getDrawable(resid);
         }
-        setBackgroundDrawable(d);
+        setBackground(d);
 
         mBackgroundResource = resid;
     }
@@ -12698,11 +12951,19 @@
      * touched. If setting the padding is desired, please use
      * {@link #setPadding(int, int, int, int)}.
      *
-     * @param d The Drawable to use as the background, or null to remove the
+     * @param background The Drawable to use as the background, or null to remove the
      *        background
      */
-    public void setBackgroundDrawable(Drawable d) {
-        if (d == mBGDrawable) {
+    public void setBackground(Drawable background) {
+        setBackgroundDrawable(background);
+    }
+
+    /**
+     * @deprecated use {@link #setBackground(Drawable)} instead
+     */
+    @Deprecated
+    public void setBackgroundDrawable(Drawable background) {
+        if (background == mBackground) {
             return;
         }
 
@@ -12714,19 +12975,19 @@
          * Regardless of whether we're setting a new background or not, we want
          * to clear the previous drawable.
          */
-        if (mBGDrawable != null) {
-            mBGDrawable.setCallback(null);
-            unscheduleDrawable(mBGDrawable);
+        if (mBackground != null) {
+            mBackground.setCallback(null);
+            unscheduleDrawable(mBackground);
         }
 
-        if (d != null) {
+        if (background != null) {
             Rect padding = sThreadLocal.get();
             if (padding == null) {
                 padding = new Rect();
                 sThreadLocal.set(padding);
             }
-            if (d.getPadding(padding)) {
-                switch (d.getResolvedLayoutDirectionSelf()) {
+            if (background.getPadding(padding)) {
+                switch (background.getResolvedLayoutDirectionSelf()) {
                     case LAYOUT_DIRECTION_RTL:
                         setPadding(padding.right, padding.top, padding.left, padding.bottom);
                         break;
@@ -12738,17 +12999,17 @@
 
             // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
             // if it has a different minimum size, we should layout again
-            if (mBGDrawable == null || mBGDrawable.getMinimumHeight() != d.getMinimumHeight() ||
-                    mBGDrawable.getMinimumWidth() != d.getMinimumWidth()) {
+            if (mBackground == null || mBackground.getMinimumHeight() != background.getMinimumHeight() ||
+                    mBackground.getMinimumWidth() != background.getMinimumWidth()) {
                 requestLayout = true;
             }
 
-            d.setCallback(this);
-            if (d.isStateful()) {
-                d.setState(getDrawableState());
+            background.setCallback(this);
+            if (background.isStateful()) {
+                background.setState(getDrawableState());
             }
-            d.setVisible(getVisibility() == VISIBLE, false);
-            mBGDrawable = d;
+            background.setVisible(getVisibility() == VISIBLE, false);
+            mBackground = background;
 
             if ((mPrivateFlags & SKIP_DRAW) != 0) {
                 mPrivateFlags &= ~SKIP_DRAW;
@@ -12757,7 +13018,7 @@
             }
         } else {
             /* Remove the background */
-            mBGDrawable = null;
+            mBackground = null;
 
             if ((mPrivateFlags & ONLY_DRAWS_BACKGROUND) != 0) {
                 /*
@@ -12793,10 +13054,15 @@
 
     /**
      * Gets the background drawable
+     *
      * @return The drawable used as the background for this view, if any.
+     *
+     * @see #setBackground(Drawable)
+     *
+     * @attr ref android.R.styleable#View_background
      */
     public Drawable getBackground() {
-        return mBGDrawable;
+        return mBackground;
     }
 
     /**
@@ -13337,8 +13603,8 @@
      * number.
      *
      * @see #NO_ID
-     * @see #getId() 
-     * @see #findViewById(int) 
+     * @see #getId()
+     * @see #findViewById(int)
      *
      * @param id a number used to identify the view
      *
@@ -13377,8 +13643,8 @@
      * @return a positive integer used to identify the view or {@link #NO_ID}
      *         if the view has no ID
      *
-     * @see #setId(int) 
-     * @see #findViewById(int) 
+     * @see #setId(int)
+     * @see #findViewById(int)
      * @attr ref android.R.styleable#View_id
      */
     @ViewDebug.CapturedViewProperty
@@ -13890,16 +14156,8 @@
      * @return The suggested minimum height of the view.
      */
     protected int getSuggestedMinimumHeight() {
-        int suggestedMinHeight = mMinHeight;
+        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
 
-        if (mBGDrawable != null) {
-            final int bgMinHeight = mBGDrawable.getMinimumHeight();
-            if (suggestedMinHeight < bgMinHeight) {
-                suggestedMinHeight = bgMinHeight;
-            }
-        }
-
-        return suggestedMinHeight;
     }
 
     /**
@@ -13914,16 +14172,20 @@
      * @return The suggested minimum width of the view.
      */
     protected int getSuggestedMinimumWidth() {
-        int suggestedMinWidth = mMinWidth;
+        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
+    }
 
-        if (mBGDrawable != null) {
-            final int bgMinWidth = mBGDrawable.getMinimumWidth();
-            if (suggestedMinWidth < bgMinWidth) {
-                suggestedMinWidth = bgMinWidth;
-            }
-        }
-
-        return suggestedMinWidth;
+    /**
+     * Returns the minimum height of the view.
+     *
+     * @return the minimum height the view will try to be.
+     *
+     * @see #setMinimumHeight(int)
+     *
+     * @attr ref android.R.styleable#View_minHeight
+     */
+    public int getMinimumHeight() {
+        return mMinHeight;
     }
 
     /**
@@ -13932,9 +14194,27 @@
      * constrains it with less available height).
      *
      * @param minHeight The minimum height the view will try to be.
+     *
+     * @see #getMinimumHeight()
+     *
+     * @attr ref android.R.styleable#View_minHeight
      */
     public void setMinimumHeight(int minHeight) {
         mMinHeight = minHeight;
+        requestLayout();
+    }
+
+    /**
+     * Returns the minimum width of the view.
+     *
+     * @return the minimum width the view will try to be.
+     *
+     * @see #setMinimumWidth(int)
+     *
+     * @attr ref android.R.styleable#View_minWidth
+     */
+    public int getMinimumWidth() {
+        return mMinWidth;
     }
 
     /**
@@ -13943,9 +14223,15 @@
      * constrains it with less available width).
      *
      * @param minWidth The minimum width the view will try to be.
+     *
+     * @see #getMinimumWidth()
+     *
+     * @attr ref android.R.styleable#View_minWidth
      */
     public void setMinimumWidth(int minWidth) {
         mMinWidth = minWidth;
+        requestLayout();
+
     }
 
     /**
@@ -14064,11 +14350,11 @@
                 getLocationInWindow(location);
                 region.op(location[0], location[1], location[0] + mRight - mLeft,
                         location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
-            } else if ((pflags & ONLY_DRAWS_BACKGROUND) != 0 && mBGDrawable != null) {
+            } else if ((pflags & ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null) {
                 // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
                 // exists, so we remove the background drawable's non-transparent
                 // parts from this transparent region.
-                applyDrawableToTransparentRegion(mBGDrawable, region);
+                applyDrawableToTransparentRegion(mBackground, region);
             }
         }
         return true;
@@ -14739,7 +15025,7 @@
      * {@link #TEXT_DIRECTION_ANY_RTL},
      * {@link #TEXT_DIRECTION_LTR},
      * {@link #TEXT_DIRECTION_RTL},
-     * {@link #TEXT_DIRECTION_LOCALE},
+     * {@link #TEXT_DIRECTION_LOCALE}
      */
     @ViewDebug.ExportedProperty(category = "text", mapping = {
             @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
@@ -14763,7 +15049,7 @@
      * {@link #TEXT_DIRECTION_ANY_RTL},
      * {@link #TEXT_DIRECTION_LTR},
      * {@link #TEXT_DIRECTION_RTL},
-     * {@link #TEXT_DIRECTION_LOCALE},
+     * {@link #TEXT_DIRECTION_LOCALE}
      */
     public void setTextDirection(int textDirection) {
         if (getTextDirection() != textDirection) {
@@ -14772,6 +15058,7 @@
             resetResolvedTextDirection();
             // Set the new text direction
             mPrivateFlags2 |= ((textDirection << TEXT_DIRECTION_MASK_SHIFT) & TEXT_DIRECTION_MASK);
+            // Refresh
             requestLayout();
             invalidate(true);
         }
@@ -14791,7 +15078,7 @@
      * {@link #TEXT_DIRECTION_ANY_RTL},
      * {@link #TEXT_DIRECTION_LTR},
      * {@link #TEXT_DIRECTION_RTL},
-     * {@link #TEXT_DIRECTION_LOCALE},
+     * {@link #TEXT_DIRECTION_LOCALE}
      */
     public int getResolvedTextDirection() {
         // The text direction will be resolved only if needed
@@ -14809,44 +15096,49 @@
         // Reset any previous text direction resolution
         mPrivateFlags2 &= ~(TEXT_DIRECTION_RESOLVED | TEXT_DIRECTION_RESOLVED_MASK);
 
-        // Set resolved text direction flag depending on text direction flag
-        final int textDirection = getTextDirection();
-        switch(textDirection) {
-            case TEXT_DIRECTION_INHERIT:
-                if (canResolveTextDirection()) {
-                    ViewGroup viewGroup = ((ViewGroup) mParent);
+        if (hasRtlSupport()) {
+            // Set resolved text direction flag depending on text direction flag
+            final int textDirection = getTextDirection();
+            switch(textDirection) {
+                case TEXT_DIRECTION_INHERIT:
+                    if (canResolveTextDirection()) {
+                        ViewGroup viewGroup = ((ViewGroup) mParent);
 
-                    // Set current resolved direction to the same value as the parent's one
-                    final int parentResolvedDirection = viewGroup.getResolvedTextDirection();
-                    switch (parentResolvedDirection) {
-                        case TEXT_DIRECTION_FIRST_STRONG:
-                        case TEXT_DIRECTION_ANY_RTL:
-                        case TEXT_DIRECTION_LTR:
-                        case TEXT_DIRECTION_RTL:
-                        case TEXT_DIRECTION_LOCALE:
-                            mPrivateFlags2 |=
-                                    (parentResolvedDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
-                            break;
-                        default:
-                            // Default resolved direction is "first strong" heuristic
-                            mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
+                        // Set current resolved direction to the same value as the parent's one
+                        final int parentResolvedDirection = viewGroup.getResolvedTextDirection();
+                        switch (parentResolvedDirection) {
+                            case TEXT_DIRECTION_FIRST_STRONG:
+                            case TEXT_DIRECTION_ANY_RTL:
+                            case TEXT_DIRECTION_LTR:
+                            case TEXT_DIRECTION_RTL:
+                            case TEXT_DIRECTION_LOCALE:
+                                mPrivateFlags2 |=
+                                        (parentResolvedDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
+                                break;
+                            default:
+                                // Default resolved direction is "first strong" heuristic
+                                mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
+                        }
+                    } else {
+                        // We cannot do the resolution if there is no parent, so use the default one
+                        mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
                     }
-                } else {
-                    // We cannot do the resolution if there is no parent, so use the default one
+                    break;
+                case TEXT_DIRECTION_FIRST_STRONG:
+                case TEXT_DIRECTION_ANY_RTL:
+                case TEXT_DIRECTION_LTR:
+                case TEXT_DIRECTION_RTL:
+                case TEXT_DIRECTION_LOCALE:
+                    // Resolved direction is the same as text direction
+                    mPrivateFlags2 |= (textDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
+                    break;
+                default:
+                    // Default resolved direction is "first strong" heuristic
                     mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
-                }
-                break;
-            case TEXT_DIRECTION_FIRST_STRONG:
-            case TEXT_DIRECTION_ANY_RTL:
-            case TEXT_DIRECTION_LTR:
-            case TEXT_DIRECTION_RTL:
-            case TEXT_DIRECTION_LOCALE:
-                // Resolved direction is the same as text direction
-                mPrivateFlags2 |= (textDirection << TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
-                break;
-            default:
-                // Default resolved direction is "first strong" heuristic
-                mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
+            }
+        } else {
+            // Default resolved direction is "first strong" heuristic
+            mPrivateFlags2 |= TEXT_DIRECTION_RESOLVED_DEFAULT;
         }
 
         // Set to resolved
@@ -14895,6 +15187,199 @@
     public void onResolvedTextDirectionReset() {
     }
 
+    /**
+     * Return the value specifying the text alignment or policy that was set with
+     * {@link #setTextAlignment(int)}.
+     *
+     * @return the defined text alignment. It can be one of:
+     *
+     * {@link #TEXT_ALIGNMENT_INHERIT},
+     * {@link #TEXT_ALIGNMENT_GRAVITY},
+     * {@link #TEXT_ALIGNMENT_CENTER},
+     * {@link #TEXT_ALIGNMENT_TEXT_START},
+     * {@link #TEXT_ALIGNMENT_TEXT_END},
+     * {@link #TEXT_ALIGNMENT_VIEW_START},
+     * {@link #TEXT_ALIGNMENT_VIEW_END}
+     */
+    @ViewDebug.ExportedProperty(category = "text", mapping = {
+            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
+            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
+            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
+            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
+            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
+            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
+            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
+    })
+    public int getTextAlignment() {
+        return (mPrivateFlags2 & TEXT_ALIGNMENT_MASK) >> TEXT_ALIGNMENT_MASK_SHIFT;
+    }
+
+    /**
+     * Set the text alignment.
+     *
+     * @param textAlignment The text alignment to set. Should be one of
+     *
+     * {@link #TEXT_ALIGNMENT_INHERIT},
+     * {@link #TEXT_ALIGNMENT_GRAVITY},
+     * {@link #TEXT_ALIGNMENT_CENTER},
+     * {@link #TEXT_ALIGNMENT_TEXT_START},
+     * {@link #TEXT_ALIGNMENT_TEXT_END},
+     * {@link #TEXT_ALIGNMENT_VIEW_START},
+     * {@link #TEXT_ALIGNMENT_VIEW_END}
+     *
+     * @attr ref android.R.styleable#View_textAlignment
+     */
+    public void setTextAlignment(int textAlignment) {
+        if (textAlignment != getTextAlignment()) {
+            // Reset the current and resolved text alignment
+            mPrivateFlags2 &= ~TEXT_ALIGNMENT_MASK;
+            resetResolvedTextAlignment();
+            // Set the new text alignment
+            mPrivateFlags2 |= ((textAlignment << TEXT_ALIGNMENT_MASK_SHIFT) & TEXT_ALIGNMENT_MASK);
+            // Refresh
+            requestLayout();
+            invalidate(true);
+        }
+    }
+
+    /**
+     * Return the resolved text alignment.
+     *
+     * The resolved text alignment. This needs resolution if the value is
+     * TEXT_ALIGNMENT_INHERIT. The resolution matches {@link #setTextAlignment(int)}  if it is
+     * not TEXT_ALIGNMENT_INHERIT, otherwise resolution proceeds up the parent chain of the view.
+     *
+     * @return the resolved text alignment. Returns one of:
+     *
+     * {@link #TEXT_ALIGNMENT_GRAVITY},
+     * {@link #TEXT_ALIGNMENT_CENTER},
+     * {@link #TEXT_ALIGNMENT_TEXT_START},
+     * {@link #TEXT_ALIGNMENT_TEXT_END},
+     * {@link #TEXT_ALIGNMENT_VIEW_START},
+     * {@link #TEXT_ALIGNMENT_VIEW_END}
+     */
+    @ViewDebug.ExportedProperty(category = "text", mapping = {
+            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
+            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
+            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
+            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
+            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
+            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
+            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
+    })
+    public int getResolvedTextAlignment() {
+        // If text alignment is not resolved, then resolve it
+        if ((mPrivateFlags2 & TEXT_ALIGNMENT_RESOLVED) != TEXT_ALIGNMENT_RESOLVED) {
+            resolveTextAlignment();
+        }
+        return (mPrivateFlags2 & TEXT_ALIGNMENT_RESOLVED_MASK) >> TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
+    }
+
+    /**
+     * Resolve the text alignment. Will call {@link View#onResolvedTextAlignmentChanged} when
+     * resolution is done.
+     */
+    public void resolveTextAlignment() {
+        // Reset any previous text alignment resolution
+        mPrivateFlags2 &= ~(TEXT_ALIGNMENT_RESOLVED | TEXT_ALIGNMENT_RESOLVED_MASK);
+
+        if (hasRtlSupport()) {
+            // Set resolved text alignment flag depending on text alignment flag
+            final int textAlignment = getTextAlignment();
+            switch (textAlignment) {
+                case TEXT_ALIGNMENT_INHERIT:
+                    // Check if we can resolve the text alignment
+                    if (canResolveLayoutDirection() && mParent instanceof View) {
+                        View view = (View) mParent;
+
+                        final int parentResolvedTextAlignment = view.getResolvedTextAlignment();
+                        switch (parentResolvedTextAlignment) {
+                            case TEXT_ALIGNMENT_GRAVITY:
+                            case TEXT_ALIGNMENT_TEXT_START:
+                            case TEXT_ALIGNMENT_TEXT_END:
+                            case TEXT_ALIGNMENT_CENTER:
+                            case TEXT_ALIGNMENT_VIEW_START:
+                            case TEXT_ALIGNMENT_VIEW_END:
+                                // Resolved text alignment is the same as the parent resolved
+                                // text alignment
+                                mPrivateFlags2 |=
+                                        (parentResolvedTextAlignment << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
+                                break;
+                            default:
+                                // Use default resolved text alignment
+                                mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+                        }
+                    }
+                    else {
+                        // We cannot do the resolution if there is no parent so use the default
+                        mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+                    }
+                    break;
+                case TEXT_ALIGNMENT_GRAVITY:
+                case TEXT_ALIGNMENT_TEXT_START:
+                case TEXT_ALIGNMENT_TEXT_END:
+                case TEXT_ALIGNMENT_CENTER:
+                case TEXT_ALIGNMENT_VIEW_START:
+                case TEXT_ALIGNMENT_VIEW_END:
+                    // Resolved text alignment is the same as text alignment
+                    mPrivateFlags2 |= (textAlignment << TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
+                    break;
+                default:
+                    // Use default resolved text alignment
+                    mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+            }
+        } else {
+            // Use default resolved text alignment
+            mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+        }
+
+        // Set the resolved
+        mPrivateFlags2 |= TEXT_ALIGNMENT_RESOLVED;
+        onResolvedTextAlignmentChanged();
+    }
+
+    /**
+     * Check if text alignment resolution can be done.
+     *
+     * @return true if text alignment resolution can be done otherwise return false.
+     */
+    public boolean canResolveTextAlignment() {
+        switch (getTextAlignment()) {
+            case TEXT_DIRECTION_INHERIT:
+                return (mParent != null);
+            default:
+                return true;
+        }
+    }
+
+    /**
+     * Called when text alignment has been resolved. Subclasses that care about text alignment
+     * resolution should override this method.
+     *
+     * The default implementation does nothing.
+     */
+    public void onResolvedTextAlignmentChanged() {
+    }
+
+    /**
+     * Reset resolved text alignment. Text alignment can be resolved with a call to
+     * getResolvedTextAlignment(). Will call {@link View#onResolvedTextAlignmentReset} when
+     * reset is done.
+     */
+    public void resetResolvedTextAlignment() {
+        // Reset any previous text alignment resolution
+        mPrivateFlags2 &= ~(TEXT_ALIGNMENT_RESOLVED | TEXT_ALIGNMENT_RESOLVED_MASK);
+        onResolvedTextAlignmentReset();
+    }
+
+    /**
+     * Called when text alignment is reset. Subclasses that care about text alignment reset should
+     * override this method and do a reset of the text alignment of their children. The default
+     * implementation does nothing.
+     */
+    public void onResolvedTextAlignmentReset() {
+    }
+
     //
     // Properties
     //
@@ -15387,7 +15872,7 @@
      * visibility.  This reports <strong>global</strong> changes to the system UI
      * state, not just what the application is requesting.
      *
-     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener) 
+     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
      */
     public interface OnSystemUiVisibilityChangeListener {
         /**
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 20183ee..9d06145 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -31,14 +31,14 @@
 public class ViewConfiguration {
     /**
      * Expected bit depth of the display panel.
-     * 
+     *
      * @hide
      */
     public static final float PANEL_BIT_DEPTH = 24;
 
     /**
      * Minimum alpha required for a view to draw.
-     * 
+     *
      * @hide
      */
     public static final float ALPHA_THRESHOLD = 0.5f / PANEL_BIT_DEPTH;
@@ -72,8 +72,8 @@
      * Defines the duration in milliseconds of the pressed state in child
      * components.
      */
-    private static final int PRESSED_STATE_DURATION = 125;
-    
+    private static final int PRESSED_STATE_DURATION = 64;
+
     /**
      * Defines the default duration in milliseconds before a press turns into
      * a long press
@@ -91,18 +91,18 @@
      * lock screen, etc).
      */
     private static final int GLOBAL_ACTIONS_KEY_TIMEOUT = 500;
-    
+
     /**
-     * Defines the duration in milliseconds we will wait to see if a touch event 
+     * Defines the duration in milliseconds we will wait to see if a touch event
      * is a tap or a scroll. If the user does not move within this interval, it is
-     * considered to be a tap. 
+     * considered to be a tap.
      */
     private static final int TAP_TIMEOUT = 180;
-    
+
     /**
-     * Defines the duration in milliseconds we will wait to see if a touch event 
+     * Defines the duration in milliseconds we will wait to see if a touch event
      * is a jump tap. If the user does not complete the jump tap within this interval, it is
-     * considered to be a tap. 
+     * considered to be a tap.
      */
     private static final int JUMP_TAP_TIMEOUT = 500;
 
@@ -128,7 +128,7 @@
     private static final int HOVER_TAP_SLOP = 20;
 
     /**
-     * Defines the duration in milliseconds we want to display zoom controls in response 
+     * Defines the duration in milliseconds we want to display zoom controls in response
      * to a user panning within an application.
      */
     private static final int ZOOM_CONTROLS_TIMEOUT = 3000;
@@ -137,7 +137,7 @@
      * Inset in dips to look for touchable content when the user touches the edge of the screen
      */
     private static final int EDGE_SLOP = 12;
-    
+
     /**
      * Distance a touch can wander before we think the user is scrolling in dips.
      * Note that this value defined here is only used as a fallback by legacy/misbehaving
@@ -150,7 +150,7 @@
      * the characteristics of the touch panel and firmware.
      */
     private static final int TOUCH_SLOP = 8;
-    
+
     /**
      * Distance the first touch can wander before we stop considering this event a double tap
      * (in dips)
@@ -170,12 +170,12 @@
      * config_viewConfigurationTouchSlop * 2 when provided with a Context.
      */
     private static final int PAGING_TOUCH_SLOP = TOUCH_SLOP * 2;
-    
+
     /**
      * Distance in dips between the first touch and second touch to still be considered a double tap
      */
     private static final int DOUBLE_TAP_SLOP = 100;
-    
+
     /**
      * Distance in dips a touch needs to be outside of a window's bounds for it to
      * count as outside for purposes of dismissing the window.
@@ -186,7 +186,7 @@
      * Minimum velocity to initiate a fling, as measured in dips per second
      */
     private static final int MINIMUM_FLING_VELOCITY = 50;
-    
+
     /**
      * Maximum velocity to initiate a fling, as measured in dips per second
      */
@@ -281,7 +281,7 @@
      *
      * @param context The application context used to initialize this view configuration.
      *
-     * @see #get(android.content.Context) 
+     * @see #get(android.content.Context)
      * @see android.util.DisplayMetrics
      */
     private ViewConfiguration(Context context) {
@@ -315,7 +315,7 @@
         if (!sHasPermanentMenuKeySet) {
             IWindowManager wm = Display.getWindowManager();
             try {
-                sHasPermanentMenuKey = wm.canStatusBarHide() && !wm.hasNavigationBar();
+                sHasPermanentMenuKey = !wm.hasSystemNavBar() && !wm.hasNavigationBar();
                 sHasPermanentMenuKeySet = true;
             } catch (RemoteException ex) {
                 sHasPermanentMenuKey = false;
@@ -383,7 +383,7 @@
     public static int getScrollDefaultDelay() {
         return SCROLL_BAR_DEFAULT_DELAY;
     }
-    
+
     /**
      * @return the length of the fading edges in dips
      *
@@ -435,7 +435,7 @@
     /**
      * @return the duration in milliseconds we will wait to see if a touch event
      * is a tap or a scroll. If the user does not move within this interval, it is
-     * considered to be a tap. 
+     * considered to be a tap.
      */
     public static int getTapTimeout() {
         return TAP_TIMEOUT;
@@ -444,12 +444,12 @@
     /**
      * @return the duration in milliseconds we will wait to see if a touch event
      * is a jump tap. If the user does not move within this interval, it is
-     * considered to be a tap. 
+     * considered to be a tap.
      */
     public static int getJumpTapTimeout() {
         return JUMP_TAP_TIMEOUT;
     }
-    
+
     /**
      * @return the duration in milliseconds between the first tap's up event and
      * the second tap's down event for an interaction to be considered a
@@ -514,7 +514,7 @@
     public int getScaledTouchSlop() {
         return mTouchSlop;
     }
-    
+
     /**
      * @return Distance in pixels the first touch can wander before we do not consider this a
      * potential double tap event
@@ -543,7 +543,7 @@
     public static int getDoubleTapSlop() {
         return DOUBLE_TAP_SLOP;
     }
-    
+
     /**
      * @return Distance in pixels between the first touch and second touch to still be
      *         considered a double tap
@@ -595,7 +595,7 @@
     public int getScaledWindowTouchSlop() {
         return mWindowTouchSlop;
     }
-    
+
     /**
      * @return Minimum velocity to initiate a fling, as measured in dips per second.
      *
@@ -629,7 +629,7 @@
     public int getScaledMaximumFlingVelocity() {
         return mMaximumFlingVelocity;
     }
-    
+
     /**
      * The maximum drawing cache size expressed in bytes.
      *
@@ -671,7 +671,7 @@
     /**
      * The amount of time that the zoom controls should be
      * displayed on the screen expressed in milliseconds.
-     * 
+     *
      * @return the time the zoom controls should be visible expressed
      * in milliseconds.
      */
@@ -692,7 +692,7 @@
 
     /**
      * The amount of friction applied to scrolls and flings.
-     * 
+     *
      * @return A scalar dimensionless value representing the coefficient of
      *         friction.
      */
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index d5c783f..121b544 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3375,7 +3375,7 @@
 
         boolean clearChildFocus = false;
         if (view == mFocused) {
-            view.clearFocusForRemoval();
+            view.unFocus();
             clearChildFocus = true;
         }
 
@@ -3398,6 +3398,7 @@
 
         if (clearChildFocus) {
             clearChildFocus(view);
+            ensureInputFocusOnFirstFocusable();
         }
     }
 
@@ -3450,7 +3451,7 @@
             }
 
             if (view == focused) {
-                view.clearFocusForRemoval();
+                view.unFocus();
                 clearChildFocus = view;
             }
 
@@ -3474,6 +3475,7 @@
 
         if (clearChildFocus != null) {
             clearChildFocus(clearChildFocus);
+            ensureInputFocusOnFirstFocusable();
         }
     }
 
@@ -3519,7 +3521,7 @@
             }
 
             if (view == focused) {
-                view.clearFocusForRemoval();
+                view.unFocus();
                 clearChildFocus = view;
             }
 
@@ -3542,6 +3544,7 @@
 
         if (clearChildFocus != null) {
             clearChildFocus(clearChildFocus);
+            ensureInputFocusOnFirstFocusable();
         }
     }
 
@@ -5056,6 +5059,18 @@
         }
     }
 
+    @Override
+    public void onResolvedTextAlignmentReset() {
+        // Take care of resetting the children resolution too
+        final int count = getChildCount();
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            if (child.getTextAlignment() == TEXT_ALIGNMENT_INHERIT) {
+                child.resetResolvedTextAlignment();
+            }
+        }
+    }
+
     /**
      * Return true if the pressed state should be delayed for children or descendants of this
      * ViewGroup. Generally, this should be done for containers that can scroll, such as a List.
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index 623b567..3626aba 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -834,40 +834,49 @@
      */
     private void setValue(int propertyConstant, float value) {
         final View.TransformationInfo info = mView.mTransformationInfo;
+        DisplayList displayList = View.USE_DISPLAY_LIST_PROPERTIES ? mView.mDisplayList : null;
         switch (propertyConstant) {
             case TRANSLATION_X:
                 info.mTranslationX = value;
+                if (displayList != null) displayList.setTranslationX(value);
                 break;
             case TRANSLATION_Y:
                 info.mTranslationY = value;
+                if (displayList != null) displayList.setTranslationY(value);
                 break;
             case ROTATION:
                 info.mRotation = value;
+                if (displayList != null) displayList.setRotation(value);
                 break;
             case ROTATION_X:
                 info.mRotationX = value;
+                if (displayList != null) displayList.setRotationX(value);
                 break;
             case ROTATION_Y:
                 info.mRotationY = value;
+                if (displayList != null) displayList.setRotationY(value);
                 break;
             case SCALE_X:
                 info.mScaleX = value;
+                if (displayList != null) displayList.setScaleX(value);
                 break;
             case SCALE_Y:
                 info.mScaleY = value;
+                if (displayList != null) displayList.setScaleY(value);
                 break;
             case X:
                 info.mTranslationX = value - mView.mLeft;
+                if (displayList != null) displayList.setTranslationX(value - mView.mLeft);
                 break;
             case Y:
                 info.mTranslationY = value - mView.mTop;
+                if (displayList != null) displayList.setTranslationY(value - mView.mTop);
                 break;
             case ALPHA:
                 info.mAlpha = value;
+                if (displayList != null) displayList.setAlpha(value);
                 break;
         }
-        // TODO: optimize to set only the properties that have changed
-        mView.setDisplayListProperties();
     }
 
     /**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index d72f3b7..899fb32 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2039,9 +2039,10 @@
 
         scrollToRectOrFocus(null, false);
 
-        if (mAttachInfo.mViewScrollChanged) {
-            mAttachInfo.mViewScrollChanged = false;
-            mAttachInfo.mTreeObserver.dispatchOnScrollChanged();
+        final AttachInfo attachInfo = mAttachInfo;
+        if (attachInfo.mViewScrollChanged) {
+            attachInfo.mViewScrollChanged = false;
+            attachInfo.mTreeObserver.dispatchOnScrollChanged();
         }
 
         int yoff;
@@ -2056,8 +2057,8 @@
             fullRedrawNeeded = true;
         }
 
-        final float appScale = mAttachInfo.mApplicationScale;
-        final boolean scalingRequired = mAttachInfo.mScalingRequired;
+        final float appScale = attachInfo.mApplicationScale;
+        final boolean scalingRequired = attachInfo.mScalingRequired;
 
         int resizeAlpha = 0;
         if (mResizeBuffer != null) {
@@ -2086,7 +2087,7 @@
         }
 
         if (fullRedrawNeeded) {
-            mAttachInfo.mIgnoreDirtyState = true;
+            attachInfo.mIgnoreDirtyState = true;
             dirty.set(0, 0, (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f));
         }
 
@@ -2099,8 +2100,10 @@
                     appScale + ", width=" + mWidth + ", height=" + mHeight);
         }
 
+        attachInfo.mTreeObserver.dispatchOnDraw();
+
         if (!dirty.isEmpty() || mIsAnimating) {
-            if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
+            if (attachInfo.mHardwareRenderer != null && attachInfo.mHardwareRenderer.isEnabled()) {
                 // Draw with hardware renderer.
                 mIsAnimating = false;
                 mHardwareYOffset = yoff;
@@ -2111,147 +2114,12 @@
                 mPreviousDirty.set(dirty);
                 dirty.setEmpty();
 
-                if (mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this,
+                if (attachInfo.mHardwareRenderer.draw(mView, attachInfo, this,
                         animating ? null : mCurrentDirty)) {
                     mPreviousDirty.set(0, 0, mWidth, mHeight);
                 }
-            } else {
-                // Draw with software renderer.
-                Canvas canvas;
-                try {
-                    int left = dirty.left;
-                    int top = dirty.top;
-                    int right = dirty.right;
-                    int bottom = dirty.bottom;
-
-                    final long lockCanvasStartTime;
-                    if (ViewDebug.DEBUG_LATENCY) {
-                        lockCanvasStartTime = System.nanoTime();
-                    }
-
-                    canvas = mSurface.lockCanvas(dirty);
-
-                    if (ViewDebug.DEBUG_LATENCY) {
-                        long now = System.nanoTime();
-                        Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- lockCanvas() took "
-                                + ((now - lockCanvasStartTime) * 0.000001f) + "ms");
-                    }
-
-                    if (left != dirty.left || top != dirty.top || right != dirty.right ||
-                            bottom != dirty.bottom) {
-                        mAttachInfo.mIgnoreDirtyState = true;
-                    }
-
-                    // TODO: Do this in native
-                    canvas.setDensity(mDensity);
-                } catch (Surface.OutOfResourcesException e) {
-                    Log.e(TAG, "OutOfResourcesException locking surface", e);
-                    try {
-                        if (!sWindowSession.outOfMemory(mWindow)) {
-                            Slog.w(TAG, "No processes killed for memory; killing self");
-                            Process.killProcess(Process.myPid());
-                        }
-                    } catch (RemoteException ex) {
-                    }
-                    mLayoutRequested = true;    // ask wm for a new surface next time.
-                    return;
-                } catch (IllegalArgumentException e) {
-                    Log.e(TAG, "IllegalArgumentException locking surface", e);
-                    // Don't assume this is due to out of memory, it could be
-                    // something else, and if it is something else then we could
-                    // kill stuff (or ourself) for no reason.
-                    mLayoutRequested = true;    // ask wm for a new surface next time.
-                    return;
-                }
-
-                try {
-                    if (DEBUG_ORIENTATION || DEBUG_DRAW) {
-                        Log.v(TAG, "Surface " + surface + " drawing to bitmap w="
-                                + canvas.getWidth() + ", h=" + canvas.getHeight());
-                        //canvas.drawARGB(255, 255, 0, 0);
-                    }
-
-                    long startTime = 0L;
-                    if (ViewDebug.DEBUG_PROFILE_DRAWING) {
-                        startTime = SystemClock.elapsedRealtime();
-                    }
-
-                    // If this bitmap's format includes an alpha channel, we
-                    // need to clear it before drawing so that the child will
-                    // properly re-composite its drawing on a transparent
-                    // background. This automatically respects the clip/dirty region
-                    // or
-                    // If we are applying an offset, we need to clear the area
-                    // where the offset doesn't appear to avoid having garbage
-                    // left in the blank areas.
-                    if (!canvas.isOpaque() || yoff != 0) {
-                        canvas.drawColor(0, PorterDuff.Mode.CLEAR);
-                    }
-
-                    dirty.setEmpty();
-                    mIsAnimating = false;
-                    mAttachInfo.mDrawingTime = SystemClock.uptimeMillis();
-                    mView.mPrivateFlags |= View.DRAWN;
-
-                    if (DEBUG_DRAW) {
-                        Context cxt = mView.getContext();
-                        Log.i(TAG, "Drawing: package:" + cxt.getPackageName() +
-                                ", metrics=" + cxt.getResources().getDisplayMetrics() +
-                                ", compatibilityInfo=" + cxt.getResources().getCompatibilityInfo());
-                    }
-                    try {
-                        canvas.translate(0, -yoff);
-                        if (mTranslator != null) {
-                            mTranslator.translateCanvas(canvas);
-                        }
-                        canvas.setScreenDensity(scalingRequired
-                                ? DisplayMetrics.DENSITY_DEVICE : 0);
-                        mAttachInfo.mSetIgnoreDirtyState = false;
-
-                        final long drawStartTime;
-                        if (ViewDebug.DEBUG_LATENCY) {
-                            drawStartTime = System.nanoTime();
-                        }
-
-                        mView.draw(canvas);
-
-                        if (ViewDebug.DEBUG_LATENCY) {
-                            long now = System.nanoTime();
-                            Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- draw() took "
-                                    + ((now - drawStartTime) * 0.000001f) + "ms");
-                        }
-                    } finally {
-                        if (!mAttachInfo.mSetIgnoreDirtyState) {
-                            // Only clear the flag if it was not set during the mView.draw() call
-                            mAttachInfo.mIgnoreDirtyState = false;
-                        }
-                    }
-
-                    if (false && ViewDebug.consistencyCheckEnabled) {
-                        mView.dispatchConsistencyCheck(ViewDebug.CONSISTENCY_DRAWING);
-                    }
-
-                    if (ViewDebug.DEBUG_PROFILE_DRAWING) {
-                        EventLog.writeEvent(60000, SystemClock.elapsedRealtime() - startTime);
-                    }
-                } finally {
-                    final long unlockCanvasAndPostStartTime;
-                    if (ViewDebug.DEBUG_LATENCY) {
-                        unlockCanvasAndPostStartTime = System.nanoTime();
-                    }
-
-                    surface.unlockCanvasAndPost(canvas);
-
-                    if (ViewDebug.DEBUG_LATENCY) {
-                        long now = System.nanoTime();
-                        Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- unlockCanvasAndPost() took "
-                                + ((now - unlockCanvasAndPostStartTime) * 0.000001f) + "ms");
-                    }
-
-                    if (LOCAL_LOGV) {
-                        Log.v(TAG, "Surface " + surface + " unlockCanvasAndPost");
-                    }
-                }
+            } else if (!drawSoftware(surface, attachInfo, yoff, scalingRequired, dirty)) {
+                return;
             }
         }
 
@@ -2261,6 +2129,151 @@
         }
     }
 
+    /**
+     * @return true if drawing was succesfull, false if an error occurred
+     */
+    private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int yoff,
+            boolean scalingRequired, Rect dirty) {
+
+        // Draw with software renderer.
+        Canvas canvas;
+        try {
+            int left = dirty.left;
+            int top = dirty.top;
+            int right = dirty.right;
+            int bottom = dirty.bottom;
+
+            final long lockCanvasStartTime;
+            if (ViewDebug.DEBUG_LATENCY) {
+                lockCanvasStartTime = System.nanoTime();
+            }
+
+            canvas = mSurface.lockCanvas(dirty);
+
+            if (ViewDebug.DEBUG_LATENCY) {
+                long now = System.nanoTime();
+                Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- lockCanvas() took "
+                        + ((now - lockCanvasStartTime) * 0.000001f) + "ms");
+            }
+
+            if (left != dirty.left || top != dirty.top || right != dirty.right ||
+                    bottom != dirty.bottom) {
+                attachInfo.mIgnoreDirtyState = true;
+            }
+
+            // TODO: Do this in native
+            canvas.setDensity(mDensity);
+        } catch (Surface.OutOfResourcesException e) {
+            Log.e(TAG, "OutOfResourcesException locking surface", e);
+            try {
+                if (!sWindowSession.outOfMemory(mWindow)) {
+                    Slog.w(TAG, "No processes killed for memory; killing self");
+                    Process.killProcess(Process.myPid());
+                }
+            } catch (RemoteException ex) {
+            }
+            mLayoutRequested = true;    // ask wm for a new surface next time.
+            return false;
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "IllegalArgumentException locking surface", e);
+            // Don't assume this is due to out of memory, it could be
+            // something else, and if it is something else then we could
+            // kill stuff (or ourself) for no reason.
+            mLayoutRequested = true;    // ask wm for a new surface next time.
+            return false;
+        }
+
+        try {
+            if (DEBUG_ORIENTATION || DEBUG_DRAW) {
+                Log.v(TAG, "Surface " + surface + " drawing to bitmap w="
+                        + canvas.getWidth() + ", h=" + canvas.getHeight());
+                //canvas.drawARGB(255, 255, 0, 0);
+            }
+
+            long startTime = 0L;
+            if (ViewDebug.DEBUG_PROFILE_DRAWING) {
+                startTime = SystemClock.elapsedRealtime();
+            }
+
+            // If this bitmap's format includes an alpha channel, we
+            // need to clear it before drawing so that the child will
+            // properly re-composite its drawing on a transparent
+            // background. This automatically respects the clip/dirty region
+            // or
+            // If we are applying an offset, we need to clear the area
+            // where the offset doesn't appear to avoid having garbage
+            // left in the blank areas.
+            if (!canvas.isOpaque() || yoff != 0) {
+                canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+            }
+
+            dirty.setEmpty();
+            mIsAnimating = false;
+            attachInfo.mDrawingTime = SystemClock.uptimeMillis();
+            mView.mPrivateFlags |= View.DRAWN;
+
+            if (DEBUG_DRAW) {
+                Context cxt = mView.getContext();
+                Log.i(TAG, "Drawing: package:" + cxt.getPackageName() +
+                        ", metrics=" + cxt.getResources().getDisplayMetrics() +
+                        ", compatibilityInfo=" + cxt.getResources().getCompatibilityInfo());
+            }
+            try {
+                canvas.translate(0, -yoff);
+                if (mTranslator != null) {
+                    mTranslator.translateCanvas(canvas);
+                }
+                canvas.setScreenDensity(scalingRequired
+                        ? DisplayMetrics.DENSITY_DEVICE : 0);
+                attachInfo.mSetIgnoreDirtyState = false;
+
+                final long drawStartTime;
+                if (ViewDebug.DEBUG_LATENCY) {
+                    drawStartTime = System.nanoTime();
+                }
+
+                mView.draw(canvas);
+
+                if (ViewDebug.DEBUG_LATENCY) {
+                    long now = System.nanoTime();
+                    Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- draw() took "
+                            + ((now - drawStartTime) * 0.000001f) + "ms");
+                }
+            } finally {
+                if (!attachInfo.mSetIgnoreDirtyState) {
+                    // Only clear the flag if it was not set during the mView.draw() call
+                    attachInfo.mIgnoreDirtyState = false;
+                }
+            }
+
+            if (false && ViewDebug.consistencyCheckEnabled) {
+                mView.dispatchConsistencyCheck(ViewDebug.CONSISTENCY_DRAWING);
+            }
+
+            if (ViewDebug.DEBUG_PROFILE_DRAWING) {
+                EventLog.writeEvent(60000, SystemClock.elapsedRealtime() - startTime);
+            }
+        } finally {
+            final long unlockCanvasAndPostStartTime;
+            if (ViewDebug.DEBUG_LATENCY) {
+                unlockCanvasAndPostStartTime = System.nanoTime();
+            }
+
+            surface.unlockCanvasAndPost(canvas);
+
+            if (ViewDebug.DEBUG_LATENCY) {
+                long now = System.nanoTime();
+                Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- unlockCanvasAndPost() took "
+                        + ((now - unlockCanvasAndPostStartTime) * 0.000001f) + "ms");
+            }
+
+            if (LOCAL_LOGV) {
+                Log.v(TAG, "Surface " + surface + " unlockCanvasAndPost");
+            }
+        }
+        return true;
+    }
+
     void invalidateDisplayLists() {
         final ArrayList<DisplayList> displayLists = mDisplayLists;
         final int count = displayLists.size();
@@ -3830,30 +3843,33 @@
         if (LOCAL_LOGV) Log.v(TAG, "DIE in " + this + " of " + mSurface);
         synchronized (this) {
             if (mAdded) {
-                mAdded = false;
                 dispatchDetachedFromWindow();
             }
 
             if (mAdded && !mFirst) {
                 destroyHardwareRenderer();
 
-                int viewVisibility = mView.getVisibility();
-                boolean viewVisibilityChanged = mViewVisibility != viewVisibility;
-                if (mWindowAttributesChanged || viewVisibilityChanged) {
-                    // If layout params have been changed, first give them
-                    // to the window manager to make sure it has the correct
-                    // animation info.
-                    try {
-                        if ((relayoutWindow(mWindowAttributes, viewVisibility, false)
-                                & WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) {
-                            sWindowSession.finishDrawing(mWindow);
+                if (mView != null) {
+                    int viewVisibility = mView.getVisibility();
+                    boolean viewVisibilityChanged = mViewVisibility != viewVisibility;
+                    if (mWindowAttributesChanged || viewVisibilityChanged) {
+                        // If layout params have been changed, first give them
+                        // to the window manager to make sure it has the correct
+                        // animation info.
+                        try {
+                            if ((relayoutWindow(mWindowAttributes, viewVisibility, false)
+                                    & WindowManagerImpl.RELAYOUT_RES_FIRST_TIME) != 0) {
+                                sWindowSession.finishDrawing(mWindow);
+                            }
+                        } catch (RemoteException e) {
                         }
-                    } catch (RemoteException e) {
                     }
+    
+                    mSurface.release();
                 }
-
-                mSurface.release();
             }
+
+            mAdded = false;
         }
     }
 
diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java
index 7fd3389..1c5d436 100644
--- a/core/java/android/view/ViewTreeObserver.java
+++ b/core/java/android/view/ViewTreeObserver.java
@@ -38,6 +38,7 @@
     private CopyOnWriteArrayList<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners;
     private CopyOnWriteArrayList<OnScrollChangedListener> mOnScrollChangedListeners;
     private ArrayList<OnPreDrawListener> mOnPreDrawListeners;
+    private ArrayList<OnDrawListener> mOnDrawListeners;
 
     private boolean mAlive = true;
 
@@ -90,6 +91,27 @@
     }
 
     /**
+     * Interface definition for a callback to be invoked when the view tree is about to be drawn.
+     */
+    public interface OnDrawListener {
+        /**
+         * <p>Callback method to be invoked when the view tree is about to be drawn. At this point,
+         * views cannot be modified in any way.</p>
+         * 
+         * <p>Unlike with {@link OnPreDrawListener}, this method cannot be used to cancel the
+         * current drawing pass.</p>
+         * 
+         * <p>An {@link OnDrawListener} listener <strong>cannot be added or removed</strong>
+         * from this method.</p>
+         *
+         * @see android.view.View#onMeasure
+         * @see android.view.View#onLayout
+         * @see android.view.View#onDraw
+         */
+        public void onDraw();
+    }
+
+    /**
      * Interface definition for a callback to be invoked when the touch mode changes.
      */
     public interface OnTouchModeChangeListener {
@@ -171,11 +193,7 @@
         public void setTouchableInsets(int val) {
             mTouchableInsets = val;
         }
-        
-        public int getTouchableInsets() {
-            return mTouchableInsets;
-        }
-        
+
         int mTouchableInsets;
         
         void reset() {
@@ -184,29 +202,28 @@
             touchableRegion.setEmpty();
             mTouchableInsets = TOUCHABLE_INSETS_FRAME;
         }
-        
+
+        @Override
+        public int hashCode() {
+            int result = contentInsets != null ? contentInsets.hashCode() : 0;
+            result = 31 * result + (visibleInsets != null ? visibleInsets.hashCode() : 0);
+            result = 31 * result + (touchableRegion != null ? touchableRegion.hashCode() : 0);
+            result = 31 * result + mTouchableInsets;
+            return result;
+        }
+
         @Override
         public boolean equals(Object o) {
-            try {
-                if (o == null) {
-                    return false;
-                }
-                InternalInsetsInfo other = (InternalInsetsInfo)o;
-                if (mTouchableInsets != other.mTouchableInsets) {
-                    return false;
-                }
-                if (!contentInsets.equals(other.contentInsets)) {
-                    return false;
-                }
-                if (!visibleInsets.equals(other.visibleInsets)) {
-                    return false;
-                }
-                return touchableRegion.equals(other.touchableRegion);
-            } catch (ClassCastException e) {
-                return false;
-            }
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            InternalInsetsInfo other = (InternalInsetsInfo)o;
+            return mTouchableInsets == other.mTouchableInsets &&
+                    contentInsets.equals(other.contentInsets) &&
+                    visibleInsets.equals(other.visibleInsets) &&
+                    touchableRegion.equals(other.touchableRegion);
         }
-        
+
         void set(InternalInsetsInfo other) {
             contentInsets.set(other.contentInsets);
             visibleInsets.set(other.visibleInsets);
@@ -420,6 +437,44 @@
     }
 
     /**
+     * <p>Register a callback to be invoked when the view tree is about to be drawn.</p>
+     * <p><strong>Note:</strong> this method <strong>cannot</strong> be invoked from
+     * {@link android.view.ViewTreeObserver.OnDrawListener#onDraw()}.</p>
+     *
+     * @param listener The callback to add
+     *
+     * @throws IllegalStateException If {@link #isAlive()} returns false
+     */
+    public void addOnDrawListener(OnDrawListener listener) {
+        checkIsAlive();
+
+        if (mOnDrawListeners == null) {
+            mOnDrawListeners = new ArrayList<OnDrawListener>();
+        }
+
+        mOnDrawListeners.add(listener);
+    }
+
+    /**
+     * <p>Remove a previously installed pre-draw callback.</p>
+     * <p><strong>Note:</strong> this method <strong>cannot</strong> be invoked from
+     * {@link android.view.ViewTreeObserver.OnDrawListener#onDraw()}.</p>
+     *
+     * @param victim The callback to remove
+     *
+     * @throws IllegalStateException If {@link #isAlive()} returns false
+     *
+     * @see #addOnDrawListener(OnDrawListener)
+     */
+    public void removeOnDrawListener(OnDrawListener victim) {
+        checkIsAlive();
+        if (mOnDrawListeners == null) {
+            return;
+        }
+        mOnDrawListeners.remove(victim);
+    }
+
+    /**
      * Register a callback to be invoked when a view has been scrolled.
      *
      * @param listener The callback to add
@@ -601,6 +656,7 @@
      *
      * @return True if the current draw should be canceled and resceduled, false otherwise.
      */
+    @SuppressWarnings("unchecked")
     public final boolean dispatchOnPreDraw() {
         // NOTE: we *must* clone the listener list to perform the dispatching.
         // The clone is a safe guard against listeners that
@@ -619,6 +675,19 @@
     }
 
     /**
+     * Notifies registered listeners that the drawing pass is about to start.
+     */
+    public final void dispatchOnDraw() {
+        if (mOnDrawListeners != null) {
+            final ArrayList<OnDrawListener> listeners = mOnDrawListeners;
+            int numListeners = listeners.size();
+            for (int i = 0; i < numListeners; ++i) {
+                listeners.get(i).onDraw();
+            }
+        }
+    }
+
+    /**
      * Notifies registered listeners that the touch mode has changed.
      *
      * @param inTouchMode True if the touch mode is now enabled, false otherwise.
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 75267bb..cf9cafc 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -326,6 +326,11 @@
          * Returns true if {@link #hideLw} was last called for the window.
          */
         public boolean showLw(boolean doAnimation);
+
+        /**
+         * Check whether the process hosting this window is currently alive.
+         */
+        public boolean isAlive();
     }
 
     /**
@@ -447,7 +452,7 @@
      * Called by window manager once it has the initial, default native
      * display dimensions.
      */
-    public void setInitialDisplaySize(int width, int height);
+    public void setInitialDisplaySize(Display display, int width, int height);
 
     /**
      * Check permissions when adding a window.
@@ -514,10 +519,10 @@
     public int getMaxWallpaperLayer();
     
     /**
-     * Return true if the policy allows the status bar to hide.  Otherwise,
-     * it is a tablet-style system bar.
+     * Return true if the policy desires a full unified system nav bar.  Otherwise,
+     * it is a phone-style status bar with optional nav bar.
      */
-    public boolean canStatusBarHide();
+    public boolean hasSystemNavBar();
 
     /**
      * Return the display width available after excluding any screen
diff --git a/core/java/android/webkit/WebSettingsClassic.java b/core/java/android/webkit/WebSettingsClassic.java
index 94b46fc..aa3d8d3 100644
--- a/core/java/android/webkit/WebSettingsClassic.java
+++ b/core/java/android/webkit/WebSettingsClassic.java
@@ -33,7 +33,7 @@
  */
 public class WebSettingsClassic extends WebSettings {
     // TODO: Keep this up to date
-    private static final String PREVIOUS_VERSION = "4.0.3";
+    private static final String PREVIOUS_VERSION = "4.0.4";
 
     // WebView associated with this WebSettings.
     private WebViewClassic mWebView;
diff --git a/core/java/android/widget/Chronometer.java b/core/java/android/widget/Chronometer.java
index 0370049..9c9eb4b 100644
--- a/core/java/android/widget/Chronometer.java
+++ b/core/java/android/widget/Chronometer.java
@@ -25,6 +25,7 @@
 import android.text.format.DateUtils;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.Slog;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.RemoteViews.RemoteView;
@@ -247,6 +248,7 @@
             }
         }
         setText(text);
+        Slog.v("Chronometer", "updateText: sec=" + seconds + " mFormat=" + mFormat + " text=" + text);
     }
 
     private void updateRunning() {
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 880dc34..cbff58c 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1609,7 +1609,6 @@
         private boolean mCancelled;
 
         public void run() {
-            Log.d("GILLES", "blinking !!!");
             if (mCancelled) {
                 return;
             }
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index b1a75e1..91e2e497 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -201,7 +201,7 @@
 
     @Override
     protected boolean onSetAlpha(int alpha) {
-        if (getBackground() == null) {
+        if (!USE_DISPLAY_LIST_PROPERTIES && getBackground() == null) {
             int scale = alpha + (alpha >> 7);
             if (mViewAlphaScale != scale) {
                 mViewAlphaScale = scale;
@@ -214,6 +214,15 @@
     }
 
     @Override
+    public boolean hasOverlappingRendering() {
+        if (!USE_DISPLAY_LIST_PROPERTIES) {
+            return super.hasOverlappingRendering();
+        } else {
+            return (getBackground() != null);
+        }
+    }
+
+    @Override
     public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
         super.onPopulateAccessibilityEvent(event);
         CharSequence contentDescription = getContentDescription();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 2a81f08..9867e47 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4268,7 +4268,8 @@
     protected boolean onSetAlpha(int alpha) {
         // Alpha is supported if and only if the drawing can be done in one pass.
         // TODO text with spans with a background color currently do not respect this alpha.
-        if (getBackground() == null) {
+        if (!USE_DISPLAY_LIST_PROPERTIES &&
+                (getBackground() != null || mText instanceof Spannable || hasSelection())) {
             if (mCurrentAlpha != alpha) {
                 mCurrentAlpha = alpha;
                 final Drawables dr = mDrawables;
@@ -4292,6 +4293,15 @@
         return false;
     }
 
+    @Override
+    public boolean hasOverlappingRendering() {
+        if (!USE_DISPLAY_LIST_PROPERTIES) {
+            return super.hasOverlappingRendering();
+        } else {
+            return (getBackground() != null || mText instanceof Spannable || hasSelection());
+        }
+    }
+
     /**
      * When a TextView is used to display a useful piece of information to the user (such as a
      * contact's address), it should be made selectable, so that the user can select and copy this
@@ -5330,24 +5340,63 @@
                       physicalWidth, false);
     }
 
+    @Override
+    public void onResolvedLayoutDirectionReset() {
+        if (mLayoutAlignment != null) {
+            int resolvedTextAlignment = getResolvedTextAlignment();
+            if (resolvedTextAlignment == TEXT_ALIGNMENT_VIEW_START ||
+                 resolvedTextAlignment == TEXT_ALIGNMENT_VIEW_END) {
+                mLayoutAlignment = null;
+            }
+        }
+    }
+
     private Layout.Alignment getLayoutAlignment() {
         if (mLayoutAlignment == null) {
-            switch (mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) {
-                case Gravity.START:
+            int textAlign = getResolvedTextAlignment();
+            switch (textAlign) {
+                case TEXT_ALIGNMENT_GRAVITY:
+                    switch (mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) {
+                        case Gravity.START:
+                            mLayoutAlignment = Layout.Alignment.ALIGN_NORMAL;
+                            break;
+                        case Gravity.END:
+                            mLayoutAlignment = Layout.Alignment.ALIGN_OPPOSITE;
+                            break;
+                        case Gravity.LEFT:
+                            mLayoutAlignment = Layout.Alignment.ALIGN_LEFT;
+                            break;
+                        case Gravity.RIGHT:
+                            mLayoutAlignment = Layout.Alignment.ALIGN_RIGHT;
+                            break;
+                        case Gravity.CENTER_HORIZONTAL:
+                            mLayoutAlignment = Layout.Alignment.ALIGN_CENTER;
+                            break;
+                        default:
+                            mLayoutAlignment = Layout.Alignment.ALIGN_NORMAL;
+                            break;
+                    }
+                    break;
+                case TEXT_ALIGNMENT_TEXT_START:
                     mLayoutAlignment = Layout.Alignment.ALIGN_NORMAL;
                     break;
-                case Gravity.END:
+                case TEXT_ALIGNMENT_TEXT_END:
                     mLayoutAlignment = Layout.Alignment.ALIGN_OPPOSITE;
                     break;
-                case Gravity.LEFT:
-                    mLayoutAlignment = Layout.Alignment.ALIGN_LEFT;
-                    break;
-                case Gravity.RIGHT:
-                    mLayoutAlignment = Layout.Alignment.ALIGN_RIGHT;
-                    break;
-                case Gravity.CENTER_HORIZONTAL:
+                case TEXT_ALIGNMENT_CENTER:
                     mLayoutAlignment = Layout.Alignment.ALIGN_CENTER;
                     break;
+                case TEXT_ALIGNMENT_VIEW_START:
+                    mLayoutAlignment = (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
+                            Layout.Alignment.ALIGN_RIGHT : Layout.Alignment.ALIGN_LEFT;
+                    break;
+                case TEXT_ALIGNMENT_VIEW_END:
+                    mLayoutAlignment = (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
+                            Layout.Alignment.ALIGN_LEFT : Layout.Alignment.ALIGN_RIGHT;
+                    break;
+                case TEXT_ALIGNMENT_INHERIT:
+                    // This should never happen as we have already resolved the text alignment
+                    // but better safe than sorry so we just fall through
                 default:
                     mLayoutAlignment = Layout.Alignment.ALIGN_NORMAL;
                     break;
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 3115eff..f1dffa1 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -85,6 +85,8 @@
     private TabImpl mSelectedTab;
     private int mSavedTabPosition = INVALID_POSITION;
     
+    private boolean mDisplayHomeAsUpSet;
+
     ActionModeImpl mActionMode;
     ActionMode mDeferredDestroyActionMode;
     ActionMode.Callback mDeferredModeDestroyCallback;
@@ -375,11 +377,17 @@
     }
 
     public void setDisplayOptions(int options) {
+        if ((options & DISPLAY_HOME_AS_UP) != 0) {
+            mDisplayHomeAsUpSet = true;
+        }
         mActionView.setDisplayOptions(options);
     }
 
     public void setDisplayOptions(int options, int mask) {
         final int current = mActionView.getDisplayOptions(); 
+        if ((mask & DISPLAY_HOME_AS_UP) != 0) {
+            mDisplayHomeAsUpSet = true;
+        }
         mActionView.setDisplayOptions((options & mask) | (current & ~mask));
     }
 
@@ -1072,4 +1080,10 @@
     public void setLogo(Drawable logo) {
         mActionView.setLogo(logo);
     }
+
+    public void setDefaultDisplayHomeAsUpEnabled(boolean enable) {
+        if (!mDisplayHomeAsUpSet) {
+            setDisplayHomeAsUpEnabled(enable);
+        }
+    }
 }
diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java
index ccd2763..d59585f 100644
--- a/core/java/com/android/internal/net/NetworkStatsFactory.java
+++ b/core/java/com/android/internal/net/NetworkStatsFactory.java
@@ -16,7 +16,7 @@
 
 package com.android.internal.net;
 
-import static android.net.NetworkStats.SET_DEFAULT;
+import static android.net.NetworkStats.SET_ALL;
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
 import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
@@ -101,7 +101,7 @@
             while (reader.hasMoreData()) {
                 entry.iface = reader.nextString();
                 entry.uid = UID_ALL;
-                entry.set = SET_DEFAULT;
+                entry.set = SET_ALL;
                 entry.tag = TAG_NONE;
 
                 final boolean active = reader.nextInt() != 0;
@@ -165,7 +165,7 @@
 
             entry.iface = iface;
             entry.uid = UID_ALL;
-            entry.set = SET_DEFAULT;
+            entry.set = SET_ALL;
             entry.tag = TAG_NONE;
             entry.rxBytes = readSingleLongFromFile(new File(ifacePath, "rx_bytes"));
             entry.rxPackets = readSingleLongFromFile(new File(ifacePath, "rx_packets"));
@@ -193,7 +193,7 @@
                 try {
                     entry.iface = values.get(0);
                     entry.uid = UID_ALL;
-                    entry.set = SET_DEFAULT;
+                    entry.set = SET_ALL;
                     entry.tag = TAG_NONE;
                     entry.rxBytes = Long.parseLong(values.get(1));
                     entry.rxPackets = Long.parseLong(values.get(2));
diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java
index d462d7f..7c2b1b5 100644
--- a/core/java/com/android/internal/util/Protocol.java
+++ b/core/java/com/android/internal/util/Protocol.java
@@ -49,7 +49,7 @@
     public static final int BASE_DATA_CONNECTION                                    = 0x00040000;
     public static final int BASE_DATA_CONNECTION_AC                                 = 0x00041000;
     public static final int BASE_DATA_CONNECTION_TRACKER                            = 0x00042000;
-
     public static final int BASE_DNS_PINGER                                         = 0x00050000;
+    public static final int BASE_NSD_MANAGER                                        = 0x00060000;
     //TODO: define all used protocols
 }
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
new file mode 100644
index 0000000..c72c770
--- /dev/null
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+/** {@hide} */
+interface ILockSettings {
+    void setBoolean(in String key, in boolean value, in int userId);
+    void setLong(in String key, in long value, in int userId);
+    void setString(in String key, in String value, in int userId);
+    boolean getBoolean(in String key, in boolean defaultValue, in int userId);
+    long getLong(in String key, in long defaultValue, in int userId);
+    String getString(in String key, in String defaultValue, in int userId);
+    void setLockPattern(in byte[] hash, int userId);
+    boolean checkPattern(in byte[] hash, int userId);
+    void setLockPassword(in byte[] hash, int userId);
+    boolean checkPassword(in byte[] hash, int userId);
+    boolean havePattern(int userId);
+    boolean havePassword(int userId);
+    void removeUser(int userId);
+}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 93f90f6..4d308dd 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -21,15 +21,20 @@
 import com.google.android.collect.Lists;
 
 import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.PackageManager;
+import android.os.Binder;
 import android.os.FileObserver;
 import android.os.IBinder;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
+import android.os.UserId;
 import android.os.storage.IMountService;
 import android.provider.Settings;
 import android.security.KeyStore;
@@ -59,10 +64,6 @@
 
     private static final String TAG = "LockPatternUtils";
 
-    private static final String SYSTEM_DIRECTORY = "/system/";
-    private static final String LOCK_PATTERN_FILE = "gesture.key";
-    private static final String LOCK_PASSWORD_FILE = "password.key";
-
     /**
      * The maximum number of incorrect attempts before the user is prevented
      * from trying again for {@link #FAILED_ATTEMPT_TIMEOUT_MS}.
@@ -111,14 +112,14 @@
      */
     public static final int FLAG_BIOMETRIC_WEAK_LIVELINESS = 0x1;
 
-    private final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently";
-    private final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline";
-    private final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen";
+    protected final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently";
+    protected final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline";
+    protected final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen";
     public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type";
     public static final String PASSWORD_TYPE_ALTERNATE_KEY = "lockscreen.password_type_alternate";
-    private final static String LOCK_PASSWORD_SALT_KEY = "lockscreen.password_salt";
-    private final static String DISABLE_LOCKSCREEN_KEY = "lockscreen.disabled";
-    private final static String LOCKSCREEN_OPTIONS = "lockscreen.options";
+    protected final static String LOCK_PASSWORD_SALT_KEY = "lockscreen.password_salt";
+    protected final static String DISABLE_LOCKSCREEN_KEY = "lockscreen.disabled";
+    protected final static String LOCKSCREEN_OPTIONS = "lockscreen.options";
     public final static String LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK
             = "lockscreen.biometric_weak_fallback";
     public final static String BIOMETRIC_WEAK_EVER_CHOSEN_KEY
@@ -126,35 +127,13 @@
     public final static String LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS
             = "lockscreen.power_button_instantly_locks";
 
-    private final static String PASSWORD_HISTORY_KEY = "lockscreen.passwordhistory";
+    protected final static String PASSWORD_HISTORY_KEY = "lockscreen.passwordhistory";
 
     private final Context mContext;
     private final ContentResolver mContentResolver;
     private DevicePolicyManager mDevicePolicyManager;
-    private static String sLockPatternFilename;
-    private static String sLockPasswordFilename;
-
-    private static final AtomicBoolean sHaveNonZeroPatternFile = new AtomicBoolean(false);
-    private static final AtomicBoolean sHaveNonZeroPasswordFile = new AtomicBoolean(false);
-
-    private static FileObserver sPasswordObserver;
-
-    private static class PasswordFileObserver extends FileObserver {
-        public PasswordFileObserver(String path, int mask) {
-            super(path, mask);
-        }
-
-        @Override
-        public void onEvent(int event, String path) {
-            if (LOCK_PATTERN_FILE.equals(path)) {
-                Log.d(TAG, "lock pattern file changed");
-                sHaveNonZeroPatternFile.set(new File(sLockPatternFilename).length() > 0);
-            } else if (LOCK_PASSWORD_FILE.equals(path)) {
-                Log.d(TAG, "lock password file changed");
-                sHaveNonZeroPasswordFile.set(new File(sLockPasswordFilename).length() > 0);
-            }
-        }
-    }
+    private ILockSettings mLockSettingsService;
+    private int mCurrentUserId = 0;
 
     public DevicePolicyManager getDevicePolicyManager() {
         if (mDevicePolicyManager == null) {
@@ -167,34 +146,27 @@
         }
         return mDevicePolicyManager;
     }
+
     /**
      * @param contentResolver Used to look up and save settings.
      */
     public LockPatternUtils(Context context) {
         mContext = context;
         mContentResolver = context.getContentResolver();
+    }
 
-        // Initialize the location of gesture & PIN lock files
-        if (sLockPatternFilename == null) {
-            String dataSystemDirectory =
-                    android.os.Environment.getDataDirectory().getAbsolutePath() +
-                    SYSTEM_DIRECTORY;
-            sLockPatternFilename =  dataSystemDirectory + LOCK_PATTERN_FILE;
-            sLockPasswordFilename = dataSystemDirectory + LOCK_PASSWORD_FILE;
-            sHaveNonZeroPatternFile.set(new File(sLockPatternFilename).length() > 0);
-            sHaveNonZeroPasswordFile.set(new File(sLockPasswordFilename).length() > 0);
-            int fileObserverMask = FileObserver.CLOSE_WRITE | FileObserver.DELETE |
-                    FileObserver.MOVED_TO | FileObserver.CREATE;
-            sPasswordObserver = new PasswordFileObserver(dataSystemDirectory, fileObserverMask);
-            sPasswordObserver.startWatching();
+    private ILockSettings getLockSettings() {
+        if (mLockSettingsService == null) {
+            mLockSettingsService = ILockSettings.Stub.asInterface(
+                (IBinder) ServiceManager.getService("lock_settings"));
         }
+        return mLockSettingsService;
     }
 
     public int getRequestedMinimumPasswordLength() {
         return getDevicePolicyManager().getPasswordMinimumLength(null);
     }
 
-
     /**
      * Gets the device policy password mode. If the mode is non-specific, returns
      * MODE_PATTERN which allows the user to choose anything.
@@ -243,6 +215,33 @@
         getDevicePolicyManager().reportSuccessfulPasswordAttempt();
     }
 
+    public void setCurrentUser(int userId) {
+        if (Process.myUid() == Process.SYSTEM_UID) {
+            mCurrentUserId = userId;
+        } else {
+            throw new SecurityException("Only the system process can set the current user");
+        }
+    }
+
+    public void removeUser(int userId) {
+        if (Process.myUid() == Process.SYSTEM_UID) {
+            try {
+                getLockSettings().removeUser(userId);
+            } catch (RemoteException re) {
+                Log.e(TAG, "Couldn't remove lock settings for user " + userId);
+            }
+        }
+    }
+
+    private int getCurrentOrCallingUserId() {
+        int callingUid = Binder.getCallingUid();
+        if (callingUid == android.os.Process.SYSTEM_UID) {
+            return mCurrentUserId;
+        } else {
+            return UserId.getUserId(callingUid);
+        }
+    }
+
     /**
      * Check to see if a pattern matches the saved pattern.  If no pattern exists,
      * always returns true.
@@ -250,20 +249,10 @@
      * @return Whether the pattern matches the stored one.
      */
     public boolean checkPattern(List<LockPatternView.Cell> pattern) {
+        int userId = getCurrentOrCallingUserId();
         try {
-            // Read all the bytes from the file
-            RandomAccessFile raf = new RandomAccessFile(sLockPatternFilename, "r");
-            final byte[] stored = new byte[(int) raf.length()];
-            int got = raf.read(stored, 0, stored.length);
-            raf.close();
-            if (got <= 0) {
-                return true;
-            }
-            // Compare the hash from the file with the entered pattern's hash
-            return Arrays.equals(stored, LockPatternUtils.patternToHash(pattern));
-        } catch (FileNotFoundException fnfe) {
-            return true;
-        } catch (IOException ioe) {
+            return getLockSettings().checkPattern(patternToHash(pattern), userId);
+        } catch (RemoteException re) {
             return true;
         }
     }
@@ -275,20 +264,10 @@
      * @return Whether the password matches the stored one.
      */
     public boolean checkPassword(String password) {
+        int userId = getCurrentOrCallingUserId();
         try {
-            // Read all the bytes from the file
-            RandomAccessFile raf = new RandomAccessFile(sLockPasswordFilename, "r");
-            final byte[] stored = new byte[(int) raf.length()];
-            int got = raf.read(stored, 0, stored.length);
-            raf.close();
-            if (got <= 0) {
-                return true;
-            }
-            // Compare the hash from the file with the entered password's hash
-            return Arrays.equals(stored, passwordToHash(password));
-        } catch (FileNotFoundException fnfe) {
-            return true;
-        } catch (IOException ioe) {
+            return getLockSettings().checkPassword(passwordToHash(password), userId);
+        } catch (RemoteException re) {
             return true;
         }
     }
@@ -325,7 +304,11 @@
      * @return Whether a saved pattern exists.
      */
     public boolean savedPatternExists() {
-        return sHaveNonZeroPatternFile.get();
+        try {
+            return getLockSettings().havePattern(getCurrentOrCallingUserId());
+        } catch (RemoteException re) {
+            return false;
+        }
     }
 
     /**
@@ -333,7 +316,11 @@
      * @return Whether a saved pattern exists.
      */
     public boolean savedPasswordExists() {
-        return sHaveNonZeroPasswordFile.get();
+        try {
+            return getLockSettings().havePassword(getCurrentOrCallingUserId());
+        } catch (RemoteException re) {
+            return false;
+        }
     }
 
     /**
@@ -471,15 +458,7 @@
         // Compute the hash
         final byte[] hash = LockPatternUtils.patternToHash(pattern);
         try {
-            // Write the hash to file
-            RandomAccessFile raf = new RandomAccessFile(sLockPatternFilename, "rw");
-            // Truncate the file if pattern is null, to clear the lock
-            if (pattern == null) {
-                raf.setLength(0);
-            } else {
-                raf.write(hash, 0, hash.length);
-            }
-            raf.close();
+            getLockSettings().setLockPattern(hash, getCurrentOrCallingUserId());
             DevicePolicyManager dpm = getDevicePolicyManager();
             KeyStore keyStore = KeyStore.getInstance();
             if (pattern != null) {
@@ -505,13 +484,8 @@
                 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0,
                         0, 0, 0, 0, 0);
             }
-        } catch (FileNotFoundException fnfe) {
-            // Cant do much, unless we want to fail over to using the settings
-            // provider
-            Log.e(TAG, "Unable to save lock pattern to " + sLockPatternFilename);
-        } catch (IOException ioe) {
-            // Cant do much
-            Log.e(TAG, "Unable to save lock pattern to " + sLockPatternFilename);
+        } catch (RemoteException re) {
+            Log.e(TAG, "Couldn't save lock pattern " + re);
         }
     }
 
@@ -586,15 +560,7 @@
         // Compute the hash
         final byte[] hash = passwordToHash(password);
         try {
-            // Write the hash to file
-            RandomAccessFile raf = new RandomAccessFile(sLockPasswordFilename, "rw");
-            // Truncate the file if pattern is null, to clear the lock
-            if (password == null) {
-                raf.setLength(0);
-            } else {
-                raf.write(hash, 0, hash.length);
-            }
-            raf.close();
+            getLockSettings().setLockPassword(hash, getCurrentOrCallingUserId());
             DevicePolicyManager dpm = getDevicePolicyManager();
             KeyStore keyStore = KeyStore.getInstance();
             if (password != null) {
@@ -676,12 +642,9 @@
                 dpm.setActivePasswordState(
                         DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0);
             }
-        } catch (FileNotFoundException fnfe) {
-            // Cant do much, unless we want to fail over to using the settings provider
-            Log.e(TAG, "Unable to save lock pattern to " + sLockPasswordFilename);
-        } catch (IOException ioe) {
+        } catch (RemoteException re) {
             // Cant do much
-            Log.e(TAG, "Unable to save lock pattern to " + sLockPasswordFilename);
+            Log.e(TAG, "Unable to save lock password " + re);
         }
     }
 
@@ -1013,30 +976,57 @@
     }
 
     private boolean getBoolean(String secureSettingKey, boolean defaultValue) {
-        return 1 ==
-                android.provider.Settings.Secure.getInt(mContentResolver, secureSettingKey,
-                        defaultValue ? 1 : 0);
+        try {
+            return getLockSettings().getBoolean(secureSettingKey, defaultValue,
+                    getCurrentOrCallingUserId());
+        } catch (RemoteException re) {
+            return defaultValue;
+        }
     }
 
     private void setBoolean(String secureSettingKey, boolean enabled) {
-        android.provider.Settings.Secure.putInt(mContentResolver, secureSettingKey,
-                                                enabled ? 1 : 0);
+        try {
+            getLockSettings().setBoolean(secureSettingKey, enabled, getCurrentOrCallingUserId());
+        } catch (RemoteException re) {
+            // What can we do?
+            Log.e(TAG, "Couldn't write boolean " + secureSettingKey + re);
+        }
     }
 
-    private long getLong(String secureSettingKey, long def) {
-        return android.provider.Settings.Secure.getLong(mContentResolver, secureSettingKey, def);
+    private long getLong(String secureSettingKey, long defaultValue) {
+        try {
+            return getLockSettings().getLong(secureSettingKey, defaultValue,
+                    getCurrentOrCallingUserId());
+        } catch (RemoteException re) {
+            return defaultValue;
+        }
     }
 
     private void setLong(String secureSettingKey, long value) {
-        android.provider.Settings.Secure.putLong(mContentResolver, secureSettingKey, value);
+        try {
+            getLockSettings().setLong(secureSettingKey, value, getCurrentOrCallingUserId());
+        } catch (RemoteException re) {
+            // What can we do?
+            Log.e(TAG, "Couldn't write long " + secureSettingKey + re);
+        }
     }
 
     private String getString(String secureSettingKey) {
-        return android.provider.Settings.Secure.getString(mContentResolver, secureSettingKey);
+        try {
+            return getLockSettings().getString(secureSettingKey, null,
+                    getCurrentOrCallingUserId());
+        } catch (RemoteException re) {
+            return null;
+        }
     }
 
     private void setString(String secureSettingKey, String value) {
-        android.provider.Settings.Secure.putString(mContentResolver, secureSettingKey, value);
+        try {
+            getLockSettings().setString(secureSettingKey, value, getCurrentOrCallingUserId());
+        } catch (RemoteException re) {
+            // What can we do?
+            Log.e(TAG, "Couldn't write string " + secureSettingKey + re);
+        }
     }
 
     public boolean isSecure() {
diff --git a/core/java/com/android/internal/widget/LockSettingsService.java b/core/java/com/android/internal/widget/LockSettingsService.java
new file mode 100644
index 0000000..24c7161
--- /dev/null
+++ b/core/java/com/android/internal/widget/LockSettingsService.java
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.os.UserId;
+import android.provider.Settings;
+import android.provider.Settings.Secure;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.util.Arrays;
+
+/**
+ * Keeps the lock pattern/password data and related settings for each user.
+ * Used by LockPatternUtils. Needs to be a service because Settings app also needs
+ * to be able to save lockscreen information for secondary users.
+ * @hide
+ */
+public class LockSettingsService extends ILockSettings.Stub {
+
+    private final DatabaseHelper mOpenHelper;
+    private static final String TAG = "LockSettingsService";
+
+    private static final String TABLE = "locksettings";
+    private static final String COLUMN_KEY = "name";
+    private static final String COLUMN_USERID = "user";
+    private static final String COLUMN_VALUE = "value";
+
+    private static final String[] COLUMNS_FOR_QUERY = {
+        COLUMN_VALUE
+    };
+
+    private static final String SYSTEM_DIRECTORY = "/system/";
+    private static final String LOCK_PATTERN_FILE = "gesture.key";
+    private static final String LOCK_PASSWORD_FILE = "password.key";
+
+    private final Context mContext;
+
+    public LockSettingsService(Context context) {
+        mContext = context;
+        // Open the database
+        mOpenHelper = new DatabaseHelper(mContext);
+    }
+
+    public void systemReady() {
+        migrateOldData();
+    }
+
+    private void migrateOldData() {
+        try {
+            if (getString("migrated", null, 0) != null) {
+                // Already migrated
+                return;
+            }
+
+            final ContentResolver cr = mContext.getContentResolver();
+            for (String validSetting : VALID_SETTINGS) {
+                String value = Settings.Secure.getString(cr, validSetting);
+                if (value != null) {
+                    setString(validSetting, value, 0);
+                }
+            }
+            // No need to move the password / pattern files. They're already in the right place.
+            setString("migrated", "true", 0);
+            Slog.i(TAG, "Migrated lock settings to new location");
+        } catch (RemoteException re) {
+            Slog.e(TAG, "Unable to migrate old data");
+        }
+    }
+
+    private static final void checkWritePermission(int userId) {
+        final int callingUid = Binder.getCallingUid();
+        if (UserId.getAppId(callingUid) != android.os.Process.SYSTEM_UID) {
+            throw new SecurityException("uid=" + callingUid
+                    + " not authorized to write lock settings");
+        }
+    }
+
+    private static final void checkPasswordReadPermission(int userId) {
+        final int callingUid = Binder.getCallingUid();
+        if (UserId.getAppId(callingUid) != android.os.Process.SYSTEM_UID) {
+            throw new SecurityException("uid=" + callingUid
+                    + " not authorized to read lock password");
+        }
+    }
+
+    private static final void checkReadPermission(int userId) {
+        final int callingUid = Binder.getCallingUid();
+        if (UserId.getAppId(callingUid) != android.os.Process.SYSTEM_UID
+                && UserId.getUserId(callingUid) != userId) {
+            throw new SecurityException("uid=" + callingUid
+                    + " not authorized to read settings of user " + userId);
+        }
+    }
+
+    @Override
+    public void setBoolean(String key, boolean value, int userId) throws RemoteException {
+        checkWritePermission(userId);
+
+        writeToDb(key, value ? "1" : "0", userId);
+    }
+
+    @Override
+    public void setLong(String key, long value, int userId) throws RemoteException {
+        checkWritePermission(userId);
+
+        writeToDb(key, Long.toString(value), userId);
+    }
+
+    @Override
+    public void setString(String key, String value, int userId) throws RemoteException {
+        checkWritePermission(userId);
+
+        writeToDb(key, value, userId);
+    }
+
+    @Override
+    public boolean getBoolean(String key, boolean defaultValue, int userId) throws RemoteException {
+        //checkReadPermission(userId);
+
+        String value = readFromDb(key, null, userId);
+        return TextUtils.isEmpty(value) ?
+                defaultValue : (value.equals("1") || value.equals("true"));
+    }
+
+    @Override
+    public long getLong(String key, long defaultValue, int userId) throws RemoteException {
+        //checkReadPermission(userId);
+
+        String value = readFromDb(key, null, userId);
+        return TextUtils.isEmpty(value) ? defaultValue : Long.parseLong(value);
+    }
+
+    @Override
+    public String getString(String key, String defaultValue, int userId) throws RemoteException {
+        //checkReadPermission(userId);
+
+        return readFromDb(key, defaultValue, userId);
+    }
+
+    private String getLockPatternFilename(int userId) {
+        String dataSystemDirectory =
+                android.os.Environment.getDataDirectory().getAbsolutePath() +
+                SYSTEM_DIRECTORY;
+        if (userId == 0) {
+            // Leave it in the same place for user 0
+            return dataSystemDirectory + LOCK_PATTERN_FILE;
+        } else {
+            return  dataSystemDirectory + "users/" + userId + "/" + LOCK_PATTERN_FILE;
+        }
+    }
+
+    private String getLockPasswordFilename(int userId) {
+        String dataSystemDirectory =
+                android.os.Environment.getDataDirectory().getAbsolutePath() +
+                SYSTEM_DIRECTORY;
+        if (userId == 0) {
+            // Leave it in the same place for user 0
+            return dataSystemDirectory + LOCK_PASSWORD_FILE;
+        } else {
+            return  dataSystemDirectory + "users/" + userId + "/" + LOCK_PASSWORD_FILE;
+        }
+    }
+
+    @Override
+    public boolean havePassword(int userId) throws RemoteException {
+        // Do we need a permissions check here?
+
+        return new File(getLockPasswordFilename(userId)).length() > 0;
+    }
+
+    @Override
+    public boolean havePattern(int userId) throws RemoteException {
+        // Do we need a permissions check here?
+
+        return new File(getLockPatternFilename(userId)).length() > 0;
+    }
+
+    @Override
+    public void setLockPattern(byte[] hash, int userId) throws RemoteException {
+        checkWritePermission(userId);
+
+        writeFile(getLockPatternFilename(userId), hash);
+    }
+
+    @Override
+    public boolean checkPattern(byte[] hash, int userId) throws RemoteException {
+        checkPasswordReadPermission(userId);
+        try {
+            // Read all the bytes from the file
+            RandomAccessFile raf = new RandomAccessFile(getLockPatternFilename(userId), "r");
+            final byte[] stored = new byte[(int) raf.length()];
+            int got = raf.read(stored, 0, stored.length);
+            raf.close();
+            if (got <= 0) {
+                return true;
+            }
+            // Compare the hash from the file with the entered pattern's hash
+            return Arrays.equals(stored, hash);
+        } catch (FileNotFoundException fnfe) {
+            Slog.e(TAG, "Cannot read file " + fnfe);
+            return true;
+        } catch (IOException ioe) {
+            Slog.e(TAG, "Cannot read file " + ioe);
+            return true;
+        }
+    }
+
+    @Override
+    public void setLockPassword(byte[] hash, int userId) throws RemoteException {
+        checkWritePermission(userId);
+
+        writeFile(getLockPasswordFilename(userId), hash);
+    }
+
+    @Override
+    public boolean checkPassword(byte[] hash, int userId) throws RemoteException {
+        checkPasswordReadPermission(userId);
+
+        try {
+            // Read all the bytes from the file
+            RandomAccessFile raf = new RandomAccessFile(getLockPasswordFilename(userId), "r");
+            final byte[] stored = new byte[(int) raf.length()];
+            int got = raf.read(stored, 0, stored.length);
+            raf.close();
+            if (got <= 0) {
+                return true;
+            }
+            // Compare the hash from the file with the entered password's hash
+            return Arrays.equals(stored, hash);
+        } catch (FileNotFoundException fnfe) {
+            Slog.e(TAG, "Cannot read file " + fnfe);
+            return true;
+        } catch (IOException ioe) {
+            Slog.e(TAG, "Cannot read file " + ioe);
+            return true;
+        }
+    }
+
+    @Override
+    public void removeUser(int userId) {
+        checkWritePermission(userId);
+
+        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+        try {
+            File file = new File(getLockPasswordFilename(userId));
+            if (file.exists()) {
+                file.delete();
+            }
+            file = new File(getLockPatternFilename(userId));
+            if (file.exists()) {
+                file.delete();
+            }
+
+            db.beginTransaction();
+            db.delete(TABLE, COLUMN_USERID + "='" + userId + "'", null);
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+    }
+
+    private void writeFile(String name, byte[] hash) {
+        try {
+            // Write the hash to file
+            RandomAccessFile raf = new RandomAccessFile(name, "rw");
+            // Truncate the file if pattern is null, to clear the lock
+            if (hash == null || hash.length == 0) {
+                raf.setLength(0);
+            } else {
+                raf.write(hash, 0, hash.length);
+            }
+            raf.close();
+        } catch (IOException ioe) {
+            Slog.e(TAG, "Error writing to file " + ioe);
+        }
+    }
+
+    private void writeToDb(String key, String value, int userId) {
+        ContentValues cv = new ContentValues();
+        cv.put(COLUMN_KEY, key);
+        cv.put(COLUMN_USERID, userId);
+        cv.put(COLUMN_VALUE, value);
+
+        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+        db.beginTransaction();
+        try {
+            db.delete(TABLE, COLUMN_KEY + "=? AND " + COLUMN_USERID + "=?",
+                    new String[] {key, Integer.toString(userId)});
+            db.insert(TABLE, null, cv);
+            db.setTransactionSuccessful();
+        } finally {
+            db.endTransaction();
+        }
+    }
+
+    private String readFromDb(String key, String defaultValue, int userId) {
+        Cursor cursor;
+        String result = defaultValue;
+        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+        if ((cursor = db.query(TABLE, COLUMNS_FOR_QUERY,
+                COLUMN_USERID + "=? AND " + COLUMN_KEY + "=?",
+                new String[] { Integer.toString(userId), key },
+                null, null, null)) != null) {
+            if (cursor.moveToFirst()) {
+                result = cursor.getString(0);
+            }
+            cursor.close();
+        }
+        return result;
+    }
+
+    class DatabaseHelper extends SQLiteOpenHelper {
+        private static final String TAG = "LockSettingsDB";
+        private static final String DATABASE_NAME = "locksettings.db";
+
+        private static final int DATABASE_VERSION = 1;
+
+        public DatabaseHelper(Context context) {
+            super(context, DATABASE_NAME, null, DATABASE_VERSION);
+            setWriteAheadLoggingEnabled(true);
+        }
+
+        private void createTable(SQLiteDatabase db) {
+            db.execSQL("CREATE TABLE " + TABLE + " (" +
+                    "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
+                    COLUMN_KEY + " TEXT," +
+                    COLUMN_USERID + " INTEGER," +
+                    COLUMN_VALUE + " TEXT" +
+                    ");");
+        }
+
+        @Override
+        public void onCreate(SQLiteDatabase db) {
+            createTable(db);
+        }
+
+        @Override
+        public void onUpgrade(SQLiteDatabase db, int oldVersion, int currentVersion) {
+            // Nothing yet
+        }
+    }
+
+    private static final String[] VALID_SETTINGS = new String[] {
+        LockPatternUtils.LOCKOUT_PERMANENT_KEY,
+        LockPatternUtils.LOCKOUT_ATTEMPT_DEADLINE,
+        LockPatternUtils.PATTERN_EVER_CHOSEN_KEY,
+        LockPatternUtils.PASSWORD_TYPE_KEY,
+        LockPatternUtils.PASSWORD_TYPE_ALTERNATE_KEY,
+        LockPatternUtils.LOCK_PASSWORD_SALT_KEY,
+        LockPatternUtils.DISABLE_LOCKSCREEN_KEY,
+        LockPatternUtils.LOCKSCREEN_OPTIONS,
+        LockPatternUtils.LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK,
+        LockPatternUtils.BIOMETRIC_WEAK_EVER_CHOSEN_KEY,
+        LockPatternUtils.LOCKSCREEN_POWER_BUTTON_INSTANTLY_LOCKS,
+        LockPatternUtils.PASSWORD_HISTORY_KEY,
+        Secure.LOCK_PATTERN_ENABLED,
+        Secure.LOCK_BIOMETRIC_WEAK_FLAGS,
+        Secure.LOCK_PATTERN_VISIBLE,
+        Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED
+        };
+}
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 5e73a5f..3c27caf 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -236,7 +236,7 @@
                                0, 0, width, height, bitmap);

     }

 

-    return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff, isMutable, NULL);

+    return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff, isMutable, NULL, NULL);

 }

 

 static jobject Bitmap_copy(JNIEnv* env, jobject, const SkBitmap* src,

@@ -248,7 +248,7 @@
         return NULL;

     }

 

-    return GraphicsJNI::createBitmap(env, new SkBitmap(result), allocator.getStorageObj(), isMutable, NULL);

+    return GraphicsJNI::createBitmap(env, new SkBitmap(result), allocator.getStorageObj(), isMutable, NULL, NULL);

 }

 

 static void Bitmap_destructor(JNIEnv* env, jobject, SkBitmap* bitmap) {

@@ -407,7 +407,7 @@
     bitmap->unlockPixels();

 

     blob.release();

-    return GraphicsJNI::createBitmap(env, bitmap, buffer, isMutable, NULL, density);

+    return GraphicsJNI::createBitmap(env, bitmap, buffer, isMutable, NULL, NULL, density);

 }

 

 static jboolean Bitmap_writeToParcel(JNIEnv* env, jobject,

@@ -485,7 +485,7 @@
         env->ReleaseIntArrayElements(offsetXY, array, 0);

     }

 

-    return GraphicsJNI::createBitmap(env, dst, allocator.getStorageObj(), true, NULL);

+    return GraphicsJNI::createBitmap(env, dst, allocator.getStorageObj(), true, NULL, NULL);

 }

 

 ///////////////////////////////////////////////////////////////////////////////

diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index dcd1d28..dd59444 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -35,6 +35,7 @@
 jfieldID gOptions_mCancelID;
 jfieldID gOptions_bitmapFieldID;
 jfieldID gBitmap_nativeBitmapFieldID;
+jfieldID gBitmap_layoutBoundsFieldID;
 
 #if 0
     #define TRACE_BITMAP(code)  code
@@ -276,7 +277,7 @@
     }
 
     jbyteArray ninePatchChunk = NULL;
-    if (peeker.fPatchIsValid) {
+    if (peeker.fPatch != NULL) {
         if (willScale) {
             scaleNinePatchChunk(peeker.fPatch, scale);
         }
@@ -296,6 +297,18 @@
         env->ReleasePrimitiveArrayCritical(ninePatchChunk, array, 0);
     }
 
+    jintArray layoutBounds = NULL;
+    if (peeker.fLayoutBounds != NULL) {
+        layoutBounds = env->NewIntArray(4);
+        if (layoutBounds == NULL) {
+            return nullObjectReturn("layoutBounds == null");
+        }
+
+        env->SetIntArrayRegion(layoutBounds, 0, 4, (jint*) peeker.fLayoutBounds);
+        if (javaBitmap != NULL) {
+            env->SetObjectField(javaBitmap, gBitmap_layoutBoundsFieldID, layoutBounds);
+        }
+    }
     // detach bitmap from its autodeleter, since we want to own it now
     adb.detach();
 
@@ -321,7 +334,7 @@
     }
 
     if (padding) {
-        if (peeker.fPatchIsValid) {
+        if (peeker.fPatch != NULL) {
             GraphicsJNI::set_jrect(env, padding,
                     peeker.fPatch->paddingLeft, peeker.fPatch->paddingTop,
                     peeker.fPatch->paddingRight, peeker.fPatch->paddingBottom);
@@ -350,7 +363,7 @@
     }
     // now create the java bitmap
     return GraphicsJNI::createBitmap(env, bitmap, javaAllocator.getStorageObj(),
-            isMutable, ninePatchChunk);
+            isMutable, ninePatchChunk, layoutBounds, -1);
 }
 
 static jobject nativeDecodeStreamScaled(JNIEnv* env, jobject clazz, jobject is, jbyteArray storage,
@@ -576,7 +589,7 @@
     jclass bitmap_class = env->FindClass("android/graphics/Bitmap");
     SkASSERT(bitmap_class);
     gBitmap_nativeBitmapFieldID = getFieldIDCheck(env, bitmap_class, "mNativeBitmap", "I");
-
+    gBitmap_layoutBoundsFieldID = getFieldIDCheck(env, bitmap_class, "mLayoutBounds", "[I");
     int ret = AndroidRuntime::registerNativeMethods(env,
                                     "android/graphics/BitmapFactory$Options",
                                     gOptionsMethods,
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index 682877a..dd8e84f 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -244,7 +244,7 @@
 
     JavaPixelAllocator* allocator = (JavaPixelAllocator*) decoder->getAllocator();
     jbyteArray buff = allocator->getStorageObjAndReset();
-    return GraphicsJNI::createBitmap(env, bitmap, buff, false, NULL, -1);
+    return GraphicsJNI::createBitmap(env, bitmap, buff, false, NULL, NULL, -1);
 }
 
 static int nativeGetHeight(JNIEnv* env, jobject, SkBitmapRegionDecoder *brd) {
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index a1d41ee..d4c7600 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -345,14 +345,14 @@
 ///////////////////////////////////////////////////////////////////////////////////////////
 
 jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buffer,
-                                  bool isMutable, jbyteArray ninepatch, int density)
+                                  bool isMutable, jbyteArray ninepatch, jintArray layoutbounds,
+                                  int density)
 {
     SkASSERT(bitmap);
     SkASSERT(bitmap->pixelRef());
-
     jobject obj = env->NewObject(gBitmap_class, gBitmap_constructorMethodID,
             static_cast<jint>(reinterpret_cast<uintptr_t>(bitmap)),
-            buffer, isMutable, ninepatch, density);
+            buffer, isMutable, ninepatch, layoutbounds, density);
     hasException(env); // For the side effect of logging.
     return obj;
 }
@@ -360,7 +360,7 @@
 jobject GraphicsJNI::createBitmap(JNIEnv* env, SkBitmap* bitmap, bool isMutable,
                             jbyteArray ninepatch, int density)
 {
-    return createBitmap(env, bitmap, NULL, isMutable, ninepatch, density);
+    return createBitmap(env, bitmap, NULL, isMutable, ninepatch, NULL, density);
 }
 
 
@@ -587,7 +587,7 @@
     gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
     gBitmap_nativeInstanceID = getFieldIDCheck(env, gBitmap_class, "mNativeBitmap", "I");
     gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>",
-                                            "(I[BZ[BI)V");
+                                            "(I[BZ[B[II)V");
     gBitmapRegionDecoder_class = make_globalref(env, "android/graphics/BitmapRegionDecoder");
     gBitmapRegionDecoder_constructorMethodID = env->GetMethodID(gBitmapRegionDecoder_class, "<init>", "(I)V");
 
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index cc32f44..c5b06f5 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -53,7 +53,8 @@
         storage array (may be null).
     */
     static jobject createBitmap(JNIEnv* env, SkBitmap* bitmap, jbyteArray buffer,
-                                bool isMutable, jbyteArray ninepatch, int density = -1);
+                                bool isMutable, jbyteArray ninepatch, jintArray layoutbounds,
+                                int density = -1);
 
     static jobject createBitmap(JNIEnv* env, SkBitmap* bitmap, bool isMutable,
                                 jbyteArray ninepatch, int density = -1);
diff --git a/core/jni/android/graphics/NinePatchPeeker.cpp b/core/jni/android/graphics/NinePatchPeeker.cpp
index 365d985..df996af 100644
--- a/core/jni/android/graphics/NinePatchPeeker.cpp
+++ b/core/jni/android/graphics/NinePatchPeeker.cpp
@@ -31,14 +31,11 @@
         // this relies on deserialization being done in place
         Res_png_9patch::deserialize(patchNew);
         patchNew->fileToDevice();
-        if (fPatchIsValid) {
-            free(fPatch);
-        }
+        free(fPatch);
         fPatch = patchNew;
         //printf("9patch: (%d,%d)-(%d,%d)\n",
         //       fPatch.sizeLeft, fPatch.sizeTop,
         //       fPatch.sizeRight, fPatch.sizeBottom);
-        fPatchIsValid = true;
 
         // now update our host to force index or 32bit config
         // 'cause we don't want 565 predithered, since as a 9patch, we know
@@ -52,8 +49,9 @@
             SkBitmap::kARGB_8888_Config,
         };
         fHost->setPrefConfigTable(gNo565Pref);
-    } else {
-        fPatch = NULL;
+    } else if (strcmp("npLb", tag) == 0 && length == sizeof(int) * 4) {
+        fLayoutBounds = new int[4];
+        memcpy(fLayoutBounds, data, sizeof(int) * 4);
     }
     return true;    // keep on decoding
 }
diff --git a/core/jni/android/graphics/NinePatchPeeker.h b/core/jni/android/graphics/NinePatchPeeker.h
index 207536c..10d268a 100644
--- a/core/jni/android/graphics/NinePatchPeeker.h
+++ b/core/jni/android/graphics/NinePatchPeeker.h
@@ -28,17 +28,17 @@
     NinePatchPeeker(SkImageDecoder* host) {
         // the host lives longer than we do, so a raw ptr is safe
         fHost = host;
-        fPatchIsValid = false;
+        fPatch = NULL;
+        fLayoutBounds = NULL;
     }
 
     ~NinePatchPeeker() {
-        if (fPatchIsValid) {
-            free(fPatch);
-        }
+        free(fPatch);
+        delete fLayoutBounds;
     }
 
-    bool    fPatchIsValid;
     Res_png_9patch*  fPatch;
+    int    *fLayoutBounds;
 
     virtual bool peek(const char tag[], const void* data, size_t length);
 };
diff --git a/core/jni/android_view_GLES20DisplayList.cpp b/core/jni/android_view_GLES20DisplayList.cpp
index 60fb6d4..b307a2f 100644
--- a/core/jni/android_view_GLES20DisplayList.cpp
+++ b/core/jni/android_view_GLES20DisplayList.cpp
@@ -65,6 +65,11 @@
     displayList->setAlpha(alpha);
 }
 
+static void android_view_GLES20DisplayList_setHasOverlappingRendering(JNIEnv* env,
+        jobject clazz, DisplayList* displayList, bool hasOverlappingRendering) {
+    displayList->setHasOverlappingRendering(hasOverlappingRendering);
+}
+
 static void android_view_GLES20DisplayList_setTranslationX(JNIEnv* env,
         jobject clazz, DisplayList* displayList, float tx) {
     displayList->setTranslationX(tx);
@@ -185,6 +190,8 @@
     { "nSetAnimationMatrix",   "(II)V",  (void*) android_view_GLES20DisplayList_setAnimationMatrix },
     { "nSetClipChildren",      "(IZ)V",  (void*) android_view_GLES20DisplayList_setClipChildren },
     { "nSetAlpha",             "(IF)V",  (void*) android_view_GLES20DisplayList_setAlpha },
+    { "nSetHasOverlappingRendering", "(IZ)V",
+            (void*) android_view_GLES20DisplayList_setHasOverlappingRendering },
     { "nSetTranslationX",      "(IF)V",  (void*) android_view_GLES20DisplayList_setTranslationX },
     { "nSetTranslationY",      "(IF)V",  (void*) android_view_GLES20DisplayList_setTranslationY },
     { "nSetRotation",          "(IF)V",  (void*) android_view_GLES20DisplayList_setRotation },
diff --git a/packages/SystemUI/res/anim/status_bar_enter.xml b/core/res/res/anim/dock_bottom_enter.xml
similarity index 77%
copy from packages/SystemUI/res/anim/status_bar_enter.xml
copy to core/res/res/anim/dock_bottom_enter.xml
index f1c1301..7a2e94b 100644
--- a/packages/SystemUI/res/anim/status_bar_enter.xml
+++ b/core/res/res/anim/dock_bottom_enter.xml
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-/* //device/apps/common/res/anim/options_panel_enter.xml
-**
-** Copyright 2007, The Android Open Source Project
+/* 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. 
@@ -18,10 +16,11 @@
 */
 -->
 
+<!-- Animation for when a dock window at the bottom of the screen is entering. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@android:interpolator/decelerate_quad">
-	<translate android:fromYDelta="-75%" android:toYDelta="0"
+    <translate android:fromYDelta="75%" android:toYDelta="0"
         android:duration="@android:integer/config_mediumAnimTime"/>
-	<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
         android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/packages/SystemUI/res/anim/status_bar_exit.xml b/core/res/res/anim/dock_bottom_exit.xml
similarity index 78%
copy from packages/SystemUI/res/anim/status_bar_exit.xml
copy to core/res/res/anim/dock_bottom_exit.xml
index 46462e2..c2fd15c 100644
--- a/packages/SystemUI/res/anim/status_bar_exit.xml
+++ b/core/res/res/anim/dock_bottom_exit.xml
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-/* //device/apps/common/res/anim/options_panel_exit.xml
-**
-** Copyright 2007, The Android Open Source Project
+/* 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. 
@@ -18,10 +16,11 @@
 */
 -->
 
+<!-- Animation for when a dock window at the bottom of the screen is exiting. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@android:interpolator/accelerate_quad">
-	<translate android:fromYDelta="0" android:toYDelta="-75%"
+    <translate android:fromYDelta="0" android:toYDelta="75%"
         android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/>
-	<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+    <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
         android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/packages/SystemUI/res/anim/status_bar_enter.xml b/core/res/res/anim/dock_left_enter.xml
similarity index 77%
copy from packages/SystemUI/res/anim/status_bar_enter.xml
copy to core/res/res/anim/dock_left_enter.xml
index f1c1301..b057f67 100644
--- a/packages/SystemUI/res/anim/status_bar_enter.xml
+++ b/core/res/res/anim/dock_left_enter.xml
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-/* //device/apps/common/res/anim/options_panel_enter.xml
-**
-** Copyright 2007, The Android Open Source Project
+/* 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. 
@@ -18,10 +16,11 @@
 */
 -->
 
+<!-- Animation for when a dock window at the left of the screen is entering. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@android:interpolator/decelerate_quad">
-	<translate android:fromYDelta="-75%" android:toYDelta="0"
+    <translate android:fromXDelta="-75%" android:toXDelta="0"
         android:duration="@android:integer/config_mediumAnimTime"/>
-	<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
         android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/packages/SystemUI/res/anim/status_bar_exit.xml b/core/res/res/anim/dock_left_exit.xml
similarity index 78%
copy from packages/SystemUI/res/anim/status_bar_exit.xml
copy to core/res/res/anim/dock_left_exit.xml
index 46462e2..576b1aa 100644
--- a/packages/SystemUI/res/anim/status_bar_exit.xml
+++ b/core/res/res/anim/dock_left_exit.xml
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-/* //device/apps/common/res/anim/options_panel_exit.xml
-**
-** Copyright 2007, The Android Open Source Project
+/* 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. 
@@ -18,10 +16,11 @@
 */
 -->
 
+<!-- Animation for when a dock window at the right of the screen is exiting. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@android:interpolator/accelerate_quad">
-	<translate android:fromYDelta="0" android:toYDelta="-75%"
+    <translate android:fromXDelta="0" android:toXDelta="-75%"
         android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/>
-	<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+    <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
         android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/packages/SystemUI/res/anim/status_bar_enter.xml b/core/res/res/anim/dock_right_enter.xml
similarity index 77%
copy from packages/SystemUI/res/anim/status_bar_enter.xml
copy to core/res/res/anim/dock_right_enter.xml
index f1c1301..e1bd190 100644
--- a/packages/SystemUI/res/anim/status_bar_enter.xml
+++ b/core/res/res/anim/dock_right_enter.xml
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-/* //device/apps/common/res/anim/options_panel_enter.xml
-**
-** Copyright 2007, The Android Open Source Project
+/* 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. 
@@ -18,10 +16,11 @@
 */
 -->
 
+<!-- Animation for when a dock window at the right of the screen is entering. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@android:interpolator/decelerate_quad">
-	<translate android:fromYDelta="-75%" android:toYDelta="0"
+    <translate android:fromXDelta="75%" android:toXDelta="0"
         android:duration="@android:integer/config_mediumAnimTime"/>
-	<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
         android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/packages/SystemUI/res/anim/status_bar_exit.xml b/core/res/res/anim/dock_right_exit.xml
similarity index 78%
copy from packages/SystemUI/res/anim/status_bar_exit.xml
copy to core/res/res/anim/dock_right_exit.xml
index 46462e2..6d778fa 100644
--- a/packages/SystemUI/res/anim/status_bar_exit.xml
+++ b/core/res/res/anim/dock_right_exit.xml
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-/* //device/apps/common/res/anim/options_panel_exit.xml
-**
-** Copyright 2007, The Android Open Source Project
+/* 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. 
@@ -18,10 +16,11 @@
 */
 -->
 
+<!-- Animation for when a dock window at the right of the screen is exiting. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@android:interpolator/accelerate_quad">
-	<translate android:fromYDelta="0" android:toYDelta="-75%"
+    <translate android:fromXDelta="0" android:toXDelta="75%"
         android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/>
-	<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+    <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
         android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/packages/SystemUI/res/anim/status_bar_enter.xml b/core/res/res/anim/dock_top_enter.xml
similarity index 77%
rename from packages/SystemUI/res/anim/status_bar_enter.xml
rename to core/res/res/anim/dock_top_enter.xml
index f1c1301..f2e4cae 100644
--- a/packages/SystemUI/res/anim/status_bar_enter.xml
+++ b/core/res/res/anim/dock_top_enter.xml
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-/* //device/apps/common/res/anim/options_panel_enter.xml
-**
-** Copyright 2007, The Android Open Source Project
+/* Copyright 2007, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License"); 
 ** you may not use this file except in compliance with the License. 
@@ -18,10 +16,11 @@
 */
 -->
 
+<!-- Animation for when a dock window at the top of the screen is entering. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@android:interpolator/decelerate_quad">
-	<translate android:fromYDelta="-75%" android:toYDelta="0"
+    <translate android:fromYDelta="-75%" android:toYDelta="0"
         android:duration="@android:integer/config_mediumAnimTime"/>
-	<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
         android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/packages/SystemUI/res/anim/status_bar_exit.xml b/core/res/res/anim/dock_top_exit.xml
similarity index 78%
rename from packages/SystemUI/res/anim/status_bar_exit.xml
rename to core/res/res/anim/dock_top_exit.xml
index 46462e2..7373695 100644
--- a/packages/SystemUI/res/anim/status_bar_exit.xml
+++ b/core/res/res/anim/dock_top_exit.xml
@@ -1,8 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-/* //device/apps/common/res/anim/options_panel_exit.xml
-**
-** Copyright 2007, The Android Open Source Project
+/* Copyright 2007, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License"); 
 ** you may not use this file except in compliance with the License. 
@@ -18,10 +16,11 @@
 */
 -->
 
+<!-- Animation for when a dock window at the top of the screen is exiting. -->
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:interpolator="@android:interpolator/accelerate_quad">
-	<translate android:fromYDelta="0" android:toYDelta="-75%"
+    <translate android:fromYDelta="0" android:toYDelta="-75%"
         android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime"/>
-	<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
+    <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
         android:startOffset="100" android:duration="@android:integer/config_mediumAnimTime" />
 </set>
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
index fb62eb6..36d4a2a 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_password_portrait.xml
@@ -98,7 +98,7 @@
                     android:textAppearance="?android:attr/textAppearanceMedium"
                     android:background="@null"
                     android:textColor="#ffffffff"
-                    android:imeOptions="flagForceAscii"
+                    android:imeOptions="flagForceAscii|actionDone"
                 />
 
                 <!-- This delete button is only visible for numeric PIN entry -->
diff --git a/core/res/res/layout/keyguard_screen_unlock_portrait.xml b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
index 9a2e024..35b8665 100644
--- a/core/res/res/layout/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
@@ -173,13 +173,13 @@
     <RelativeLayout
         android:id="@+id/faceLockAreaView"
         android:visibility="invisible"
-        android:layout_row="4"
+        android:layout_row="3"
         android:layout_column="0"
-        android:layout_rowSpan="1"
+        android:layout_rowSpan="2"
         android:layout_columnSpan="1"
         android:layout_gravity="fill"
-        android:layout_marginTop="8dip"
-        android:layout_marginBottom="8dip"
+        android:layout_marginTop="4dip"
+        android:layout_marginBottom="4dip"
         android:layout_width="0dip"
         android:layout_height="0dip"
         android:background="@drawable/intro_bg">
diff --git a/core/res/res/layout/notification_template_base.xml b/core/res/res/layout/notification_template_base.xml
index 5b06460..b9710d6 100644
--- a/core/res/res/layout/notification_template_base.xml
+++ b/core/res/res/layout/notification_template_base.xml
@@ -28,7 +28,7 @@
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_gravity="center_vertical"
+        android:layout_gravity="fill_vertical"
         android:layout_marginLeft="@dimen/notification_large_icon_width"
         android:minHeight="@dimen/notification_large_icon_height"
         android:orientation="vertical"
@@ -36,6 +36,7 @@
         android:paddingRight="12dp"
         android:paddingTop="4dp"
         android:paddingBottom="4dp"
+        android:gravity="center_vertical"
         >
         <LinearLayout
             android:id="@+id/line1"
@@ -52,15 +53,21 @@
                 android:fadingEdge="horizontal"
                 android:layout_weight="1"
                 />
-            <DateTimeView android:id="@+id/time"
-                android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Time"
+            <ViewStub android:id="@+id/time"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center"
                 android:layout_weight="0"
-                android:singleLine="true"
-                android:gravity="center"
-                android:paddingLeft="8dp"
+                android:visibility="gone"
+                android:layout="@layout/notification_template_part_time"
+                />
+            <ViewStub android:id="@+id/chronometer"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:layout_weight="0"
+                android:visibility="gone"
+                android:layout="@layout/notification_template_part_chronometer"
                 />
         </LinearLayout>
         <TextView android:id="@+id/text2"
diff --git a/core/res/res/layout/notification_template_part_chronometer.xml b/core/res/res/layout/notification_template_part_chronometer.xml
new file mode 100644
index 0000000..382b0e4
--- /dev/null
+++ b/core/res/res/layout/notification_template_part_chronometer.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<Chronometer android:id="@+id/chronometer" xmlns:android="http://schemas.android.com/apk/res/android"
+    android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Time"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:layout_weight="0"
+    android:singleLine="true"
+    android:gravity="center"
+    android:paddingLeft="8dp"
+    />
diff --git a/core/res/res/layout/notification_template_part_time.xml b/core/res/res/layout/notification_template_part_time.xml
new file mode 100644
index 0000000..410fcaf
--- /dev/null
+++ b/core/res/res/layout/notification_template_part_time.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<DateTimeView android:id="@+id/time" xmlns:android="http://schemas.android.com/apk/res/android"
+    android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Time"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:layout_weight="0"
+    android:singleLine="true"
+    android:gravity="center"
+    android:paddingLeft="8dp"
+    />
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 203c335..d6073e3 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Voer \'n PUK van 8 syfers of langer in."</string>
     <string name="needPuk" msgid="919668385956251611">"Jou SIM-kaart is PUK-gesluit. Voer die PUK-kode in om dit te ontsluit."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Sleutel PUK2 in om SIM-kaart oop te sluit."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Inkomender beller-ID"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Uitgaande beller-ID"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Oproepaanstuur"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Stel tyd"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Stel datum"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Stel"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Verstek"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NUUT: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Geen toestemmings benodig nie"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Voeg \'n rekening by"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Watter rekening wil jy gebruik?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Voeg rekening by"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Verhoging"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Verminder"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> raak en hou."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Skuif op om by te tel en af om af te trek."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Tel \'n minuut by"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Trek \'n minuut af"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Tel \'n uur by."</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Trek \'n uur af"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Stel NM."</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Stel VM."</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Tel \'n maand by"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Trek \'n maand af"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Tel \'n dag by"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Trek \'n dag af."</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Tel \'n jaar by"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Trek \'n jaar af"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"gekontroleer"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"nie gekontroleer nie"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"gekies"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Deel met"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Deel met <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Skyfievatsel. Raak en hou."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Op na <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Af vir <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Links vir <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Regs vir <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Ontsluit"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Stil"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index ab937c5..2b98607 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -50,10 +50,8 @@
     <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>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"የገቢ ደዋይID"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"የወጪ ጥሪID"</string>
     <string name="CfMmi" msgid="5123218989141573515">"ጥሪ ማስተላለፍ"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"ጊዜ አዘጋጅ"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"ውሂብ አዘጋጅ"</string>
     <string name="date_time_set" msgid="5777075614321087758">"አዘጋጅ"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"ነባሪ"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"አዲስ፦ "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"ምንም ፍቃዶች አይጠየቁም"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"መለያ አክል"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"የትኛውን መለያ መጠቀም ትፈልጋለህ?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"መለያ አክል"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"ጨምር"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"ቀንስ"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> ንካ እና ያዝ።"</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"ለመጨመር ወደላይ ለመቀነስ ወደታች አንሸራት"</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"ደቂቃዎች ጨምር"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"ደቂቃ ቀንስ"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"ሰዓት ጨምር።"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"ሰዓት ቀንስ"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"PM አዘጋጅ"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"AM አዘጋጅ"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"ወር ጨምር"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"ወር ቀንስ"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"ቀን ጨምር"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"ቀን ቀንስ"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"አመት ጨምር"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"አመት ቀንስ"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"ታይቷል"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"አልተፈተሸም"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"የተመረጠ"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"ተጋራ ከ"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"ከ <xliff:g id="APPLICATION_NAME">%s</xliff:g> ጋር ተጋራ"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"ባለስላይድ መያዣ፡፡ ዳስ&amp;ያዝ፡፡"</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ወደላይ።"</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ወደታች።"</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ወደግራ።"</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ወደቀኝ።"</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"ክፈት"</string>
     <string name="description_target_camera" msgid="969071997552486814">"ካሜራ"</string>
     <string name="description_target_silent" msgid="893551287746522182">"ፀጥታ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index aca8f47..9c3ef5e 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"اكتب رمز PUK مكونًا من 8 أرقام أو أكثر."</string>
     <string name="needPuk" msgid="919668385956251611">"بطاقة SIM مؤمّنة بكود PUK. اكتب كود PUK لإلغاء تأمينها."</string>
     <string name="needPuk2" msgid="4526033371987193070">"اكتب PUK2 لإلغاء تأمين بطاقة SIM."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"معرف المتصل الوارد"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"معرف المتصل الصادر"</string>
     <string name="CfMmi" msgid="5123218989141573515">"إعادة توجيه الاتصال"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"تعيين الوقت"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"تعيين التاريخ"</string>
     <string name="date_time_set" msgid="5777075614321087758">"تعيين"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"افتراضي"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"جديد: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"لا أذونات مطلوبة"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"إضافة حساب"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"ما الحساب الذي تريد استخدامه؟"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"إضافة حساب"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"زيادة"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"تناقص"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> المس مع الاستمرار."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"مرر لأعلى للزيادة ولأسفل للإنقاص."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"زيادة دقيقة"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"إنقاص دقيقة"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"زيادة ساعة"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"إنقاص ساعة"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"تعيين المساء"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"تعيين الصباح"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"زيادة شهر"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"إنقاص شهر"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"زيادة يوم"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"إنقاص يوم"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"زيادة عام"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"إنقاص عام"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"تم التحديد"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"لم يتم التحديد"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"محدد"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"مشاركة مع"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"مشاركة مع <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"مقبض التمرير. المس مع الاستمرار."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"أعلى إلى <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"أسفل إلى <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"يسارًا إلى <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"يمينًا إلى <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"إلغاء تأمين"</string>
     <string name="description_target_camera" msgid="969071997552486814">"الكاميرا"</string>
     <string name="description_target_silent" msgid="893551287746522182">"صامت"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 4d304f1..dcb8f05 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Увядзіце PUK з 8 лічбаў ці больш."</string>
     <string name="needPuk" msgid="919668385956251611">"Ваша SIM-карта заблакавана PUK-кодам. Увядзіце PUK, каб разблакаваць карту."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Увядзіце PUK2 для разблакавання SIM-карты."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Ідэнтыфікатар АВН"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Ідэнтыфікатар АВН"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Пераадрасацыя выкліку"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Усталяваць час"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Усталяваць дату"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Задаць"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Па змаўчанні"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"НОВАЕ: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Дазволу не патрабуецца"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Дадаць уліковы запіс"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Які ўліковы запіс вы жадаеце выкарыстоўваць?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Дадаць уліковы запіс"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Інкрэмент"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Дэкрэмент"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Націсніце і ўтрымлівайце <xliff:g id="VALUE">%s</xliff:g>."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Перасуньце палец уверх, каб павялiчыць адрэзак, або ўніз, каб паменшыць."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"На хвiлiну больш"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"На хвiлiну менш"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"На гадзiну больш"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"На гадзiну менш"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Усталяваць час пасля паўдня"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Усталяваць час да паўдня"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"На месяц больш"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"На месяц менш"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"На дзень больш"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"На дзень менш."</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"На год больш"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"На год менш"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"пастаўлены"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"не пастаўлены"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"абрана"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Апублікаваць з дапамогай"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Адправiць з дапамогай прыкладання <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Ручка для перасоўвання. Націсніце і ўтрымлівайце."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Уверх да <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Уніз да <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Улева да <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Управа да <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Разблакаваць"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Камера"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Ціхі рэжым"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index b057cef..cee54b4 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Въведете PUK код с поне осем цифри."</string>
     <string name="needPuk" msgid="919668385956251611">"SIM картата ви е заключена с PUK. Въведете PUK кода, за да я отключите."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Въведете PUK2, за да отблокирате SIM картата."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Идентификация на вх. обаждания"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Идентификация на изходящите повиквания"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Пренасочване на повиквания"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Задаване на часа"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Задаване на дата"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Задаване"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"По подразбиране"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"НОВО: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Не се изискват разрешения"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Добавяне на профил"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Кой профил искате да използвате?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Добавяне на профил"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Увеличаване"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Намаляване"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Докоснете <xliff:g id="VALUE">%s</xliff:g> път/и и задръжте."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Плъзнете нагоре за увеличаване и надолу за намаляване."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Увеличаване на минутите"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Намаляване на минутите"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Увеличаване на часа"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Намаляване на часа"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Задаване на PM"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Задаване на AM"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Увеличаване на месеца"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Намаляване на месеца"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Увеличаване на деня"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Намаляване на деня"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Увеличаване на годината"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Намаляване на годината"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"отметнато"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"не е отметнато"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"избрано"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Споделяне със"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Споделяне със: <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Плъзгаща се дръжка. Докоснете и задръжте."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Нагоре за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Надолу за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Наляво за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Надясно за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Отключване"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Камера"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Тих режим"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 61c3cf0..e360af1 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Introdueix un PUK compost com a mínim de 8 nombres."</string>
     <string name="needPuk" msgid="919668385956251611">"La targeta SIM està bloquejada pel PUK. Escriviu el codi PUK per desbloquejar-la."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Escriviu el PUK2 per desbloquejar la targeta SIM."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Identificació de trucada entrant"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Identificació de trucada de sortida"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Desviació de trucades"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Estableix l\'hora"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Establiment de data"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Defineix"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Predeterminat"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NOU: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"No cal cap permís"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Addició d\'un compte"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Quin compte vols utilitzar?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Afegeix un compte"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Incrementa"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Disminueix"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Mantén premut <xliff:g id="VALUE">%s</xliff:g>."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Fes lliscar el dit cap amunt per incrementar i cap avall per disminuir."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Incrementa els minuts"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Disminueix els minuts"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Incrementa les hores"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Disminueix les hores"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Estableix com a p. m."</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Estableix com a a. m."</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Incrementa el mes"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Disminueix el mes"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Incrementa els dies"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Disminueix els dies"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Incrementa l\'any"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Disminueix l\'any"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"marcat"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"no marcat"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"seleccionat"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Comparteix amb"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Comparteix amb <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Llisca el dit. Mantén premut."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Cap amunt per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Cap avall per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Cap a l\'esquerra per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Cap a la dreta per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Desbloqueja"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Càmera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Silenci"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index ec640f7..ea206b0 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Zadejte osmimístný nebo delší kód PUK."</string>
     <string name="needPuk" msgid="919668385956251611">"Karta SIM je blokována pomocí kódu PUK. Odblokujete ji zadáním kódu PUK."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Chcete-li odblokovat kartu SIM, zadejte kód PUK2."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Příchozí identifikace volajícího"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Odchozí identifikace volajícího"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Přesměrování hovorů"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Nastavení času"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Nastavení data"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Nastavit"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Výchozí"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NOVÉ: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Nejsou vyžadována žádná oprávnění"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Přidat účet"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Který účet chcete použít?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Přidat účet"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Zvýšení"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Snížení"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> dotkněte se a podržte."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Chcete-li přičítat, přejeďte prstem nahoru, chcete-li odečítat, přejeďte prstem dolů."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Přičíst minutu"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Odečíst minutu"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Přičíst hodinu"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Odečíst hodinu"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Nastavit odp."</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Nastavit dop."</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Přičíst měsíc"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Odečíst měsíc"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Přičíst den"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Odečíst den"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Přičíst rok"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Odečíst rok"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"zaškrtnuto"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"nezaškrtnuto"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"Vybráno"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Sdílet s"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Sdílet s aplikací <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Posuvník. Dotkněte se a podržte."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> – nahoru."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> – dolů."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> – vlevo."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> – vpravo."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Odemknout"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Fotoaparát"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Tichý"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index d72364b..94c2999 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Angiv en PUK-kode på 8 eller flere cifre."</string>
     <string name="needPuk" msgid="919668385956251611">"Dit SIM-kort er låst med PUK-koden. Indtast PUK-koden for at låse den op."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Indtast PUK2-koden for at låse op for SIM-kortet."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI-nummer"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Indgående opkalds-id"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Udgående opkalds-id"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Viderestilling af opkald"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Angiv tidspunkt"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Angiv dato"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Angiv"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Standard"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NYHED! "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Der kræves ingen tilladelser"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Tilføj en konto"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Hvilken konto vil du bruge?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Tilføj konto"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Optælling"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Nedtælling"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Tryk <xliff:g id="VALUE">%s</xliff:g> gange, og hold inde."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Glid op for at tilføje, og glid ned for at fjerne."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Tilføj minut"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Fjern minut"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Tilføj time"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Fjern time"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Indstil PM"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Indstil AM"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Tilføj måned"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Fjern måned"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Tilføj dag"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Fjern dag"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Tilføj år"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Fjern år"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"markeret"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"ikke markeret"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"udvalgt"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Del med"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Del med <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Glidende håndtag. Tryk og hold nede."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Op for at <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Ned for at <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Til venstre for at <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Til højre for at <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Lås op"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Lydløs"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index defd850..82a60d2 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Geben Sie eine mindestens achtstellige PUK ein."</string>
     <string name="needPuk" msgid="919668385956251611">"Ihre SIM-Karte ist mit einem PUK gesperrt. Geben Sie zum Entsperren den PUK-Code ein."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Geben Sie zum Entsperren der SIM-Karte den PUK2 ein."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Anrufer-ID für eingehenden Anruf"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Anrufer-ID für ausgehenden Anruf"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Rufweiterleitung"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Uhrzeit festlegen"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Datum festlegen"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Speichern"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Standard"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"Neu: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Keine Berechtigungen erforderlich"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Konto hinzufügen"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Welches Konto möchten Sie verwenden?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Konto hinzufügen"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Erhöhen"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Verringern"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> berühren und gedrückt halten"</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Zum Vorstellen nach oben und zum Zurückstellen nach unten ziehen"</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Minute vorstellen"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Minute zurückstellen"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Stunde vorstellen"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Stunde zurückstellen"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Zeit festlegen"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Zeit festlegen"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Monat vorstellen"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Monat zurückstellen"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Tag vorstellen"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Tag zurückstellen"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Jahr vorstellen"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Jahr zurückstellen"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"Aktiviert"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"Nicht aktiviert"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"Ausgewählt"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Teilen mit"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Mit <xliff:g id="APPLICATION_NAME">%s</xliff:g> teilen"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Schieberegler: Berühren und halten"</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Für <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> nach oben"</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Für <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> nach unten"</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Für <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> nach links"</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Für <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> nach rechts"</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Entsperren"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Lautlos"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 71547ce..b9710e5 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Πληκτρολογήστε έναν κωδικό PUK με 8 αριθμούς ή περισσότερους."</string>
     <string name="needPuk" msgid="919668385956251611">"Η κάρτα SIM έχει κλειδωθεί με κωδικό PUK. Πληκτρολογήστε τον κωδικό PUK για να την ξεκλειδώσετε."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Πληκτρολογήστε τον κωδικό PUK2 για την κατάργηση αποκλεισμού της κάρτας SIM."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Εισερχόμενη αναγνώριση κλήσης"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Εξερχόμενη αναγνώριση κλήσης"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Προώθηση κλήσεων"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Ρύθμιση ώρας"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Ορισμός ημερομηνίας"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Ορισμός"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Προεπιλεγμένο"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"ΝΕΟ: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Δεν απαιτούνται άδειες"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Προσθήκη λογαριασμού"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Ποιον λογαριασμό θέλετε να χρησιμοποιήσετε;"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Προσθήκη λογαριασμού"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Αύξηση"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Μείωση"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Πατήστε παρατεταμένα το <xliff:g id="VALUE">%s</xliff:g>."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Πραγματοποιήστε κύλιση προς τα πάνω για αύξηση και προς τα κάτω για μείωση."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Αύξηση λεπτού"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Μείωση λεπτού"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Αύξηση ώρας"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Μείωση ώρας"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Ορισμός ΜΜ"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Ορισμός ΠΜ"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Επόμενος μήνας"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Προηγούμενος μήνας"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Επόμενη ημέρα"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Προηγούμενη μέρα"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Αύξηση έτους"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Προηγούμενο έτος"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"ελέγχθηκε"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"δεν επιλέχθηκε"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"επιλεγμένο"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Κοινή χρήση με"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Κοινή χρήση με <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Στοιχείο χειρισμού με δυνατότητα ολίσθησης. Αγγίξτε και πατήστε παρατεταμένα."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Κύλιση πάνω <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Κύλιση κάτω για <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Κύλιση αριστερά για <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Κύλιση δεξιά <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Ξεκλείδωμα"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Φωτογραφική μηχανή"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Αθόρυβο"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index b070e02..c41f2be 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Type a PUK that is 8 numbers or longer."</string>
     <string name="needPuk" msgid="919668385956251611">"Your SIM card is PUK-locked. Type the PUK code to unlock it."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Type PUK2 to unblock SIM card."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Incoming Caller ID"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Outgoing Caller ID"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Call forwarding"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Set time"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Set date"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Set"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Default"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NEW: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"No permission required"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Add an account"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Which account do you want to use?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Add account"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Increment"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Decrement"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> touch and hold."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Slide up to increment and down to decrease."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Increment minute"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Decrement minute"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Increment hour"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Decrement hour"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Set p.m."</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Set a.m."</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Increment month"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Decrement month"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Increment day"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Decrement day"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Increment year"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Decrement year"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"ticked"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"not ticked"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"selected"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Share with"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Share with <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Sliding handle. Touch &amp; hold."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Up for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Down for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Left for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Right for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Unlock"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Camera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Silent"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 8de6b8c0..19e8e25 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Ingresa un código PUK de ocho números o más."</string>
     <string name="needPuk" msgid="919668385956251611">"Tu tarjeta SIM está bloqueada con PUK. Escribe el código PUK para desbloquearla."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Escribir PUK2 para desbloquear la tarjeta SIM."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Identificador de llamadas entrantes"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Identificador de llamadas salientes"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Desvío de llamadas"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Configurar hora"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Configurar fecha"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Establecer"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Predeterminado"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NUEVO: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"No se requieren permisos"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Agregar una cuenta"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"¿Qué cuenta quieres usar?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Agregar una cuenta"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Incremento"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Decremento"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Mantén presionado <xliff:g id="VALUE">%s</xliff:g>."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Deslízate hacia arriba para aumentar y hacia abajo para disminuir."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Aumentar minutos"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Disminuir minutos"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Aumentar horas"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Disminuir horas"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Establecer p.m."</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Establecer a.m."</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Aumentar mes"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Disminuir mes"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Aumentar día"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Disminuir día"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Aumentar año"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Disminuir año"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"marcado"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"no marcado"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"seleccionado"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Compartir con"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Compartir con <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Mantén presionado el controlador deslizante."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Hacia arriba para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Hacia abajo para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Hacia la izquierda para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Hacia la derecha para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Desbloquear"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Cámara"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Silencioso"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index b76053f..c732ab9 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Escribe un código PUK de ocho caracteres o más."</string>
     <string name="needPuk" msgid="919668385956251611">"La tarjeta SIM está bloqueada con el código PUK. Introduce el código PUK para desbloquearla."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Introduce el código PUK2 para desbloquear la tarjeta SIM."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"ID de emisor de llamada entrante"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"ID de emisor de llamada saliente"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Desvío de llamada"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Establecer hora"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Establecer fecha"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Establecer"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Predeterminado"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NUEVO:"</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"No es necesario ningún permiso"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Añadir una cuenta"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"¿Qué cuenta quieres usar?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Añadir cuenta"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Aumentar"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Disminuir"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Mantén pulsado <xliff:g id="VALUE">%s</xliff:g>."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Desliza el dedo hacia arriba para aumentar y hacia abajo para disminuir."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Aumentar minuto"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Disminuir minuto"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Aumentar hora"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Disminuir hora"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Establecer p.m."</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Establecer a.m."</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Aumentar mes"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Disminuir mes"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Aumentar día"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Disminuir día"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Aumentar año"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Disminuir año"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"seleccionado"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"no seleccionado"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"seleccionado"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Compartir con"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Compartir con <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Mantén pulsado el icono de desbloqueo y deslízalo."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Hacia arriba para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Hacia abajo para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Hacia la izquierda para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Hacia la derecha para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Desbloquear"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Cámara"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Silencio"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 38c9251..890dd7b 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Sisestage 8- või enamanumbriline PUK-kood."</string>
     <string name="needPuk" msgid="919668385956251611">"SIM-kaart on PUK-lukustatud. Avamiseks sisestage PUK-kood."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Sisestage SIM-kaardi blokeeringu tühistamiseks PUK2-kood."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Sissetuleva kõne helistaja ID"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Väljuva kõne helistaja ID"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Kõnede suunamine"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Kellaaja määramine"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Kuupäeva määramine"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Määra"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Vaikimisi"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"UUS: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Lube pole vaja"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Konto lisamine"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Millist kontot soovite kasutada?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Lisa konto"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Suurenda"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Vähenda"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> puudutage ja hoidke."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Suurendamiseks lohistage üles, vähendamiseks alla."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Minutite arvu suurendamine"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Minutite arvu vähendamine"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Tundide arvu suurendamine"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Tundide arvu vähendamine"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"PM-i seadmine"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"AM-i seadmine"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Järgmine kuu"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Eelmine kuu"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Järgmine päev"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Eelmine päev"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Aastaarvu suurendamine"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Aastaarvu vähendamine"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"märgitud"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"pole märgitud"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"valitud"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Jaga:"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Jaga rakendusega <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Libistamispide. Puudutage ja hoidke all."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Üles – <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Alla – <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Vasakule – <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Paremale – <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Luku avamine"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Kaamera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Hääletu"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 5a50a8f..ce26f1e 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"یک PUK با 8 رقم یا بیشتر تایپ کنید."</string>
     <string name="needPuk" msgid="919668385956251611">"سیم کارت شما با PUK قفل شده است. کد PUK را برای بازگشایی آن بنویسید."</string>
     <string name="needPuk2" msgid="4526033371987193070">"PUK2 را برای بازگشایی قفل سیم کارت بنویسید."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"شناسه تماس گیرنده ورودی"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"شناسه تماس گیرنده خروجی"</string>
     <string name="CfMmi" msgid="5123218989141573515">"هدایت تماس"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"تنظیم زمان"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"تاریخ تنظیم"</string>
     <string name="date_time_set" msgid="5777075614321087758">"تنظیم"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"پیش فرض"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"جدید: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"مجوزی لازم نیست"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"افزودن یک حساب"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"کدام حساب را می‎خواهید استفاده کنید؟"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"افزودن حساب"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"افزایش"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"کاهش"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> لمس کرده و نگه دارید."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"برای افزایش به بالا و برای کاهش به پایین بلغزانید."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">" افزایش دقیقه"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"کاهش دقیقه"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"افزایش ساعت"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"کاهش ساعت"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"تنظیم ب.ظ"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"تنظیم ق.ظ"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"ماه افزایشی"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"کاهش ماه"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"افزایش روز"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"کاهش روز"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"افزایش سال"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"کاهش سال"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"علامت زده"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"بدون علامت"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"انتخاب شد"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"اشتراک‌گذاری با"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"اشتراک‌گذاری با <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"اهرم کنترل حرکت. لمس کرده و نگهدارید."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"بالا برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"پایین برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"چپ برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"راست برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"بازکردن قفل"</string>
     <string name="description_target_camera" msgid="969071997552486814">"دوربین"</string>
     <string name="description_target_silent" msgid="893551287746522182">"ساکت"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 6d849dd..54e1a1b 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Kirjoita vähintään 8 numeron pituinen PUK-koodi."</string>
     <string name="needPuk" msgid="919668385956251611">"SIM-korttisi on PUK-lukittu. Poista lukitus antamalla PUK-koodi."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Pura SIM-kortin esto antamalla PUK2-koodi."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI-koodi"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Soittajan tunnus"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Soittajan tunnus"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Soitonsiirto"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Aseta aika"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Aseta päivämäärä"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Aseta"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Oletus"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"UUTTA: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Lupia ei tarvita"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Lisää tili"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Mitä tiliä haluat käyttää?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Lisää tili"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Lisää"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Vähennä"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> kosketa pitkään."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Kasvata tai pienennä arvoa liu\'uttamalla ylös tai alas."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Kasvata minuuttia"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Pienennä minuuttia"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Kasvata tuntia"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Pienennä tuntia"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Aseta ip"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Aseta ap"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Kasvata kuukautta"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Vähennä kuukautta"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Kasvata päivää"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Pienennä päivää"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Kasvata vuotta"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Pienennä vuotta"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"valittu"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"ei valittu"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"valittu"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Jaa seuraavien kanssa:"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Jaa sovelluksessa <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Liukuva valitsin. Kosketa pitkään."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Ylös: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Alas: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Vasemmalle: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Oikealle: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Poista lukitus"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Äänetön"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 548d66b..d4a6f5b 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Saisissez un code PUK comportant au moins huit chiffres."</string>
     <string name="needPuk" msgid="919668385956251611">"Votre carte SIM est verrouillée par clé PUK. Saisissez la clé PUK pour la déverrouiller."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Saisissez la clé PUK2 pour débloquer la carte SIM."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"Code IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"Code MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Numéro de l\'appelant (entrant)"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Numéro de l\'appelant (sortant)"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Transfert d\'appel"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Définir l\'heure"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Définir la date"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Définir"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Par défaut"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NOUVEAU"</font>" :"</string>
     <string name="no_permissions" msgid="7283357728219338112">"Aucune autorisation requise"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Ajouter un compte"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Quel compte souhaitez-vous utiliser ?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Ajouter un compte"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Augmenter"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Diminuer"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> appuyez de manière prolongée."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Faire glisser vers le haut pour augmenter et vers le bas pour diminuer"</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Minute suivante"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Minute précédente"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Heure suivante"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Heure précédente"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Définir la valeur PM"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Définir la valeur AM"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Mois suivant"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Mois précédent"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Jour suivant"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Jour précédent"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Année suivante"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Année précédente"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"coché"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"non coché"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"sélectionné"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Partager avec"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Partager avec <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Poignée coulissante. Appuyez de manière prolongée."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Vers le haut pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Vers le bas pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Vers la gauche pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Vers la droite pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Déverrouiller"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Appareil photo"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Mode silencieux"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index be85378..d84915e 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"ऐसा PUK लिखें जो 8 अंकों या अधिक का हो."</string>
     <string name="needPuk" msgid="919668385956251611">"आपका सिम कार्ड PUK लॉक किया गया है. इसे अनलॉक करने के लिए PUK कोड लिखें."</string>
     <string name="needPuk2" msgid="4526033371987193070">"सिम कार्ड अनब्‍लॉक करने के लिए PUK2 लिखें."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"इनकमिंग कॉलर ID"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"आउटगोइंग कॉलर ID"</string>
     <string name="CfMmi" msgid="5123218989141573515">"कॉल अग्रेषण"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"समय सेट करें"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"दिनांक सेट करें"</string>
     <string name="date_time_set" msgid="5777075614321087758">"सेट करें"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"डिफ़ॉल्ट"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"नया: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"किसी अनुमति की आवश्‍यकता नहीं है"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"कोई खाता जोड़ें"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"आप कौन-सा खाता उपयोग करना चाहते हैं?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"खाता जोड़ें"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"वृद्धि"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"कमी"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> को स्‍पर्श करके रखें."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"बढ़ते क्रम के लिए ऊपर और घटते क्रम के लिए नीचे की ओर स्‍लाइड करें."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"बढ़ते क्रम में मिनट"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"घटते क्रम में मिनट"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"बढ़ते क्रम में घंटा"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"घटते क्रम में घंटा"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"सायं सेट करें"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"प्रात: सेट करें"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"बढ़ते क्रम में माह"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"घटते क्रम में माह"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"बढ़ते क्रम में दिन"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"घटते क्रम में दिन"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"बढ़ते क्रम में वर्ष"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"घटते क्रम में वर्ष"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"चेक किया गया"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"चेक नहीं किया गया"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"चयनित"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"इसके साथ साझा करें:"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> के साथ साझा करें"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"स्लाइडिंग हैंडल. स्पर्श करके रखें."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए ऊपर."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए नीचे."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए बाएं."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए दाएं."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"अनलॉक करें"</string>
     <string name="description_target_camera" msgid="969071997552486814">"कैमरा"</string>
     <string name="description_target_silent" msgid="893551287746522182">"मौन"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index a30a5e0..b0ebc8a 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Upišite PUK koji se sastoji od barem 8 brojeva."</string>
     <string name="needPuk" msgid="919668385956251611">"Vaša je SIM kartica zaključana PUK-om. Unesite PUK kôd da biste je otključali."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Unesite PUK2 da biste odblokirali SIM karticu."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"ID dolaznog pozivatelja"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"ID izlaznog pozivatelja"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Preusmjeravanje poziva"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Postavljanje vremena"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Postavi datum"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Postavi"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Zadano"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NOVO: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Nije potrebno dopuštenje"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Dodajte račun"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Koji račun želite upotrijebiti?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Dodaj račun"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Povećaj"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Smanji"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> pritisnite i držite."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Klizite prema gore za pomak unaprijed, a prema dolje za pomak unatrag."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Pomak unaprijed za jednu minutu"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Pomak unatrag za jednu minutu"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Pomak unaprijed za jedan sat"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Pomak unatrag za jedan sat"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Postavi PM"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Postavi AM"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Pomak unaprijed za jedan mjesec"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Pomak unatrag za jedan mjesec"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Pomak unaprijed za jedan dan"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Pomak unatrag za jedan dan"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Pomak unaprijed za jednu godinu"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Pomak unatrag za jednu godinu"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"označeno"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"nije označeno"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"odabran"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Dijeljenje sa"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Dijeli s aplikacijom <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Klizna ručka. Dodirnite i držite."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Gore za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Dolje za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Lijevo za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Desno za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Otključaj"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Fotoaparat"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Bešumno"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index f6fd651..5e3464d 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"8 számjegyű vagy hosszabb PUK kódot írjon be."</string>
     <string name="needPuk" msgid="919668385956251611">"A SIM-kártya le van zárva a PUK-kóddal. A feloldáshoz adja meg a PUK-kódot."</string>
     <string name="needPuk2" msgid="4526033371987193070">"A SIM-kártya feloldásához adja meg a PUK2-kódot."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Beérkező hívóazonosító"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Kimenő hívóazonosító"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Hívásátirányítás"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Idő beállítása"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Dátum beállítása"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Beállítás"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Alapértelmezett"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"ÚJ: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Nincs szükség engedélyre"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Fiók hozzáadása"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Melyik fiókot szeretné használni?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Fiók hozzáadása"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Növelés"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Csökkentés"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> érintse meg és tartsa lenyomva."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Csúsztassa fel a növeléshez és le a csökkentéshez."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Percek növelése"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Percek csökkentése"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Órák növelése"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Órák csökkentése"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Állítsa du. értékre"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Állítsa de. értékre"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Hónapok növelése"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Hónapok csökkentése"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Napok növelése"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Napok csökkentése"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Évek növelése"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Évek csökkentése"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"bejelölve"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"nincs bejelölve"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"bejelölve"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Megosztás a következővel:"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Ossza meg a következő alkalmazással: <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Csúsztatható fogantyú. Érintse meg és tartsa."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Fel: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Le: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Balra: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Jobbra: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Feloldás"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Némítás"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 4a142083..4fb25c1 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Ketik PUK yang terdiri dari 8 angka atau lebih."</string>
     <string name="needPuk" msgid="919668385956251611">"Kartu SIM Anda dikunci PUK. Ketikkan kode PUK untuk membukanya."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Ketikkan PUK2 untuk membuka kartu SIM"</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Nomor Penelepon Masuk"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Nomor Penelepon Keluar"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Penerusan panggilan"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Setel waktu"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Setel tanggal"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Setel"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Default"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"BARU: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Tidak perlu izin"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Tambahkan akun"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Akun mana yang ingin Anda gunakan?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Tambahkan akun"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Penambahan"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Pengurangan"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> sentuh dan tahan."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Geser ke atas untuk menambah dan ke bawah untuk mengurangi."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Menit penambahan"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Menit pengurangan"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Jam penambahan"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Jam pengurangan"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Menyetel PM"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Setel AM"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Bulan penambahan"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Bulan pengurangan"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Hari penambahan"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Hari pengurangan"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Tahun penambahan"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Tahun pengurangan"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"dicentang"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"tidak diperiksa"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"dipilih"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Berbagi dengan"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Berbagi dengan <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Gagang geser. Sentuh &amp; tahan."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Ke atas untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Ke bawah untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Ke kiri untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Ke kanan untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Membuka gembok"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Senyap"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index c682a85..7f399be 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Digita un PUK formato da almeno 8 numeri."</string>
     <string name="needPuk" msgid="919668385956251611">"La SIM è bloccata tramite PUK. Digita il codice PUK per sbloccarla."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Digita il PUK2 per sbloccare la SIM."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"ID chiamante in entrata"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"ID chiamante in uscita"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Deviazione chiamate"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Imposta ora"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Imposta data"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Imposta"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Predefinito"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NUOVA: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Nessuna autorizzazione richiesta"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Aggiungi un account"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Quale account vuoi usare?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Aggiungi account"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Aumenta"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Diminuisci"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Tocca e tieni premuto il numero <xliff:g id="VALUE">%s</xliff:g>."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Scorri verso l\'alto per aumentare il valore e verso il basso per diminuirlo."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Aumenta minuto"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Diminuisci minuto"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Aumenta ora"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Diminuisci ora"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Imposta PM"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Imposta AM"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Aumenta mese"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Diminuisci mese"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Aumenta giorno"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Diminuisci giorno"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Aumenta anno"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Diminuisci anno"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"selezionata"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"non selezionato"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"selezionato"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Condividi con"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Condividi con <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Maniglia scorrevole. Tocca e tieni premuto."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Su per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Giù per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"A sinistra per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"A destra per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Sblocca"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Fotocamera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Silenzioso"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 9ebc58d..b03207d 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"הקלד PUK באורך 8 מספרים או יותר."</string>
     <string name="needPuk" msgid="919668385956251611">"כרטיס ה-SIM נעול באמצעות PUK. הקלד את קוד PUK כדי לבטל את נעילתו."</string>
     <string name="needPuk2" msgid="4526033371987193070">"הקלד PUK2 כדי לבטל את חסימת כרטיס ה-SIM."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"זיהוי מתקשר של שיחה נכנסת"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"זיהוי מתקשר בשיחה יוצאת"</string>
     <string name="CfMmi" msgid="5123218989141573515">"העברת שיחות"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"הגדרת שעה"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"הגדר תאריך"</string>
     <string name="date_time_set" msgid="5777075614321087758">"הגדר"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"ברירת מחדל"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"חדש: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"לא דרושים אישורים"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"הוסף חשבון"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"באיזה חשבון ברצונך להשתמש?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"הוסף חשבון"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"הגדל"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"הפחת"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> גע והחזק."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"הסט מעלה כדי להוסיף ומטה כדי להפחית."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"הוסף דקה"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"הפחת דקה"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"הוסף שעה"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"הפחת שעה"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"הגדר PM"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"הגדר AM"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"הוסף חודש"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"הפחת חודש"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"הוסף יום"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"הפחת יום."</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"הוסף שנה"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"הפחת שנה"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"מסומן"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"לא מסומן"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"נבחר"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"שתף עם"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"שתף עם <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"ידית להחלקה. גע והחזק."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"\'למעלה\' עבור <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"\'למטה\' עבור <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"\'שמאל\' עבור <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"\'ימין\' עבור <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"בטל נעילה"</string>
     <string name="description_target_camera" msgid="969071997552486814">"מצלמה"</string>
     <string name="description_target_silent" msgid="893551287746522182">"שקט"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 9f70bb3..526535f 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"PUKは8桁以上で入力してください。"</string>
     <string name="needPuk" msgid="919668385956251611">"SIMカードはPUKでロックされています。ロックを解除するにはPUKコードを入力してください。"</string>
     <string name="needPuk2" msgid="4526033371987193070">"SIMカードのロック解除のためPUK2を入力します。"</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"着信時の発信者番号"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"発信者番号"</string>
     <string name="CfMmi" msgid="5123218989141573515">"着信転送"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"時刻設定"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"日付設定"</string>
     <string name="date_time_set" msgid="5777075614321087758">"設定"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"端末既定"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NEW: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"権限の許可は必要ありません"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"アカウントを追加"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"どのアカウントを使用しますか?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"アカウントを追加"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"増やす"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"減らす"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g>回タップして押し続けます。"</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"上にスライドで大きく、下にスライドで小さくなります。"</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"1分進める"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"1分戻す"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"1時間進める"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"1時間戻す"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"午後に設定"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"午前に設定"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"1か月進める"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"1か月戻す"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"1日進める"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"1日戻す"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"1年進める"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"1年戻す"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"ON"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"OFF"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"ON"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"共有"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>と共有"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"スライダーハンドルです。押し続けます。"</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"上は<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>です。"</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"下は<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>です。"</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"左は<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>です。"</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"右は<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>です。"</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"ロックを解除"</string>
     <string name="description_target_camera" msgid="969071997552486814">"カメラ"</string>
     <string name="description_target_silent" msgid="893551287746522182">"マナーモード"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 0057a5b..b38b988 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -50,10 +50,8 @@
     <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>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"발신자 번호"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"내 발신 번호"</string>
     <string name="CfMmi" msgid="5123218989141573515">"착신전환"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"시간 설정"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"날짜 설정"</string>
     <string name="date_time_set" msgid="5777075614321087758">"설정"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"기본값"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"신규: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"권한 필요 없음"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"계정 추가"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"사용할 계정을 선택하세요."</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"계정 추가"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"올리기"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"줄이기"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> 길게 터치하세요."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"올리려면 위로 슬라이드하고 줄이려면 아래로 슬라이드합니다."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"\'분\'을 올립니다."</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"\'분\'을 줄입니다."</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"\'시\'를 올립니다."</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"\'시\'를 줄입니다."</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"PM 설정"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"AM 설정"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"\'월\'을 올립니다."</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"\'월\'을 줄입니다."</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"\'날짜\'를 올립니다."</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"\'날짜\'를 줄입니다."</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"\'연도\'를 올립니다."</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"\'연도\'를 줄입니다."</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"확인"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"선택 안함"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"선택됨"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"공유 대상:"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>와(과) 공유"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"슬라이딩 핸들을 길게 터치하세요."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 위로 슬라이드"</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 아래로 슬라이드"</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 왼쪽으로 슬라이드"</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 오른쪽으로 슬라이드"</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"잠금 해제"</string>
     <string name="description_target_camera" msgid="969071997552486814">"카메라"</string>
     <string name="description_target_silent" msgid="893551287746522182">"무음"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 8aeb170..4d67940 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Įveskite 8 skaitmenų ar ilgesnį PUK kodą."</string>
     <string name="needPuk" msgid="919668385956251611">"Jūsų SIM kortelė yra užrakinta PUK kodu. Jei norite ją atrakinti, įveskite PUK kodą."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Įveskite PUK2 kodą, kad panaikintumėte SIM kortelės blokavimą."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Įeinančio skambintojo ID"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Išeinančio skambintojo ID"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Skambučio peradresavimas"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Nustatyti laiką"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Nustatyti datą"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Nustatyti"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Numatytasis"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NAUJAS: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Nereikia leidimų"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Pridėti paskyrą"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Kurią paskyrą norite naudoti?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Pridėti paskyrą"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Padidinti"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Sumažinti"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Palieskite <xliff:g id="VALUE">%s</xliff:g> ir laikykite."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Slinkite aukštyn, kad būtų parodytas padidėjimas, ir žemyn, kad būtų parodytas sumažėjimas."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Padidėjimo minutė"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Sumažėjimo minutė"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Padidėjimo valanda"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Sumažėjimo valanda"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Nustatyti po pusiaudienio"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Nustatyti prieš pusiaudienį"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Padidėjimo mėnuo"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Sumažėjimo mėnuo"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Padidėjimo diena"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Sumažėjimo diena"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Padidėjimo metai"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Sumažėjimo metai"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"pažymėtas"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"nepatikrinta"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"pasirinkta"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Bendrinti su"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Bendrinti su „<xliff:g id="APPLICATION_NAME">%s</xliff:g>“"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Slydimo valdymas. Palieskite ir laikykite."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Aukštyn į <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Žemyn į <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Kairėn į <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Dešinėn į <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Atrakinti"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Vaizdo kamera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Begarsis"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index f434e09..12a0e58 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Ierakstiet PUK kodu, kas sastāv no 8 vai vairāk cipariem."</string>
     <string name="needPuk" msgid="919668385956251611">"SIM karte ir bloķēta ar PUK kodu. Ierakstiet PUK kodu, lai to atbloķētu."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Ierakstiet PUK2 kodu, lai atbloķētu SIM karti."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Ienākošā zvana zvanītāja ID"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Izejošā zvana zvanītāja ID"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Zvanu pāradresācija"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Laika iestatīšana"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Datuma iestatīšana"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Iestatīt"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Noklusējums"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"JAUNA: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Atļaujas nav nepieciešamas."</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Pievienot kontu"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Kuru kontu vēlaties izmantot?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Pievienot kontu"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Palielināt"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Samazināt"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g>: pieskarieties un turiet nospiestu."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Bīdiet uz augšu, lai palielinātu vērtību, un uz leju, lai to samazinātu."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Palielināt minūtes vērtību"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Samazināt minūtes vērtību"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Palielināt stundas vērtību"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Samazināt stundas vērtību"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Iestatīt pēcpusdienas laiku"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Iestatīt priekšpusdienas laiku"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Palielināt mēneša vērtību"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Samazināt mēneša vērtību"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Palielināt datuma vērtību"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Samazināt datuma vērtību"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Palielināt gada vērtību"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Samazināt gada vērtību"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"atzīmēta"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"nav atzīmēta"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"atlasīta"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Kopīgot ar:"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Kopīgot ar lietojumprogrammu <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Bīdāms turis. Pieskarieties tam un turiet to nospiestu."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Bīdiet uz augšu, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Bīdiet uz leju, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Bīdiet pa kreisi, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Bīdiet pa labi, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Atbloķēt"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Klusums"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index a2dd90c..f725896 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Taipkan PUK yang mempunyai 8 nombor atau lebih panjang."</string>
     <string name="needPuk" msgid="919668385956251611">"Kad SIM anda dikunci PUK. Taipkan kod PUK untuk membuka kuncinya."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Taipkan PUK2 untuk menyahsekat kad SIM."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"ID Pemanggil Masuk"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"ID Pemanggil Keluar"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Pemajuan panggilan"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Tetapkan masa"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Tetapkan tarikh"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Tetapkan"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Lalai"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"BAHARU: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Tiada kebenaran diperlukan"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Tambah akaun"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Akaun mana yang mahu anda gunakan?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Tambah akaun"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Kenaikan"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Penyusutan"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> sentuh terus."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Luncurkan ke atas untuk kenaikan dan ke bawah untuk penyusutan."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Minit kenaikan"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Minit penyusutan"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Jam kenaikan"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Jam penyusutan"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Tetapkan PM"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Tetapkan AM"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Bulan kenaikan"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Bulan penyusutan"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Hari kenaikan"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Hari penyusutan"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Tahun kenaikan"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Tahun penyusutan"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"ditandakan"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"tidak ditandakan"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"dipilih"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Kongsi dengan"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Kongsi dengan <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Pemegang gelongsor. Sentuh &amp; tahan."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Atas untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Bawah untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Kiri untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Kanan untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Buka kunci"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Senyap"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index b3ea39ff..8bc9dab 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Skriv inn en PUK-kode på åtte tall eller mer."</string>
     <string name="needPuk" msgid="919668385956251611">"SIM-kortet ditt er PUK-låst. Skriv inn PUK-koden for å låse det opp."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Skriv inn PUK2 for å låse opp SIM-kortet."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Inngående nummervisning"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Utgående nummervisning"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Viderekobling"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Stille klokken"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Angi dato"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Lagre"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Standard"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NYTT: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Trenger ingen rettigheter"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Legg til en konto"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Hvilken konto vil du bruke?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Legg til konto"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Øke"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Senke"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> – trykk og hold inne."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Skyv opp for å øke og ned for å redusere."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Endre minutter (fremover)"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Endre minutter (bakover)"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Endre timer (fremover)"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Endre time (bakover)"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Angi p.m."</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Angi a.m."</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Endre måned (fremover)"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Endre måned (bakover)"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Endre dag (fremover)"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Endre dag (bakover)"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Endre år (fremover)"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Endre år (bakover)"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"valgt"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"ikke valgt"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"valgt"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Del med"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Del med <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Glidebryter. Trykk og hold inne."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Opp for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Ned for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Venstre for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Høyre for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Lås opp"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Stille"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 5698f03..61f08e0 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Typ een PUK-code die 8 cijfers of langer is."</string>
     <string name="needPuk" msgid="919668385956251611">"Uw SIM-kaart is vergrendeld met de PUK-code. Typ de PUK-code om te ontgrendelen."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Voer de PUK2-code in om de SIM-kaart te ontgrendelen."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Inkomende beller-id"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Uitgaande beller-id"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Oproep doorschakelen"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Tijd instellen"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Datum instellen"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Instellen"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Standaard"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NIEUW: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Geen machtigingen vereist"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Een account toevoegen"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Welk account wilt u gebruiken?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Account toevoegen"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Hoger"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Lager"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> blijven aanraken."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Schuif omhoog om te verhogen en omlaag om te verlagen."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Minuten verhogen"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Minuten verlagen"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Uren verhogen"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Uren verlagen"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"PM instellen"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"AM instellen"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Maand verhogen"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Maand verlagen"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Dag verhogen"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Dag verlagen"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Jaar verhogen"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Jaar verlagen"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"aangevinkt"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"niet aangevinkt"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"geselecteerd"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Delen met"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Delen met <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Schuifgreep. Tikken en blijven aanraken."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Omhoog voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Omlaag voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Links voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Rechts voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Ontgrendelen"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Camera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Stil"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index da2f78d..77f8adc 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Wpisz kod PUK składający się z co najmniej 8 cyfr."</string>
     <string name="needPuk" msgid="919668385956251611">"Karta SIM jest zablokowana kodem PUK. Wprowadź kod PUK, aby odblokować kartę."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Wprowadź kod PUK2, aby odblokować kartę SIM."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Identyfikator rozmówcy przy połączeniach przychodzących"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Identyfikator rozmówcy przy połączeniach wychodzących"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Przekazywanie połączeń"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Ustaw godzinę"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Ustaw datę"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Ustaw"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Domyślne"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NOWE: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Nie są wymagane żadne uprawnienia"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Dodaj konto"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Którego konta chcesz użyć?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Dodaj konto"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Zwiększ"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Zmniejsz"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> dotknij i przytrzymaj."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Przesuń w górę, aby zwiększyć wartość, lub w dół, aby ją zmniejszyć."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Następna minuta"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Poprzednia minuta"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Następna godzina"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Poprzednia godzina"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Ustaw PM"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Ustaw AM"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Następny miesiąc"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Poprzedni miesiąc"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Następny dzień"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Poprzedni dzień"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Następny rok"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Poprzedni rok"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"zaznaczono"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"nie zaznaczono"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"wybrano"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Udostępnij przez"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Udostępnij przez <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Uchwyt przesuwny. Dotknij i przytrzymaj."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>: w górę"</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>: w dół"</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>: w lewo"</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>: w prawo"</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Odblokuj"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Aparat"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Wyciszenie"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index ec43491..2a3e2b9 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Introduza um PUK que tenha 8 ou mais algarismos."</string>
     <string name="needPuk" msgid="919668385956251611">"O seu cartão SIM está bloqueado com PUK. Introduza o código PUK para desbloqueá-lo."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Introduza o PUK2 para desbloquear o cartão SIM."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"ID do Autor da Chamada"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"ID do autor da chamada efetuada"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Encaminhamento de chamadas"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Definir hora"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Definir data"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Definir"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Predefinido"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NOVA: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Não são necessárias permissões"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Adicionar uma conta"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Que conta pretende utilizar?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Adicionar conta"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Aumentar"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Diminuir"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Toque sem soltar em <xliff:g id="VALUE">%s</xliff:g>."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Deslize lentamente para cima para aumentar e para baixo para diminuir."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Aumentar minuto"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Diminuir minuto"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Aumentar hora"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Diminuir hora"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Definir PM"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Definir AM"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Aumentar mês"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Diminuir mês"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Aumentar dia"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Diminuir dia"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Aumentar ano"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Diminuir ano"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"marcado"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"desmarcado"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"selecionado"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Partilhar com:"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Compartilhar com <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Barra deslizante. Toque &amp; não solte."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Para cima para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Para baixo para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Para a esquerda para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Para a direita para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Desbloquear"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Câmara"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Silencioso"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 53e2a96..88b7a57 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Digite um PUK com oito números ou mais."</string>
     <string name="needPuk" msgid="919668385956251611">"O seu cartão SIM está bloqueado por um PUK. Digite o código PUK para desbloqueá-lo."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Digite o PUK2 para desbloquear o cartão SIM."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"ID do chamador de entrada"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"ID do chamador de saída"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Encaminhamento de chamada"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Definir hora"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Definir data"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Definir"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Padrão"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NOVO: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Nenhuma permissão necessária"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Adicionar uma conta"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Qual conta você deseja usar?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Adicionar conta"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Incremento"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Redução"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> toque e mantenha pressionado."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Deslize para cima para aumentar e para baixo para diminuir."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Aumentar minuto"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Diminuir minuto"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Aumentar hora"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Diminuir hora"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Configurar valor PM"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Configurar valor AM"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Aumentar mês"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Diminuir mês"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Aumentar dia"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Reduzir dia"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Aumentar ano"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Diminuir ano"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"verificado"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"não selecionado"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"selecionado"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Compartilhar com"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Compartilhar com <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Recurso deslizante. Toque e segure."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Deslize para cima para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Deslize para baixo para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Deslize para a esquerda para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Deslize para a direita para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Desbloquear"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Câmera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Silencioso"</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 5f0561b..75c5c7e 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -1509,6 +1509,8 @@
     <!-- no translation found for date_picker_dialog_title (5879450659453782278) -->
     <skip />
     <string name="date_time_set" msgid="5777075614321087758">"Definir"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Standard"</string>
     <!-- no translation found for perms_new_perm_prefix (8257740710754301407) -->
     <skip />
@@ -1746,37 +1748,37 @@
     <skip />
     <!-- no translation found for add_account_button_label (3611982894853435874) -->
     <skip />
-    <!-- no translation found for number_picker_increment_button (4830170763103463443) -->
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
     <skip />
-    <!-- no translation found for number_picker_decrement_button (2576606679160067262) -->
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
     <skip />
     <!-- no translation found for number_picker_increment_scroll_mode (3073101067441638428) -->
     <skip />
-    <!-- no translation found for number_picker_increment_scroll_action (4628981789985093179) -->
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
     <skip />
-    <!-- no translation found for time_picker_increment_minute_button (2843066823236250329) -->
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
     <skip />
-    <!-- no translation found for time_picker_decrement_minute_button (4357907223628449595) -->
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
     <skip />
-    <!-- no translation found for time_picker_increment_hour_button (2484204991937119057) -->
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
     <skip />
-    <!-- no translation found for time_picker_decrement_hour_button (4659353501775842780) -->
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
     <skip />
     <!-- no translation found for time_picker_increment_set_pm_button (4147590696151230863) -->
     <skip />
     <!-- no translation found for time_picker_decrement_set_am_button (8302140353539486752) -->
     <skip />
-    <!-- no translation found for date_picker_increment_month_button (6324978841467899081) -->
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
     <skip />
-    <!-- no translation found for date_picker_decrement_month_button (7304349355000398077) -->
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
     <skip />
-    <!-- no translation found for date_picker_increment_day_button (4397040141921413183) -->
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
     <skip />
-    <!-- no translation found for date_picker_decrement_day_button (2427816793443629131) -->
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
     <skip />
-    <!-- no translation found for date_picker_increment_year_button (3058553394722295105) -->
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
     <skip />
-    <!-- no translation found for date_picker_decrement_year_button (5193062846559743823) -->
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
     <skip />
     <!-- no translation found for checkbox_checked (7222044992652711167) -->
     <skip />
@@ -1816,13 +1818,13 @@
     <skip />
     <!-- no translation found for content_description_sliding_handle (415975056159262248) -->
     <skip />
-    <!-- no translation found for description_direction_up (1983114130441878529) -->
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
     <skip />
-    <!-- no translation found for description_direction_down (4294993639091088240) -->
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
     <skip />
-    <!-- no translation found for description_direction_left (6814008463839915747) -->
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
     <skip />
-    <!-- no translation found for description_direction_right (4296057241963012862) -->
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
     <skip />
     <!-- no translation found for description_target_unlock (2228524900439801453) -->
     <skip />
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 11199b0..5409290 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Introduceţi un cod PUK care să aibă 8 cifre sau mai mult."</string>
     <string name="needPuk" msgid="919668385956251611">"Cardul SIM este blocat cu codul PUK. Introduceţi codul PUK pentru a-l debloca."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Introduceţi codul PUK2 pentru a debloca cardul SIM."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"ID apelant de primire"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"ID apelant"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Redirecţionarea apelurilor"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Setaţi ora"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Setaţi data"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Setaţi"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Prestabilit"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NOU: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Nu se solicită nicio permisiune"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Adăugaţi un cont"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Ce cont doriţi să utilizaţi?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Adăugaţi un cont"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Incrementaţi"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Decrementaţi"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Atingeţi şi ţineţi apăsat <xliff:g id="VALUE">%s</xliff:g>."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Glisaţi în sus pentru incrementare şi în jos pentru decrementare."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Incrementaţi valoarea pentru minut"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Decrementaţi valoarea pentru minut"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Incrementaţi valoarea pentru oră"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Decrementaţi valoarea pentru oră"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Setaţi valoarea PM"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Setaţi valoarea AM"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Incrementaţi valoarea pentru lună"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Decrementaţi valoarea pentru lună"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Incrementaţi valoarea pentru zi"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Decrementaţi valoarea pentru zi"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Incrementaţi valoarea pentru an"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Decrementaţi valoarea pentru an"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"bifată"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"nebifată"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"selectat"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Permiteţi accesul pentru"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Permiteţi accesul pentru <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Mâner glisant. Atingeţi şi ţineţi apăsat."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"În sus pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"În jos pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"La stânga pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"La dreapta pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Deblocaţi"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Cameră foto"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Silenţios"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index d4adfb4..9d8e4a6 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Введите PUK-код из 8 или более цифр."</string>
     <string name="needPuk" msgid="919668385956251611">"SIM-карта заблокирована с помощью кода PUK. Для разблокировки введите код PUK."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Для разблокировки SIM-карты введите PUK2."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Идентификация вызывающего абонента"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Идентификация звонящего абонента"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Переадресация вызова"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Настройка времени"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Настройка даты"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Установить"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"По умолчанию"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"НОВОЕ: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Не требуется разрешений"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Добавить аккаунт"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Выберите аккаунт"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Добавить аккаунт"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Увеличить"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Уменьшить"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Нажмите и удерживайте <xliff:g id="VALUE">%s</xliff:g>."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Проведите вверх, чтобы увеличить значение, и вниз, чтобы уменьшить его."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"На минуту вперед"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"На минуту назад"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"На час вперед"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"На час назад"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Установить время после полудня"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Установить время до полудня"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"На месяц вперед"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"На месяц назад"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"На день вперед"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"На день назад"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"На год вперед"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"На год назад"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"установлено"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"не установлено"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"выбрано"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Открыть доступ:"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Открыть доступ приложению \"<xliff:g id="APPLICATION_NAME">%s</xliff:g>\""</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Перетаскиваемый значок блокировки. Нажмите и удерживайте."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Проведите вверх, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Проведите вниз, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Проведите влево, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Проведите вправо, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Разблокировать"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Камера"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Без звука"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index bad739f9..ca80f6b 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Zadajte kód PUK, ktorý má 8 alebo viac čísel."</string>
     <string name="needPuk" msgid="919668385956251611">"Karta SIM je uzamknutá pomocou kódu PUK. Odomknite ju zadaním kódu PUK."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Ak chcete odblokovať kartu SIM, zadajte kód PUK2."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Prichádzajúca identifikácia volajúceho"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Odchádzajúca identifikácia volajúceho"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Presmerovanie hovorov"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Nastaviť čas"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Nastaviť dátum"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Nastaviť"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Predvolené"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NOVINKA: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Nevyžadujú sa žiadne oprávnenia."</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Pridať účet"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Ktorý účet chcete použiť?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Pridať účet"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Zvýšenie"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Zníženie"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Dotknite sa a podržte <xliff:g id="VALUE">%s</xliff:g>."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Ak chcete pripočítať, potiahnite prst nahor. Ak chcete odpočítať, potiahnite prst nadol."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Pripočítať minútu"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Odpočítať minútu"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Pripočítať hodinu"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Odpočítať hodinu"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Nastaviť čas popoludní"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Nastaviť čas dopoludnia"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Pripočítať mesiac"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Odpočítať mesiac"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Pripočítať deň"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Odpočítať deň"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Pripočítať rok"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Odpočítať rok"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"začiarknuté"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"nezačiarknuté"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"vybratý"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Zdieľať s"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Zdieľať s aplikáciou <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Posuvné tlačidlo. Dotknite sa a podržte."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Nahor na <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Nadol na <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Doľava na <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Doprava na <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Odomknúť"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Fotoaparát"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Tichý"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 767305c..e664d9c 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Vnesite 8- ali več mestni PUK."</string>
     <string name="needPuk" msgid="919668385956251611">"Kartica SIM je zaklenjena s kodo PUK. Če jo želite odkleniti, vnesite kodo PUK."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Če želite odstraniti blokiranje kartice SIM, vnesite PUK2."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"ID dohodnega klicatelja"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"ID odhodnega klicatelja"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Preusmerjanje klicev"</string>
@@ -430,7 +428,7 @@
     <string name="permlab_readPhoneState" msgid="2326172951448691631">"branje stanja in identitete telefona"</string>
     <string name="permdesc_readPhoneState" msgid="5127767618743602782">"Programu omogoča dostop do funkcij telefona v napravi. Program lahko s tem dovoljenjem določi telefonsko številko in serijsko številko tega telefona, določi lahko tudi, ali je klic aktiven, številko, s katero je klic povezan, in podobno."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"preprečitev prehoda tabličnega računalnika v stanje pripravljenosti"</string>
-    <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"preprečevanje prehod v stanje pripravljenosti telefona"</string>
+    <string name="permlab_wakeLock" product="default" msgid="573480187941496130">"preprečevanje prehoda v stanje pripravljenosti telefona"</string>
     <string name="permdesc_wakeLock" product="tablet" msgid="7311319824400447868">"Omogoča, da program prepreči prehod tabličnega računalnika v stanje pripravljenosti."</string>
     <string name="permdesc_wakeLock" product="default" msgid="8559100677372928754">"Programu omogoča, da v telefonu prepreči prehod v stanje pripravljenosti."</string>
     <string name="permlab_devicePower" product="tablet" msgid="2787034722616350417">"vklop ali izklop tabličnega računalnika"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Nastavi uro"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Nastavi datum"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Nastavi"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Privzeto"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NOVO: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Ni zahtevanih dovoljenj"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Dodajanje računa"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Kateri račun želite uporabiti?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Dodaj račun"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Povečaj"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Zmanjšaj"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Dotaknite se vrednosti <xliff:g id="VALUE">%s</xliff:g> in jo pridržite."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Povlecite gor za povečanje in dol za zmanjšanje."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Povečaj minute"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Zmanjšaj minute"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Povečaj uro"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Zmanjšaj uro"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Nastavi PM"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Nastavi AM"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Naslednji mesec"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Prejšnji mesec"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Naslednji dan"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Prejšnji dan"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Naslednje leto"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Prejšnje leto"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"potrjeno"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"ni odkljukano"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"izbrano"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Delite z"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Delite s programom <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Drsna ročica. Dotaknite se in pridržite."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Gor za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Dol za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Levo za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Desno za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Odkleni"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Fotoaparat"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Tiho"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index d03abd7..4a3839b 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Унесите PUK који се састоји од 8 цифара или више."</string>
     <string name="needPuk" msgid="919668385956251611">"SIM картица је закључана PUK кодом. Унесите PUK кôд да бисте је откључали."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Унесите PUK2 да бисте деблокирали SIM картицу."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Долазни ИД позиваоца"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Одлазни ИД позиваоца"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Преусмеравање позива"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Подешавање времена"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Подешавање датума"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Подеси"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Подразумевано"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"НОВО: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Није потребна ниједна дозвола"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Додај налог"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Који налог желите да користите?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Додај налог"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Повећање"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Смањење"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> додирните и задржите."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Превуците нагоре за повећање, а надоле за смањење."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Повећај минуте"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Смањи минуте"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Повећај сате"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Смањи сате"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Подеси по подне"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Подеси пре подне"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Повећај месеце"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Смањи месеце"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Повећај дане"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Смањи дане"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Повећај године"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Смањи године"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"изабрано"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"није потврђено"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"изабрано"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Дели са"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Дели са апликацијом <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Клизна ручица. Додирните и задржите."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Нагоре за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Надоле за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Улево за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Удесно за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Откључај"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Камера"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Нечујно"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index ddaa30a..7ba32ce 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Ange en PUK-kod med minst 8 siffror."</string>
     <string name="needPuk" msgid="919668385956251611">"Ditt SIM-kort är PUK-låst. Ange PUK-koden om du vill låsa upp det."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Ange PUK2-koden för att häva spärren av SIM-kortet."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI-kod"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Nummerpresentatör för inkommande samtal"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Nummerpresentatör för utgående samtal"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Vidarebefordra samtal"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Ange tid"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Ange datum"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Ställ in"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Standardinställning"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NY: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Inga behörigheter krävs"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Lägg till ett konto"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Vilket konto vill du använda?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Lägg till konto"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Öka"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Minska"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> tryck länge."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Skjut uppåt för att öka och nedåt för att minska."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Öka minuter"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Minska minuter"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Öka timmar"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Minska timmar"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Ange em"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Ange fm"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Öka månad"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Minska månad"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Öka dagar"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Minska dag"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Öka år"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Minska år"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"markerat"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"inte markerat"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"markerade"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Dela med"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Dela med <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Skärmlåsfunktion. Tryck och dra."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Upp för <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Ned för <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Vänster för <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Höger för <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Lås upp"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Tyst"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 0424964..1744095 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Andika PUK ambayo ina urefu wa nambari 8 au zaidi."</string>
     <string name="needPuk" msgid="919668385956251611">"Kadi yako ya SIM imefungwa na PUK. Anika msimbo wa PUK ili kuifungua."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Chapisha PUK2 ili kufungua SIM kadi."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Kitambulisho cha Mpigaji wa Simu Inayoingia"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"ID ya Mpigaji simu Inayotoka nje"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Kusambaza simu"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Weka muda"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Weka tarehe"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Weka"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Chaguo-msingi"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">" MPYA: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Hakuna vibali vinavyohitajika"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Ongeza akaunti"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Je, ni akaunti gani unataka kutumia?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Ongeza akaunti"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Ongezeko"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Punguza"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> gusa na ushikilie."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Nyiririsha juu kuongeza na chini kupunguza."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Dakika ya nyongeza"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Dakika pungufu"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Saa ya nyongeza"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Saa pungufu."</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Seti PM"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Seti AM"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Mwezi wa nyongeza"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Mwezi pungufu"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Siku ya nyongeza"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Siku pungufu"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Mwaka wa nyongeza"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Mwaka pungufu"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"imeangaliwa"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"haijakaguliwa"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"Iliyochaguliwa"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Gawa na"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Gawa na <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Utambo unaosonga. Gusa &amp; shika"</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Juu ajili ya<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Chini kwa ajili ya<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Kushoto kwa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Kulia kwa ajili ya <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Fungua"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Kimya"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 7197f90..32281b5 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"พิมพ์รหัส PUK ซึ่งต้องเป็นตัวเลขอย่างน้อย 8 หลัก"</string>
     <string name="needPuk" msgid="919668385956251611">"ซิมการ์ดของคุณถูกล็อกด้วย PUK พิมพ์รหัส PUK เพื่อปลดล็อก"</string>
     <string name="needPuk2" msgid="4526033371987193070">"พิมพ์ PUK2 เพื่อยกเลิกการปิดกั้นซิมการ์ด"</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"หมายเลขผู้โทรเข้า"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"หมายเลขผู้โทรออก"</string>
     <string name="CfMmi" msgid="5123218989141573515">"การโอนสาย"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"ตั้งเวลา"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"ตั้งวันที่"</string>
     <string name="date_time_set" msgid="5777075614321087758">"ตั้งค่า"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"เริ่มต้น"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"ใหม่: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"ไม่ต้องการการอนุญาต"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"เพิ่มบัญชี"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"คุณต้องการใช้บัญชีใด"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"เพิ่มบัญชี"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"การเพิ่ม"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"การลด"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"แตะ <xliff:g id="VALUE">%s</xliff:g> ค้างไว้"</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"เลื่อนขึ้นเพื่อเพิ่มและเลื่อนลงเพื่อลด"</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"เพิ่มนาที"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"ลดนาที"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"เพิ่มชั่วโมง"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"ลดชั่วโมง"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"ตั้งค่า PM"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"ตั้งค่า AM"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"เพิ่มเดือน"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"ลดเดือน"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"เพิ่มวัน"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"ลดวัน"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"เพิ่มปี"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"ลดปี"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"เลือกไว้"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"ไม่ได้ตรวจสอบ"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"เลือกแล้ว"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"แบ่งปันกับ"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"แบ่งปันด้วย <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"ที่จับสำหรับเลื่อน แตะค้างไว้"</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"เลื่อนขึ้นเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"เลื่อนลงเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"เลื่อนไปทางซ้ายเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"เลื่อนไปทางขวาเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"ปลดล็อก"</string>
     <string name="description_target_camera" msgid="969071997552486814">"กล้องถ่ายรูป"</string>
     <string name="description_target_silent" msgid="893551287746522182">"ปิดเสียง"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index ff2e7ea..fd88fc1 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Mag-type ng PUK na may 8 numbero o mas mahaba."</string>
     <string name="needPuk" msgid="919668385956251611">"Na-PUK-lock ang iyong SIM card. I-type ang PUK code upang i-unlock ito."</string>
     <string name="needPuk2" msgid="4526033371987193070">"I-type ang PUK2 upang i-unblock ang SIM card."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Papasok na Caller ID"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Papalabas na Caller ID"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Pagpapasa ng tawag"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Magtakda ng oras"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Itakda ang petsa"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Itakda"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Default"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"BAGO: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Walang mga kinakailangang pahintulot"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Magdagdag ng account"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Aling account ang nais mong gamitin?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Magdagdag ng account"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Taasan"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Babaan"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> pindutin nang matagal."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"I-slide pataas upang magdagdag at pababa upang magbawas."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Minuto ng pagdaragdag"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Minuto ng pagbawas"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Oras ng pagdaragdag"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Oras ng pagbawas"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Itakda ang PM"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Itakda ang AM"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Buwan ng pagdagdag"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Buwan ng pagbawas"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Araw ng pagdaragdag"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Araw ng pagbawas"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Taon ng pagdaragdag"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Taon ng pagbawas"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"nilagyan ng check"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"hindi nilagyan ng check"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"pinili"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Ibahagi sa"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Ibahagi sa <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Hawakan sa pag-slide. Pindutin nang matagal."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Nakataas para sa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Nakababa para sa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Pakaliwa para sa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Pakanan para sa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"I-unlock"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Camera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Tahimik"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index c450761..251e47c 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"8 veya daha uzun basamaklı bir PUK kodu yazın."</string>
     <string name="needPuk" msgid="919668385956251611">"SIM kartınızın PUK kilidi devrede. Kilidi açmak için PUK kodunu yazın."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Engellenen SIM kartı açmak için PUK2 kodunu yazın."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Gelen Çağrı Kimliği"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Giden Çağrı Kimliği"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Çağrı yönlendirme"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Saati ayarla"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Tarihi ayarla"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Ayarla"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Varsayılan"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"YENİ: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"İzin gerektirmez"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Hesap ekleyin"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Hangi hesabı kullanmak istiyorsunuz?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Hesap ekle"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Artır"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Azalt"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> rakamına dokunun ve basılı tutun."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Artırmak için yukarı, azaltmak için aşağı kaydırın."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Dakika değerini artır"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Dakika değerini azalt"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Saat değerini artır"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Saat değerini azalt"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"ÖS değerini ayarla"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"ÖÖ değerini ayarla"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Ay değerini artır"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Ay değerini azalt"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Gün değerini artır"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Gün değerini azalt"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Yıl değerini artır"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Yıl değerini azalt"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"işaretli"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"işaretlenmedi"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"seçili"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Şununla paylaş:"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"<xliff:g id="APPLICATION_NAME">%s</xliff:g> ile paylaş"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Kayan tutma yeri. Dokunun ve basılı tutun."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için yukarı."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için aşağı."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için sola."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için sağa."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Kilidi aç"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Sessiz"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 2afb95f..9054295 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Введіть PUK-код із 8 або більше цифр."</string>
     <string name="needPuk" msgid="919668385956251611">"SIM-карта заблок. PUK-кодом. Введіть PUK-код, щоб її розблок."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Введ. PUK2, щоб розбл. SIM-карту."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Вхідн. ід. абонента"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Вихід. ід. абонента"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Переадрес. виклику"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Установити час"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Установити дату"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Застосувати"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"За умовч."</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"НОВИЙ: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Дозвіл не потрібний"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Додати обліковий запис"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Який обліковий запис використовувати?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Додати облік. запис"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Додати"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Відняти"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> – торкніться й утримуйте."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Перемістіть угору, щоб додати, і вниз, щоб відняти."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Додати хвилину"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Відняти хвилину"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Додати годину"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Відняти годину"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Установити час \"пп\""</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Установити час \"дп\""</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Додати місяць"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Відняти місяць"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Додати день"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Відняти день"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Додати рік"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Відняти рік"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"перевірено"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"не перевірено"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"вибрано"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Надіслати через"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Надіслати через <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Вказівник-повзунок. Торкніться й утримуйте."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Угору, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Униз, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Ліворуч, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Праворуч, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Розблокувати"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Камера"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Без звуку"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 329917e..609452d 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Nhập PUK có từ 8 số trở lên."</string>
     <string name="needPuk" msgid="919668385956251611">"Thẻ SIM của bạn đã bị khóa PUK. Nhập mã PUK để mở khóa thẻ SIM đó."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Nhập mã PUK2 để bỏ chặn thẻ SIM."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"Số gọi đến"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"Số gọi đi"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Chuyển tiếp cuộc gọi"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Đặt giờ"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Đặt ngày"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Đặt"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Mặc định"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"MỚI: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Không yêu cầu quyền"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Thêm tài khoản"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Bạn muốn sử dụng tài khoản nào?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Thêm tài khoản"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Tăng dần"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Giảm dần"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Chạm và giữ <xliff:g id="VALUE">%s</xliff:g>."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Trượt lên để tăng và trượt xuống để giảm."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Phút tăng dần"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Phút giảm dần"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Giờ tăng dần"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Giờ giảm dần."</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Đặt CH"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Đặt SA"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Tháng tăng dần"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Tháng giảm dần"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Ngày tăng dần"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Ngày giảm dần"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Năm tăng dần"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Năm giảm dần."</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"đã kiểm tra"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"chưa chọn"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"đã chọn"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Chia sẻ với"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Chia sẻ với <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Tay trượt. Chạm &amp; giữ."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Lên để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Xuống để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Sang trái để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Sang phải để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Mở khóa"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Máy ảnh"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Im lặng"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index d6ed9a9..5a9cadc 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"请键入至少 8 位数字的 PUK 码。"</string>
     <string name="needPuk" msgid="919668385956251611">"已对 SIM 卡进行 PUK 码锁定。键入 PUK 码将其解锁。"</string>
     <string name="needPuk2" msgid="4526033371987193070">"输入 PUK2 码以解锁 SIM 卡。"</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"来电显示"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"本机号码"</string>
     <string name="CfMmi" msgid="5123218989141573515">"来电转接"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"设置时间"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"设置日期"</string>
     <string name="date_time_set" msgid="5777075614321087758">"设置"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"默认"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"新增:"</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"不需要任何权限"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"添加帐户"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"您要使用哪个帐户?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"添加帐户"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"增加"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"减少"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"触摸 <xliff:g id="VALUE">%s</xliff:g> 次并按住。"</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"向上滑动可增加值,向下滑动可减少值。"</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"增加分钟数"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"减少分钟数"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"增加小时数"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"减少小时数"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"设置下午时间"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"设置上午时间"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"增加月份值"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"减少月份值"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"增加天数"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"减少天数"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"增加年数"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"减少年份值"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"已选中"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"未选中"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"已选择"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"共享对象"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"与“<xliff:g id="APPLICATION_NAME">%s</xliff:g>”共享"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"滑动手柄。触摸并按住。"</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"向上滑动<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"向下滑动<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"向左滑动<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"向右滑动<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"解锁"</string>
     <string name="description_target_camera" msgid="969071997552486814">"相机"</string>
     <string name="description_target_silent" msgid="893551287746522182">"静音"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index bc9337b..aa8eda1 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"輸入 8 位數以上的 PUK。"</string>
     <string name="needPuk" msgid="919668385956251611">"SIM 卡的 PUK 已鎖定。請輸入 PUK 碼解除鎖定。"</string>
     <string name="needPuk2" msgid="4526033371987193070">"請輸入 PUK2 以解鎖 SIM 卡。"</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"來電顯示"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"本機號碼"</string>
     <string name="CfMmi" msgid="5123218989141573515">"來電轉接"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"設定時間"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"日期設定"</string>
     <string name="date_time_set" msgid="5777075614321087758">"設定"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"預設值"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"新增:"</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"無須許可"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"新增帳戶"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"您要使用哪個帳戶?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"新增帳戶"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"增加"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"減少"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> 輕觸並按住。"</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"向上滑動即可增加,向下滑動即可減少。"</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"增加分鐘數"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"減少分鐘數"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"增加時數"</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"減少時數"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"設定 PM 值"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"設定 AM 值"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"增加月份"</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"減少月份"</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"增加天數"</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"減少天數"</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"增加年份"</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"減少年份"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"已勾選"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"尚未勾選"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"已選取"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"分享對象:"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"與「<xliff:g id="APPLICATION_NAME">%s</xliff:g>」分享"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"滑動控制。持續輕觸。"</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"向上滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"向下滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"向左滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"向右滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"解除鎖定"</string>
     <string name="description_target_camera" msgid="969071997552486814">"相機"</string>
     <string name="description_target_silent" msgid="893551287746522182">"靜音"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 6471965..200bbea 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -50,10 +50,8 @@
     <string name="invalidPuk" msgid="8761456210898036513">"Thayipha i-PUK enezinombolo ezingu-8 noma ngaphezu."</string>
     <string name="needPuk" msgid="919668385956251611">"Ikhadi lakho le-SIM livalwe nge-PUK. Thayipha ikhodi ye-PUK ukulivula."</string>
     <string name="needPuk2" msgid="4526033371987193070">"Thayipha i-PUK2 ukuze uvule ikhadi le-SIM."</string>
-    <!-- no translation found for imei (2625429890869005782) -->
-    <skip />
-    <!-- no translation found for meid (4841221237681254195) -->
-    <skip />
+    <string name="imei" msgid="2625429890869005782">"IMEI"</string>
+    <string name="meid" msgid="4841221237681254195">"MEID"</string>
     <string name="ClipMmi" msgid="6952821216480289285">"I-ID Yocingo Olungenayo"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"I-ID Yomshayeli Ephumayo"</string>
     <string name="CfMmi" msgid="5123218989141573515">"Ukudlulisa ikholi"</string>
@@ -1021,6 +1019,8 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Hlela isikhathi"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Setha idethi"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Hlela"</string>
+    <!-- no translation found for date_time_done (2507683751759308828) -->
+    <skip />
     <string name="default_permission_group" msgid="2690160991405646128">"Okuzenzakalelayo"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"OKUSHA: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Ayikho imvume edingekayo"</string>
@@ -1170,22 +1170,35 @@
     <string name="add_account_label" msgid="2935267344849993553">"Yengeza i-akhawunti"</string>
     <string name="choose_account_text" msgid="6303348737197849675">"Ingabe iyiphi i-akhawunti ofuna ukuyisebenzisa?"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"Engeza i-akhawunti"</string>
-    <string name="number_picker_increment_button" msgid="4830170763103463443">"Nciphisa"</string>
-    <string name="number_picker_decrement_button" msgid="2576606679160067262">"Decrement"</string>
+    <!-- no translation found for number_picker_increment_button (2412072272832284313) -->
+    <skip />
+    <!-- no translation found for number_picker_decrement_button (476050778386779067) -->
+    <skip />
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> thinta bese ucindezela."</string>
-    <string name="number_picker_increment_scroll_action" msgid="4628981789985093179">"Shishilizisa kwenyuke kuye ekwenyusweni kwehle kuye ekwehlisweni."</string>
-    <string name="time_picker_increment_minute_button" msgid="2843066823236250329">"Iminithi wokwenyusa"</string>
-    <string name="time_picker_decrement_minute_button" msgid="4357907223628449595">"Iminithi yokwehlisa"</string>
-    <string name="time_picker_increment_hour_button" msgid="2484204991937119057">"Ihora lokwenyusa."</string>
-    <string name="time_picker_decrement_hour_button" msgid="4659353501775842780">"Ihora lokwehlisa"</string>
+    <!-- no translation found for number_picker_increment_scroll_action (9101473045891835490) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_minute_button (8865885114028614321) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_minute_button (6246834937080684791) -->
+    <skip />
+    <!-- no translation found for time_picker_increment_hour_button (3652056055810223139) -->
+    <skip />
+    <!-- no translation found for time_picker_decrement_hour_button (1377479863429214792) -->
+    <skip />
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Setha Ntambama"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Setha Ekuseni"</string>
-    <string name="date_picker_increment_month_button" msgid="6324978841467899081">"Inyanga yokwenyusa."</string>
-    <string name="date_picker_decrement_month_button" msgid="7304349355000398077">"Inyanga yokwehlisa."</string>
-    <string name="date_picker_increment_day_button" msgid="4397040141921413183">"Usuku lokwenyusa."</string>
-    <string name="date_picker_decrement_day_button" msgid="2427816793443629131">"Usuku lokwehlisa."</string>
-    <string name="date_picker_increment_year_button" msgid="3058553394722295105">"Unyaka wokwenyusa."</string>
-    <string name="date_picker_decrement_year_button" msgid="5193062846559743823">"Unyaka wokwehlisa"</string>
+    <!-- no translation found for date_picker_increment_month_button (5369998479067934110) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_month_button (1832698995541726019) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_day_button (7130465412308173903) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_day_button (4131881521818750031) -->
+    <skip />
+    <!-- no translation found for date_picker_increment_year_button (6318697384310808899) -->
+    <skip />
+    <!-- no translation found for date_picker_decrement_year_button (4482021813491121717) -->
+    <skip />
     <string name="checkbox_checked" msgid="7222044992652711167">"kuhloliwe"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"akuhloliwe"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"Okukhethiwe"</string>
@@ -1205,10 +1218,14 @@
     <string name="shareactionprovider_share_with" msgid="806688056141131819">"Yabelana no"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"Yabelana no <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"Ihaambis isibambo. Thinta &amp; ubambe."</string>
-    <string name="description_direction_up" msgid="1983114130441878529">"Phezulu kwe <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_down" msgid="4294993639091088240">"Ngaphansi kwe <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_left" msgid="6814008463839915747">"Kwesokunxeleee kwe <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
-    <string name="description_direction_right" msgid="4296057241963012862">"Ngakwesokudla kwe for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- no translation found for description_direction_up (7169032478259485180) -->
+    <skip />
+    <!-- no translation found for description_direction_down (5087739728639014595) -->
+    <skip />
+    <!-- no translation found for description_direction_left (7207478719805562165) -->
+    <skip />
+    <!-- no translation found for description_direction_right (8034433242579600980) -->
+    <skip />
     <string name="description_target_unlock" msgid="2228524900439801453">"Vula"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Ikhamera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Thulile"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 438c141..5b6b35a 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2079,6 +2079,7 @@
             <!-- Locale -->
             <enum name="locale" value="3" />
         </attr>
+
         <!-- Direction of the text. A heuristic is used to determine the resolved text direction
              of paragraphs. -->
          <attr name="textDirection" format="integer">
@@ -2099,6 +2100,29 @@
             <!-- The paragraph direction is coming from the system Locale. -->
             <enum name="locale" value="5" />
         </attr>
+
+        <!-- Alignment of the text. A heuristic is used to determine the resolved
+            text alignment. -->
+        <attr name="textAlignment" format="integer">
+            <!-- Default -->
+            <enum name="inherit" value="0" />
+            <!-- Default for the root view. The gravity determines the alignment, ALIGN_NORMAL,
+                ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s
+                text direction -->
+            <enum name="gravity" value="1" />
+            <!-- Align to the start of the paragraph, e.g. ALIGN_NORMAL. -->
+            <enum name="textStart" value="2" />
+            <!-- Align to the end of the paragraph, e.g. ALIGN_OPPOSITE. -->
+            <enum name="textEnd" value="3" />
+            <!-- Center the paragraph, e.g. ALIGN_CENTER. -->
+            <enum name="center" value="4" />
+            <!-- Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
+                layoutDirection is LTR, and ALIGN_RIGHT otherwise. -->
+            <enum name="viewStart" value="5" />
+            <!-- Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
+                layoutDirection is LTR, and ALIGN_LEFT otherwise -->
+            <enum name="viewEnd" value="6" />
+        </attr>
     </declare-styleable>
 
     <!-- Attributes that can be used with a {@link android.view.ViewGroup} or any
@@ -5528,4 +5552,21 @@
         <attr name="settingsActivity" />
     </declare-styleable>
 
+    <!-- Use <code>keyboard-layouts</code> as the root tag of the XML resource that
+         describes a collection of keyboard layouts provided by an application.
+         Each keyboard layout is declared by a <code>keyboard-layout</code> tag
+         with these attributes.
+
+         The XML resource that contains the keyboard layouts must be referenced from its
+         {@link android.hardware.input.InputManager#META_DATA_KEYBOARD_LAYOUTS}
+         meta-data entry used with broadcast receivers for
+         {@link android.hardware.input.InputManager#ACTION_QUERY_KEYBOARD_LAYOUTS}. -->
+    <declare-styleable name="KeyboardLayout">
+        <!-- The name of the keyboard layout, must be unique in the receiver. -->
+        <attr name="name" />
+        <!-- The display label of the keyboard layout. -->
+        <attr name="label" />
+        <!-- The key character map file resource. -->
+        <attr name="kcm" format="reference" />
+    </declare-styleable>
 </resources>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 4aa7dde..d414c7f 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -740,6 +740,9 @@
         <flag name="splitActionBarWhenNarrow" value="1" />
     </attr>
 
+    <!-- The name of the logical parent of the activity as it appears in the manifest. -->
+    <attr name="parentActivityName" format="string" />
+
     <!-- The <code>manifest</code> tag is the root of an
          <code>AndroidManifest.xml</code> file,
          describing the contents of an Android package (.apk) file.  One
@@ -843,6 +846,9 @@
              @hide -->
         <attr name="cantSaveState" format="boolean" />
         <attr name="uiOptions" />
+        <!-- Declare that your application will be able to deal with RTL (right to left) layouts.
+             If set to  false (default value), your application will not care about RTL layouts. -->
+        <attr name="supportsRtl" format="boolean" />
     </declare-styleable>
     
     <!-- The <code>permission</code> tag declares a security permission that can be
@@ -1345,6 +1351,7 @@
         <attr name="immersive" />
         <attr name="hardwareAccelerated" />
         <attr name="uiOptions" />
+        <attr name="parentActivityName" />
     </declare-styleable>
     
     <!-- The <code>activity-alias</code> tag declares a new
@@ -1381,6 +1388,7 @@
              component specific values). -->
         <attr name="enabled" />
         <attr name="exported" />
+        <attr name="parentActivityName" />
     </declare-styleable>
     
     <!-- The <code>meta-data</code> tag is used to attach additional
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 6d6b86b..0442be8 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -32,11 +32,9 @@
     <dimen name="toast_y_offset">64dip</dimen>
     <!-- Height of the status bar -->
     <dimen name="status_bar_height">25dip</dimen>
-    <!-- Height of the system bar (combined status + navigation, used on large screens) -->
-    <dimen name="system_bar_height">48dip</dimen>
-    <!-- Height of the horizontal navigation bar on devices that require it -->
+    <!-- Height of the bottom navigation / system bar. -->
     <dimen name="navigation_bar_height">48dp</dimen>
-    <!-- Width of the vertical navigation bar on devices that require it -->
+    <!-- Width of the navigation bar when it is placed vertically on the screen -->
     <dimen name="navigation_bar_width">42dp</dimen>
     <!-- Height of notification icons in the status bar -->
     <dimen name="status_bar_icon_size">24dip</dimen>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 9f29630..516078f 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -202,6 +202,7 @@
   <java-symbol type="id" name="action2" />
   <java-symbol type="id" name="big_picture" />
   <java-symbol type="id" name="big_text" />
+  <java-symbol type="id" name="chronometer" />
 
   <java-symbol type="attr" name="actionModeShareDrawable" />
   <java-symbol type="attr" name="alertDialogCenterButtons" />
@@ -1079,6 +1080,8 @@
   <java-symbol type="layout" name="notification_intruder_content" />
   <java-symbol type="layout" name="notification_template_base" />
   <java-symbol type="layout" name="notification_template_big_picture" />
+  <java-symbol type="layout" name="notification_template_part_time" />
+  <java-symbol type="layout" name="notification_template_part_chronometer" />
 
   <java-symbol type="anim" name="slide_in_child_bottom" />
   <java-symbol type="anim" name="slide_in_right" />
@@ -1125,6 +1128,14 @@
   <!-- From android.policy -->
   <java-symbol type="anim" name="app_starting_exit" />
   <java-symbol type="anim" name="lock_screen_behind_enter" />
+  <java-symbol type="anim" name="dock_top_enter" />
+  <java-symbol type="anim" name="dock_top_exit" />
+  <java-symbol type="anim" name="dock_bottom_enter" />
+  <java-symbol type="anim" name="dock_bottom_exit" />
+  <java-symbol type="anim" name="dock_left_enter" />
+  <java-symbol type="anim" name="dock_left_exit" />
+  <java-symbol type="anim" name="dock_right_enter" />
+  <java-symbol type="anim" name="dock_right_exit" />
   <java-symbol type="array" name="config_keyboardTapVibePattern" />
   <java-symbol type="array" name="config_longPressVibePattern" />
   <java-symbol type="array" name="config_safeModeDisabledVibePattern" />
@@ -1150,7 +1161,6 @@
   <java-symbol type="dimen" name="navigation_bar_height" />
   <java-symbol type="dimen" name="navigation_bar_width" />
   <java-symbol type="dimen" name="status_bar_height" />
-  <java-symbol type="dimen" name="system_bar_height" />
   <java-symbol type="drawable" name="ic_jog_dial_sound_off" />
   <java-symbol type="drawable" name="ic_jog_dial_sound_on" />
   <java-symbol type="drawable" name="ic_jog_dial_unlock" />
@@ -3551,7 +3561,10 @@
      =============================================================== -->
   <public type="attr" name="isolatedProcess" id="0x010103a7" />
 
+  <public type="attr" name="supportsRtl" id="0x010103a8" />
+
   <public type="attr" name="textDirection"/>
+  <public type="attr" name="textAlignment"/>
 
   <public type="attr" name="layoutDirection" />
 
@@ -3560,5 +3573,8 @@
 
   <public type="attr" name="layout_marginStart"/>
   <public type="attr" name="layout_marginEnd"/>
+  <public type="attr" name="kcm"/>
+
+  <public type="attr" name="parentActivityName" />
 
 </resources>
diff --git a/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java b/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java
index ea94fa9..58269a8 100644
--- a/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java
+++ b/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.net;
 
+import static android.net.NetworkStats.SET_ALL;
 import static android.net.NetworkStats.SET_DEFAULT;
 import static android.net.NetworkStats.SET_FOREGROUND;
 import static android.net.NetworkStats.TAG_NONE;
@@ -84,12 +85,12 @@
 
         final NetworkStats stats = mFactory.readNetworkStatsSummary();
         assertEquals(6, stats.size());
-        assertStatsEntry(stats, "lo", UID_ALL, SET_DEFAULT, TAG_NONE, 8308L, 8308L);
-        assertStatsEntry(stats, "rmnet0", UID_ALL, SET_DEFAULT, TAG_NONE, 1507570L, 489339L);
-        assertStatsEntry(stats, "ifb0", UID_ALL, SET_DEFAULT, TAG_NONE, 52454L, 0L);
-        assertStatsEntry(stats, "ifb1", UID_ALL, SET_DEFAULT, TAG_NONE, 52454L, 0L);
-        assertStatsEntry(stats, "sit0", UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L);
-        assertStatsEntry(stats, "ip6tnl0", UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L);
+        assertStatsEntry(stats, "lo", UID_ALL, SET_ALL, TAG_NONE, 8308L, 8308L);
+        assertStatsEntry(stats, "rmnet0", UID_ALL, SET_ALL, TAG_NONE, 1507570L, 489339L);
+        assertStatsEntry(stats, "ifb0", UID_ALL, SET_ALL, TAG_NONE, 52454L, 0L);
+        assertStatsEntry(stats, "ifb1", UID_ALL, SET_ALL, TAG_NONE, 52454L, 0L);
+        assertStatsEntry(stats, "sit0", UID_ALL, SET_ALL, TAG_NONE, 0L, 0L);
+        assertStatsEntry(stats, "ip6tnl0", UID_ALL, SET_ALL, TAG_NONE, 0L, 0L);
     }
 
     public void testNetworkStatsSummaryDown() throws Exception {
@@ -102,8 +103,8 @@
 
         final NetworkStats stats = mFactory.readNetworkStatsSummary();
         assertEquals(7, stats.size());
-        assertStatsEntry(stats, "rmnet0", UID_ALL, SET_DEFAULT, TAG_NONE, 1507570L, 489339L);
-        assertStatsEntry(stats, "wlan0", UID_ALL, SET_DEFAULT, TAG_NONE, 1024L, 2048L);
+        assertStatsEntry(stats, "rmnet0", UID_ALL, SET_ALL, TAG_NONE, 1507570L, 489339L);
+        assertStatsEntry(stats, "wlan0", UID_ALL, SET_ALL, TAG_NONE, 1024L, 2048L);
     }
 
     public void testNetworkStatsCombined() throws Exception {
@@ -115,7 +116,7 @@
         stageLong(40L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/tx_packets"));
 
         final NetworkStats stats = mFactory.readNetworkStatsSummary();
-        assertStatsEntry(stats, "rmnet0", UID_ALL, SET_DEFAULT, TAG_NONE, 1507570L + 10L,
+        assertStatsEntry(stats, "rmnet0", UID_ALL, SET_ALL, TAG_NONE, 1507570L + 10L,
                 2205L + 20L, 489339L + 30L, 2237L + 40L);
     }
 
@@ -128,7 +129,7 @@
         stageLong(40L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/tx_packets"));
 
         final NetworkStats stats = mFactory.readNetworkStatsSummary();
-        assertStatsEntry(stats, "rmnet0", UID_ALL, SET_DEFAULT, TAG_NONE, 10L, 20L, 30L, 40L);
+        assertStatsEntry(stats, "rmnet0", UID_ALL, SET_ALL, TAG_NONE, 10L, 20L, 30L, 40L);
     }
 
     public void testKernelTags() throws Exception {
@@ -153,9 +154,9 @@
 
         final NetworkStats stats = mFactory.readNetworkStatsSummary();
         assertEquals(6, stats.size());
-        assertStatsEntry(stats, "rmnet0", UID_ALL, SET_DEFAULT, TAG_NONE, 2112L, 24L, 700L, 10L);
-        assertStatsEntry(stats, "test1", UID_ALL, SET_DEFAULT, TAG_NONE, 6L, 8L, 10L, 12L);
-        assertStatsEntry(stats, "test2", UID_ALL, SET_DEFAULT, TAG_NONE, 1L, 2L, 3L, 4L);
+        assertStatsEntry(stats, "rmnet0", UID_ALL, SET_ALL, TAG_NONE, 2112L, 24L, 700L, 10L);
+        assertStatsEntry(stats, "test1", UID_ALL, SET_ALL, TAG_NONE, 6L, 8L, 10L, 12L);
+        assertStatsEntry(stats, "test2", UID_ALL, SET_ALL, TAG_NONE, 1L, 2L, 3L, 4L);
     }
 
     /**
diff --git a/docs/html/design/building-blocks/progress.jd b/docs/html/design/building-blocks/progress.jd
index dc3ded1..b188538 100644
--- a/docs/html/design/building-blocks/progress.jd
+++ b/docs/html/design/building-blocks/progress.jd
@@ -42,9 +42,9 @@
       <li class="value-1"><h4>Activity bar (shown with the Holo Dark theme)</h4>
         <p>
 
-An indeterminate activity bar is used at the start of an application download because Google Play hasn't
-been able to contact the server yet, and it's not possible to determine how long it will take for
-the download to begin.
+An indeterminate activity bar is used at the start of an application download because the Play Store
+app hasn't been able to contact the server yet, and it's not possible to determine how long it will
+take for the download to begin.
 
         </p>
       </li>
diff --git a/docs/html/design/building-blocks/tabs.jd b/docs/html/design/building-blocks/tabs.jd
index 2c854d3..19ed1c3 100644
--- a/docs/html/design/building-blocks/tabs.jd
+++ b/docs/html/design/building-blocks/tabs.jd
@@ -25,7 +25,7 @@
       <source src="{@docRoot}design/media/tabs_scrolly.ogv" type="video/ogg">
     </video>
     <div class="figure-caption">
-      Scrolling tabs in Google Play.
+      Scrolling tabs in the Play Store app.
       <div class="video-instructions">&nbsp;</div>
     </div>
 
diff --git a/docs/html/design/design_toc.cs b/docs/html/design/design_toc.cs
index 19b58d9..6dd8d61 100644
--- a/docs/html/design/design_toc.cs
+++ b/docs/html/design/design_toc.cs
@@ -35,6 +35,7 @@
       <li><a href="<?cs var:toroot ?>design/patterns/swipe-views.html">Swipe Views</a></li>
       <li><a href="<?cs var:toroot ?>design/patterns/selection.html">Selection</a></li>
       <li><a href="<?cs var:toroot ?>design/patterns/notifications.html">Notifications</a></li>
+      <li><a href="<?cs var:toroot ?>design/patterns/settings.html">Settings</a></li>
       <li><a href="<?cs var:toroot ?>design/patterns/compatibility.html">Compatibility</a></li>
       <li><a href="<?cs var:toroot ?>design/patterns/pure-android.html">Pure Android</a></li>
     </ul>
diff --git a/docs/html/design/downloads/index.jd b/docs/html/design/downloads/index.jd
index 618c44b..67dfd79 100644
--- a/docs/html/design/downloads/index.jd
+++ b/docs/html/design/downloads/index.jd
@@ -39,7 +39,7 @@
 <p>
   <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_Fireworks_Stencil_20120229.png">Adobe&reg; Fireworks&reg; PNG Stencil</a>
   <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_OmniGraffle_Stencil_20120229.graffle">Omni&reg; OmniGraffle&reg; Stencil</a>
-  <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_Holo_Widgets_20120229.zip">Adobe&reg; Photoshop&reg; Sources</a>
+  <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_Holo_Widgets_20120302.zip">Adobe&reg; Photoshop&reg; Sources</a>
 </p>
 
   </div>
diff --git a/docs/html/design/get-started/principles.jd b/docs/html/design/get-started/principles.jd
index 8f5b446..0b7147b 100644
--- a/docs/html/design/get-started/principles.jd
+++ b/docs/html/design/get-started/principles.jd
@@ -10,7 +10,7 @@
 <div class="layout-content-row">
   <div class="layout-content-col span-7">
 
-<h4>Delight me in surprising ways</h4>
+<h4 id="delight-me">Delight me in surprising ways</h4>
 <p>A beautiful surface, a carefully-placed animation, or a well-timed sound effect is a joy to
 experience. Subtle effects contribute to a feeling of effortlessness and a sense that a powerful
 force is at hand.</p>
@@ -28,7 +28,7 @@
 <div class="layout-content-row">
   <div class="layout-content-col span-7">
 
-<h4>Real objects are more fun than buttons and menus</h4>
+<h4 id="real-objects-more-fun">Real objects are more fun than buttons and menus</h4>
 <p>Allow people to directly touch and manipulate objects in your app. It reduces the cognitive effort
 needed to perform a task while making it more emotionally satisfying.</p>
 
@@ -45,7 +45,7 @@
 <div class="layout-content-row">
   <div class="layout-content-col span-7">
 
-<h4>Let me make it mine</h4>
+<h4 id="make-it-mine">Let me make it mine</h4>
 <p>People love to add personal touches because it helps them feel at home and in control. Provide
 sensible, beautiful defaults, but also consider fun, optional customizations that don't hinder
 primary tasks.</p>
@@ -63,7 +63,7 @@
 <div class="layout-content-row">
   <div class="layout-content-col span-7">
 
-<h4>Get to know me</h4>
+<h4 id="get-to-know-me">Get to know me</h4>
 <p>Learn peoples' preferences over time. Rather than asking them to make the same choices over and
 over, place previous choices within easy reach.</p>
 
@@ -80,7 +80,7 @@
 <div class="layout-content-row">
   <div class="layout-content-col span-7">
 
-<h4>Keep it brief</h4>
+<h4 id="keep-it-brief">Keep it brief</h4>
 <p>Use short phrases with simple words. People are likely to skip sentences if they're long.</p>
 
   </div>
@@ -96,7 +96,7 @@
 <div class="layout-content-row">
   <div class="layout-content-col span-7">
 
-<h4>Pictures are faster than words</h4>
+<h4 id="pictures-faster-than-words">Pictures are faster than words</h4>
 <p>Consider using pictures to explain ideas. They get people's attention and can be much more efficient
 than words.</p>
 
@@ -113,7 +113,7 @@
 <div class="layout-content-row">
   <div class="layout-content-col span-7">
 
-<h4>Decide for me but let me have the final say</h4>
+<h4 id="decide-for-me">Decide for me but let me have the final say</h4>
 <p>Take your best guess and act rather than asking first. Too many choices and decisions make people
 unhappy. Just in case you get it wrong, allow for 'undo'.</p>
 
@@ -130,7 +130,7 @@
 <div class="layout-content-row">
   <div class="layout-content-col span-7">
 
-<h4>Only show what I need when I need it</h4>
+<h4 id="only-show-when-i-need-it">Only show what I need when I need it</h4>
 <p>People get overwhelmed when they see too much at once. Break tasks and information into small,
 digestible chunks. Hide options that aren't essential at the moment, and teach people as they go.</p>
 
@@ -147,7 +147,7 @@
 <div class="layout-content-row">
   <div class="layout-content-col span-7">
 
-<h4>I should always know where I am</h4>
+<h4 id="always-know-where-i-am">I should always know where I am</h4>
 <p>Give people confidence that they know their way around. Make places in your app look distinct and
 use transitions to show relationships among screens. Provide feedback on tasks in progress.</p>
 
@@ -164,7 +164,7 @@
 <div class="layout-content-row">
   <div class="layout-content-col span-7">
 
-<h4>Never lose my stuff</h4>
+<h4 id="never-lose-my-stuff">Never lose my stuff</h4>
 <p>Save what people took time to create and let them access it from anywhere. Remember settings,
 personal touches, and creations across phones, tablets, and computers. It makes upgrading the
 easiest thing in the world.</p>
@@ -182,7 +182,7 @@
 <div class="layout-content-row">
   <div class="layout-content-col span-7">
 
-<h4>If it looks the same, it should act the same</h4>
+<h4 id="looks-same-should-act-same">If it looks the same, it should act the same</h4>
 <p>Help people discern functional differences by making them visually distinct rather than subtle.
 Avoid modes, which are places that look similar but act differently on the same input.</p>
 
@@ -199,7 +199,7 @@
 <div class="layout-content-row">
   <div class="layout-content-col span-7">
 
-<h4>Only interrupt me if it's important</h4>
+<h4 id="interrupt-only-if-important">Only interrupt me if it's important</h4>
 <p>Like a good personal assistant, shield people from unimportant minutiae. People want to stay
 focused, and unless it's critical and time-sensitive, an interruption can be taxing and frustrating.</p>
 
@@ -216,7 +216,7 @@
 <div class="layout-content-row">
   <div class="layout-content-col span-7">
 
-<h4>Give me tricks that work everywhere</h4>
+<h4 id="give-me-tricks">Give me tricks that work everywhere</h4>
 <p>People feel great when they figure things out for themselves. Make your app easier to learn by
 leveraging visual patterns and muscle memory from other Android apps. For example, the swipe gesture
 may be a good navigational shortcut.</p>
@@ -234,7 +234,7 @@
 <div class="layout-content-row">
   <div class="layout-content-col span-7">
 
-<h4>It's not my fault</h4>
+<h4 id="its-not-my-fault">It's not my fault</h4>
 <p>Be gentle in how you prompt people to make corrections. They want to feel smart when they use your
 app. If something goes wrong, give clear recovery instructions but spare them the technical details.
 If you can fix it behind the scenes, even better.</p>
@@ -252,7 +252,7 @@
 <div class="layout-content-row">
   <div class="layout-content-col span-7">
 
-<h4>Sprinkle encouragement</h4>
+<h4 id="sprinkle-encouragement">Sprinkle encouragement</h4>
 <p>Break complex tasks into smaller steps that can be easily accomplished. Give feedback on actions,
 even if it's just a subtle glow.</p>
 
@@ -269,7 +269,7 @@
 <div class="layout-content-row">
   <div class="layout-content-col span-7">
 
-<h4>Do the heavy lifting for me</h4>
+<h4 id="do-heavy-lifting-for-me">Do the heavy lifting for me</h4>
 <p>Make novices feel like experts by enabling them to do things they never thought they could. For
 example, shortcuts that combine multiple photo effects can make amateur photographs look amazing in
 only a few steps.</p>
@@ -287,7 +287,7 @@
 <div class="layout-content-row">
   <div class="layout-content-col span-7">
 
-<h4>Make important things fast</h4>
+<h4 id="make-important-things-fast">Make important things fast</h4>
 <p>Not all actions are equal. Decide what's most important in your app and make it easy to find and
 fast to use, like the shutter button in a camera, or the pause button in a music player.</p>
 
diff --git a/docs/html/design/media/app_structure_market.png b/docs/html/design/media/app_structure_market.png
index 3b0b786..5aa595e 100644
--- a/docs/html/design/media/app_structure_market.png
+++ b/docs/html/design/media/app_structure_market.png
Binary files differ
diff --git a/docs/html/design/media/app_structure_music_lndscp.png b/docs/html/design/media/app_structure_music_lndscp.png
index 0dd400c..67354de 100644
--- a/docs/html/design/media/app_structure_music_lndscp.png
+++ b/docs/html/design/media/app_structure_music_lndscp.png
Binary files differ
diff --git a/docs/html/design/media/app_structure_scrolltabs.png b/docs/html/design/media/app_structure_scrolltabs.png
index ef4fca4..ea742c2 100644
--- a/docs/html/design/media/app_structure_scrolltabs.png
+++ b/docs/html/design/media/app_structure_scrolltabs.png
Binary files differ
diff --git a/docs/html/design/media/app_structure_shortcut_on_item.png b/docs/html/design/media/app_structure_shortcut_on_item.png
index 3874e1d4..1341f1f 100644
--- a/docs/html/design/media/app_structure_shortcut_on_item.png
+++ b/docs/html/design/media/app_structure_shortcut_on_item.png
Binary files differ
diff --git a/docs/html/design/media/iconography_launcher_example.png b/docs/html/design/media/iconography_launcher_example.png
index a5db53e..0cce7ef9 100644
--- a/docs/html/design/media/iconography_launcher_example.png
+++ b/docs/html/design/media/iconography_launcher_example.png
Binary files differ
diff --git a/docs/html/design/media/iconography_overview.png b/docs/html/design/media/iconography_overview.png
index 688c1b5..56cd409 100644
--- a/docs/html/design/media/iconography_overview.png
+++ b/docs/html/design/media/iconography_overview.png
Binary files differ
diff --git a/docs/html/design/media/migrating_intents.png b/docs/html/design/media/migrating_intents.png
new file mode 100644
index 0000000..65fc1a5
--- /dev/null
+++ b/docs/html/design/media/migrating_intents.png
Binary files differ
diff --git a/docs/html/design/media/misc_full_galaxynexus_blank_land_span13.png b/docs/html/design/media/misc_full_galaxynexus_blank_land_span13.png
deleted file mode 100644
index bab6aca..0000000
--- a/docs/html/design/media/misc_full_galaxynexus_blank_land_span13.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/media/misc_full_galaxynexus_blank_port_span5.png b/docs/html/design/media/misc_full_galaxynexus_blank_port_span5.png
deleted file mode 100644
index bdccc2f..0000000
--- a/docs/html/design/media/misc_full_galaxynexus_blank_port_span5.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/media/misc_full_galaxynexus_blank_port_span9.png b/docs/html/design/media/misc_full_galaxynexus_blank_port_span9.png
deleted file mode 100644
index 5e0135b..0000000
--- a/docs/html/design/media/misc_full_galaxynexus_blank_port_span9.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/media/navigation_between_apps_back.png b/docs/html/design/media/navigation_between_apps_back.png
new file mode 100755
index 0000000..ded5d0a
--- /dev/null
+++ b/docs/html/design/media/navigation_between_apps_back.png
Binary files differ
diff --git a/docs/html/design/media/navigation_between_apps_inward.png b/docs/html/design/media/navigation_between_apps_inward.png
new file mode 100755
index 0000000..1f5e401
--- /dev/null
+++ b/docs/html/design/media/navigation_between_apps_inward.png
Binary files differ
diff --git a/docs/html/design/media/navigation_between_apps_up.png b/docs/html/design/media/navigation_between_apps_up.png
new file mode 100755
index 0000000..f192c88
--- /dev/null
+++ b/docs/html/design/media/navigation_between_apps_up.png
Binary files differ
diff --git a/docs/html/design/media/navigation_between_siblings_market1.png b/docs/html/design/media/navigation_between_siblings_market1.png
old mode 100644
new mode 100755
index c3148f8..8f2b3dc
--- a/docs/html/design/media/navigation_between_siblings_market1.png
+++ b/docs/html/design/media/navigation_between_siblings_market1.png
Binary files differ
diff --git a/docs/html/design/media/navigation_between_siblings_market2.png b/docs/html/design/media/navigation_between_siblings_market2.png
old mode 100644
new mode 100755
index 208be47..33b654c
--- a/docs/html/design/media/navigation_between_siblings_market2.png
+++ b/docs/html/design/media/navigation_between_siblings_market2.png
Binary files differ
diff --git a/docs/html/design/media/navigation_from_outside_up.png b/docs/html/design/media/navigation_from_outside_up.png
deleted file mode 100644
index eaa3cdb..0000000
--- a/docs/html/design/media/navigation_from_outside_up.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/media/navigation_indirect_notification.png b/docs/html/design/media/navigation_indirect_notification.png
new file mode 100644
index 0000000..6f99267
--- /dev/null
+++ b/docs/html/design/media/navigation_indirect_notification.png
Binary files differ
diff --git a/docs/html/design/media/navigation_popup_notification.png b/docs/html/design/media/navigation_popup_notification.png
new file mode 100644
index 0000000..a0a3ee7
--- /dev/null
+++ b/docs/html/design/media/navigation_popup_notification.png
Binary files differ
diff --git a/docs/html/design/media/navigation_up_vs_back_gmail.png b/docs/html/design/media/navigation_up_vs_back_gmail.png
index 71e6484..ff7adfe 100644
--- a/docs/html/design/media/navigation_up_vs_back_gmail.png
+++ b/docs/html/design/media/navigation_up_vs_back_gmail.png
Binary files differ
diff --git a/docs/html/design/media/navigation_with_back_and_up.png b/docs/html/design/media/navigation_with_back_and_up.png
index 4fb6dce..5440220 100644
--- a/docs/html/design/media/navigation_with_back_and_up.png
+++ b/docs/html/design/media/navigation_with_back_and_up.png
Binary files differ
diff --git a/docs/html/design/media/progress_activity.png b/docs/html/design/media/progress_activity.png
index 51210b4..32cf1f5 100644
--- a/docs/html/design/media/progress_activity.png
+++ b/docs/html/design/media/progress_activity.png
Binary files differ
diff --git a/docs/html/design/media/progress_download.png b/docs/html/design/media/progress_download.png
index f567f74..ab6bf58 100644
--- a/docs/html/design/media/progress_download.png
+++ b/docs/html/design/media/progress_download.png
Binary files differ
diff --git a/docs/html/design/media/settings_checkbox.png b/docs/html/design/media/settings_checkbox.png
new file mode 100644
index 0000000..6615bfb
--- /dev/null
+++ b/docs/html/design/media/settings_checkbox.png
Binary files differ
diff --git a/docs/html/design/media/settings_date_time.png b/docs/html/design/media/settings_date_time.png
new file mode 100644
index 0000000..8df92d4
--- /dev/null
+++ b/docs/html/design/media/settings_date_time.png
Binary files differ
diff --git a/docs/html/design/media/settings_dependency.png b/docs/html/design/media/settings_dependency.png
new file mode 100644
index 0000000..4821c61
--- /dev/null
+++ b/docs/html/design/media/settings_dependency.png
Binary files differ
diff --git a/docs/html/design/media/settings_flowchart.png b/docs/html/design/media/settings_flowchart.png
new file mode 100644
index 0000000..7e8623c
--- /dev/null
+++ b/docs/html/design/media/settings_flowchart.png
Binary files differ
diff --git a/docs/html/design/media/settings_grouping.png b/docs/html/design/media/settings_grouping.png
new file mode 100644
index 0000000..d271ea8
--- /dev/null
+++ b/docs/html/design/media/settings_grouping.png
Binary files differ
diff --git a/docs/html/design/media/settings_individual_on_off.png b/docs/html/design/media/settings_individual_on_off.png
new file mode 100644
index 0000000..03bea0b
--- /dev/null
+++ b/docs/html/design/media/settings_individual_on_off.png
Binary files differ
diff --git a/docs/html/design/media/settings_list_subscreen.png b/docs/html/design/media/settings_list_subscreen.png
new file mode 100644
index 0000000..385aa6a
--- /dev/null
+++ b/docs/html/design/media/settings_list_subscreen.png
Binary files differ
diff --git a/docs/html/design/media/settings_main.png b/docs/html/design/media/settings_main.png
new file mode 100644
index 0000000..f42a358
--- /dev/null
+++ b/docs/html/design/media/settings_main.png
Binary files differ
diff --git a/docs/html/design/media/settings_master_on_off.png b/docs/html/design/media/settings_master_on_off.png
new file mode 100644
index 0000000..e46bb97
--- /dev/null
+++ b/docs/html/design/media/settings_master_on_off.png
Binary files differ
diff --git a/docs/html/design/media/settings_master_on_off_2.png b/docs/html/design/media/settings_master_on_off_2.png
new file mode 100644
index 0000000..ab4e992
--- /dev/null
+++ b/docs/html/design/media/settings_master_on_off_2.png
Binary files differ
diff --git a/docs/html/design/media/settings_multiple_choice.png b/docs/html/design/media/settings_multiple_choice.png
new file mode 100644
index 0000000..9b28566
--- /dev/null
+++ b/docs/html/design/media/settings_multiple_choice.png
Binary files differ
diff --git a/docs/html/design/media/settings_overflow.png b/docs/html/design/media/settings_overflow.png
new file mode 100644
index 0000000..9000bec
--- /dev/null
+++ b/docs/html/design/media/settings_overflow.png
Binary files differ
diff --git a/docs/html/design/media/settings_slider.png b/docs/html/design/media/settings_slider.png
new file mode 100644
index 0000000..51545c8
--- /dev/null
+++ b/docs/html/design/media/settings_slider.png
Binary files differ
diff --git a/docs/html/design/media/settings_subscreen_navigation.png b/docs/html/design/media/settings_subscreen_navigation.png
new file mode 100644
index 0000000..2ab0b96
--- /dev/null
+++ b/docs/html/design/media/settings_subscreen_navigation.png
Binary files differ
diff --git a/docs/html/design/media/tabs_scrolly.mp4 b/docs/html/design/media/tabs_scrolly.mp4
index 4329243..dc9e9c6 100644
--- a/docs/html/design/media/tabs_scrolly.mp4
+++ b/docs/html/design/media/tabs_scrolly.mp4
Binary files differ
diff --git a/docs/html/design/media/tabs_scrolly.ogv b/docs/html/design/media/tabs_scrolly.ogv
index 345e57a..3e484f9 100644
--- a/docs/html/design/media/tabs_scrolly.ogv
+++ b/docs/html/design/media/tabs_scrolly.ogv
Binary files differ
diff --git a/docs/html/design/media/tabs_scrolly.webm b/docs/html/design/media/tabs_scrolly.webm
index 17e368e..e9d371d 100644
--- a/docs/html/design/media/tabs_scrolly.webm
+++ b/docs/html/design/media/tabs_scrolly.webm
Binary files differ
diff --git a/docs/html/design/media/ui_overview_all_apps.png b/docs/html/design/media/ui_overview_all_apps.png
index 467f5ad..17e7ece 100644
--- a/docs/html/design/media/ui_overview_all_apps.png
+++ b/docs/html/design/media/ui_overview_all_apps.png
Binary files differ
diff --git a/docs/html/design/patterns/actionbar.jd b/docs/html/design/patterns/actionbar.jd
index 9e3f48c..2226fec 100644
--- a/docs/html/design/patterns/actionbar.jd
+++ b/docs/html/design/patterns/actionbar.jd
@@ -176,7 +176,7 @@
       <source src="{@docRoot}design/media/tabs_scrolly.ogv" type="video/ogg">
     </video>
     <div class="figure-caption">
-      Scrolling tabs in Google Play.
+      Scrolling tabs in the Play Store app.
       <div class="video-instructions">&nbsp;</div>
     </div>
 
diff --git a/docs/html/design/patterns/app-structure.jd b/docs/html/design/patterns/app-structure.jd
index b54b12f..e2398ed 100644
--- a/docs/html/design/patterns/app-structure.jd
+++ b/docs/html/design/patterns/app-structure.jd
@@ -7,7 +7,7 @@
   single screen</li>
 <li>Apps such as Phone whose main purpose is to switch between different activities without deeper
   navigation</li>
-<li>Apps such as Gmail or Google Play that combine a broad set of data views with deep navigation</li>
+<li>Apps such as Gmail or the Play Store that combine a broad set of data views with deep navigation</li>
 </ul>
 <p>Your app's structure depends largely on the content and tasks you want to surface for your users.</p>
 <h2 id="general-structure">General Structure</h2>
@@ -60,7 +60,7 @@
 
     <img src="{@docRoot}design/media/app_structure_market.png">
     <div class="figure-caption">
-      The Google Play app's start screen primarily allows navigation into the stores for Apps, Music, Books,
+      The Play Store app's start screen primarily allows navigation into the stores for Apps, Music, Books,
       Movies and Games. It is also enriched with tailored recommendations and promotions that
       surface content of interest to the user. Search is readily available from the action bar.
     </div>
@@ -145,8 +145,8 @@
 
     <img src="{@docRoot}design/media/app_structure_scrolltabs.png">
     <div class="figure-caption">
-      Google Play uses tabs to simultaneously show category choice and content. To navigate between
-      categories, users can swipe left/right on the content.
+      The Play Store app uses tabs to simultaneously show category choice and content. To navigate
+      between categories, users can swipe left/right on the content.
     </div>
 
   </div>
diff --git a/docs/html/design/patterns/navigation.jd b/docs/html/design/patterns/navigation.jd
index d35cd82..7e288ae 100644
--- a/docs/html/design/patterns/navigation.jd
+++ b/docs/html/design/patterns/navigation.jd
@@ -13,32 +13,36 @@
 
 <h2 id="up-vs-back">Up vs. Back</h2>
 
-<p>The Up button is used to navigate within an application based on the hierarchical relationships
+<p>The Up button is used to navigate within an app based on the hierarchical relationships
 between screens. For instance, if screen A displays a list of items, and selecting an item leads to
 screen B (which presents that item in more detail), then screen B should offer an Up button that
 returns to screen A.</p>
-<p>If a screen is the topmost one in an app (i.e. the home of the app), it should not present an Up
+<p>If a screen is the topmost one in an app (that is, the app's home), it should not present an Up
 button.</p>
-<p>The system Back key is used to navigate based on the history of screens the user has recently seen,
-in reverse chronological order&mdash;in effect, the temporal relationships between screens.</p>
+
+<p>The system Back button is used to navigate, in reverse chronological order, through the history
+of screens the user has recently worked with. It is generally based on the temporal relationships
+between screens, rather than the app's hierarchy.</p>
+
 <p>When the previously viewed screen is also the hierarchical parent of the current screen, pressing
-the Back key will have the same result as pressing an Up button -- this is a common occurrence.
-However, unlike the Up button, which ensures the user remains within your app, the Back key can
-return the user to the Home screen, or even to a different application.</p>
+the Back button has the same result as pressing an Up button&mdash;this is a common
+occurrence. However, unlike the Up button, which ensures the user remains within your app, the Back
+button can return the user to the Home screen, or even to a different app.</p>
 
 <img src="{@docRoot}design/media/navigation_up_vs_back_gmail.png">
 
-<p>The Back key also supports a few behaviors not directly tied to screen-to-screen navigation:</p>
+<p>The Back button also supports a few behaviors not directly tied to screen-to-screen navigation:
+</p>
 <ul>
-<li>Back dismisses floating windows (dialogs, popups)</li>
-<li>Back dismisses contextual action bars, and removes the highlight from the selected items</li>
-<li>Back hides the onscreen keyboard (IME)</li>
+<li>Dismisses floating windows (dialogs, popups)</li>
+<li>Dismisses contextual action bars, and removes the highlight from the selected items</li>
+<li>Hides the onscreen keyboard (IME)</li>
 </ul>
 <h2 id="within-app">Navigation Within Your App</h2>
 
 <h4>Navigating to screens with multiple entry points</h4>
 <p>Sometimes a screen doesn't have a strict position within the app's hierarchy, and can be reached
-from multiple entry points&mdash;e.g., a settings screen which can be navigated to from any screen
+from multiple entry points&mdash;such as a settings screen that can be reached from any other screen
 in your app. In this case, the Up button should choose to return to the referring screen, behaving
 identically to Back.</p>
 <h4>Changing view within a screen</h4>
@@ -50,7 +54,7 @@
 <li>Switching views using a dropdown (aka collapsed tabs)</li>
 <li>Filtering a list</li>
 <li>Sorting a list</li>
-<li>Changing display characteristics (e.g. zooming)</li>
+<li>Changing display characteristics (such as zooming)</li>
 </ul>
 <h4>Navigating between sibling screens</h4>
 <p>When your app supports navigation from a list of items to a detail view of one of those items, it's
@@ -61,56 +65,140 @@
 
 <img src="{@docRoot}design/media/navigation_between_siblings_gmail.png">
 
-<p>However, a notable exception to this occurs when browsing between "related" detail views not tied
-together by the referring list&mdash;for example, when browsing on Google Play between apps from
+<p>However, a notable exception to this occurs when browsing between related detail views not tied
+together by the referring list&mdash;for example, when browsing in the Play Store between apps from
 the same developer, or albums by the same artist. In these cases, following each link does create
-history, causing the Back button to step through each screen of related content which has been
-viewed. Up should continue to bypass these related screens and navigate to the most recently viewed
-container screen.</p>
+history, causing the Back button to step through each previously viewed screen. Up should continue
+to bypass these related screens and navigate to the most recently viewed container screen.</p>
 
 <img src="{@docRoot}design/media/navigation_between_siblings_market1.png">
 
 <p>You have the ability to make the Up behavior even smarter based on your knowledge of detail
-view. If we extend our Google Play sample from above, imagine the user has navigated from the last Book
-viewed to the details for the Movie adaptation. In that case, Up can return to a container (Movies)
-which the user had not previously navigated through.</p>
+view. Extending the Play Store example from above, imagine the user has navigated from the last
+Book viewed to the details for the Movie adaptation. In that case, Up can return to a container
+(Movies) which the user hasn't previously navigated through.</p>
 
 <img src="{@docRoot}design/media/navigation_between_siblings_market2.png">
 
-<h2 id="from-outside">Navigation From Outside Your App</h2>
+<h2 id="into-your-app">Navigation into Your App via Home Screen Widgets and Notifications</h2>
 
-<p>There are two categories of navigation from outside your app to screens deep within the app's
-hierarchy:</p>
+<p>You can use Home screen widgets or notifications to help your users navigate directly to screens
+deep within your app's hierarchy. For example, Gmail's Inbox widget and new message notification can
+both bypass the Inbox screen, taking the user directly to a conversation view.</p>
+
+<p>For both of these cases, handle the Up button as follows:</p>
+
 <ul>
-<li>App-to-app navigation, such as via intent completion.</li>
-<li>System-to-app navigation, such as via notifications and home screen widgets.</li>
+<li><em>If the destination screen is typically reached from one particular screen within your
+app</em>, Up should navigate to that screen.</li>
+<li><em>Otherwise</em>, Up should navigate to the topmost ("Home") screen of your app.</li>
 </ul>
-<p>Gmail provides examples of each of these. For app-to-app navigation, a "Share" intent goes directly
-to the compose screen. For system-to-app navigation, both a new message notification and a home
-screen widget can bypass the Inbox screen, taking the user directly to a conversation view.</p>
-<h4>App-to-app navigation</h4>
-<p>When navigating deep into your app's hierarchy directly from another app via an intent, Back will
-return to the referring app.</p>
-<p>The Up button is handled as follows:
-- If the destination screen is typically reached from one particular screen within your app, Up
-  should navigate to that screen.
-- Otherwise, Up should navigate to the topmost ("Home") screen of your app.</p>
-<p>For example, after choosing to share a book being viewed on Google Play, the user navigates directly to
-Gmail's compose screen. From there, Up returns to the Inbox (which happens to be both the
-typical referrer to compose, as well as the topmost screen of the app), while Back returns to
-Google Play.</p>
 
-<img src="{@docRoot}design/media/navigation_from_outside_up.png">
+<p>In the case of the Back button, you should make navigation more predictable by inserting into the
+task's back stack the complete upward navigation path to the app's topmost screen. This allows users
+who've forgotten how they entered your app to navigate to the app's topmost screen before
+exiting.</p>
 
-<h4>System-to-app navigation</h4>
-<p>If your app was reached via the system mechanisms of notifications or home screen widgets, Up
-behaves as described for app-to-app navigation, above.</p>
-<p>For the Back key, you should make navigation more predictably by inserting into the task's back
-stack the complete upward navigation path to the app's topmost screen. This way, a user who has
-forgotten how they entered your app can safely navigate to the app's topmost screen before exiting
-it.</p>
-<p>For example, Gmail's Home screen widget has a button for diving directly to its compose screen.
-After following that path, the Back key first returns to the Inbox, and from there continues to
-Home.</p>
+<p>As an example, Gmail's Home screen widget has a button for diving directly to its compose
+screen. Up or Back from the compose screen would take the user to the Inbox, and from there the
+Back button continues to Home.</p>
 
 <img src="{@docRoot}design/media/navigation_from_outside_back.png">
+
+<h4>Indirect notifications</h4>
+
+<p>When your app needs to present information about multiple events simultaneously, it can use a
+single notification that directs the user to an interstitial screen. This screen summarizes these
+events, and provides paths for the user to dive deeply into the app. Notifications of this style are
+called <em>indirect notifications</em>.</p>
+
+<p>Unlike standard (direct) notifications, pressing Back from an indirect notification's
+interstitial screen returns the user to the point the notification was triggered from&mdash;no
+additional screens are inserted into the back stack. Once the user proceeds into the app from its
+interstitial screen, Up and Back behave as for standard notifications, as described above:
+navigating within the app rather than returning to the interstitial.</p>
+
+<p>For example, suppose a user in Gmail receives an indirect notification from Calendar. Touching
+this notification opens the interstitial screen, which displays reminders for several different
+events. Touching Back from the interstitial returns the user to Gmail. Touching on a particular
+event takes the user away from the interstitial and into the full Calendar app to display details of
+the event. From the event details, Up and Back navigate to the top-level view of Calendar.</p>
+
+<img src="{@docRoot}design/media/navigation_indirect_notification.png">
+
+<h4>Pop-up notifications</h4>
+
+<p><em>Pop-up notifications</em> bypass the notification drawer, instead appearing directly in
+front of the user. They are rarely used, and <strong>should be reserved for occasions where a timely
+response is required and the interruption of the user's context is necessary</strong>. For example,
+Talk uses this style to alert the user of an invitation from a friend to join a video chat, as this
+invitation will automatically expire after a few seconds.</p>
+
+<p>In terms of navigation behavior, pop-up notifications closely follow the behavior of an indirect
+notification's interstitial screen. Back dismisses the pop-up notification. If the user navigates
+from the pop-up into the notifying app, Up and Back follow the rules for standard notifications,
+navigating within the app.</p>
+
+<img src="{@docRoot}design/media/navigation_popup_notification.png">
+
+<h2 id="between-apps">Navigation Between Apps</h2>
+
+<p>One of the fundamental strengths of the Android system is the ability for apps to activate each
+other, giving the user the ability to navigate directly from one app into another. For example, an
+app that needs to capture a photo can activate the Camera app, which will return the photo
+to the referring app. This is a tremendous benefit to both the developer, who can easily leverage
+code from other apps, and the user, who enjoys a consistent experience for commonly performed
+actions.</p>
+
+<p>To understand app-to-app navigation, it's important to understand the Android framework behavior
+discussed below.</p>
+
+<h4>Activities, tasks, and intents</h4>
+
+<p>In Android, an <strong>activity</strong> is an application component that defines a screen of
+information and all of the associated actions the user can perform. Your app is a collection of
+activities, consisting of both the activities you create and those you re-use from other apps.</p>
+
+<p>A <strong>task</strong> is the sequence of activities a user follows to accomplish a goal. A
+single task can make use of activities from just one app, or may draw on activities from a number
+of different apps.</p>
+
+<p>An <strong>intent</strong> is a mechanism for one app to signal it would like another
+app's assistance in performing an action. An app's activities can indicate which intents
+they can respond to. For common intents such as "Share", the user may have many apps installed
+that can fulfill that request.</p>
+
+<h4>Example: navigating between apps to support sharing</h4>
+
+<p>To understand how activities, tasks, and intents work together, consider how one app allows users
+to share content by using another app. For example, launching the Play Store app from Home begins
+new Task A (see figure below). After navigating through the Play Store and touching a promoted book
+to see its details, the user remains in the same task, extending it by adding activities. Triggering
+the Share action prompts the user with a dialog listing each of the activities (from different apps)
+which have registered to handle the Share intent.</p>
+
+<img src="{@docRoot}design/media/navigation_between_apps_inward.png">
+
+<p>When the user elects to share via Gmail, Gmail's compose activity is added as a continuation of
+Task A&mdash;no new task is created. If Gmail had its own task running in the background, it would
+be unaffected.</p>
+
+<p>From the compose activity, sending the message or touching the Back button returns the user to
+the book details activity. Subsequent touches of Back continue to navigate back through the Play
+Store, ultimately arriving at Home.</p>
+
+<img src="{@docRoot}design/media/navigation_between_apps_back.png">
+
+<p>However, by touching Up from the compose activity, the user indicates a desire to remain within
+Gmail. Gmail's conversation list activity appears, and a new Task B is created for it. New tasks are
+always rooted to Home, so touching Back from the conversation list returns there.</p>
+
+<img src="{@docRoot}design/media/navigation_between_apps_up.png">
+
+<p>Task A persists in the background, and the user may return to it later (for example, via the
+Recents screen). If Gmail already had its own task running in the background, it would be replaced
+with Task B&mdash;the prior context is abandoned in favor of the user's new goal.</p>
+
+<p>When your app registers to handle intents with an activity deep within the app's hierarchy,
+refer to <a href="#into-your-app">Navigation into Your App via Home Screen Widgets and
+Notifications</a> for guidance on how to specify Up navigation.</p>
diff --git a/docs/html/design/patterns/pure-android.jd b/docs/html/design/patterns/pure-android.jd
index 8ed1347..77813c0 100644
--- a/docs/html/design/patterns/pure-android.jd
+++ b/docs/html/design/patterns/pure-android.jd
@@ -48,7 +48,8 @@
 document or deleting.</p>
 <p>As you are migrating your app to Android, please swap out platform-specific icons with their Android
 counterparts.</p>
-<p>You can find a wide variety of icons for use in your app in the Android SDK.</p>
+<p>You can find a wide variety of icons for use in your app on the
+<a href="{@docRoot}design/downloads/index.html">Downloads</a> page.</p>
 
   </div>
   <div class="layout-content-col span-8">
@@ -89,6 +90,33 @@
 <div class="layout-content-row">
   <div class="layout-content-col span-5">
 
+<h4>Don't hardcode links to other apps</h4>
+<p>In some cases you might want your app to take advantage of another app's feature set. For
+example, you may want to share the content that your app created via a social network or messaging
+app, or view the content of a weblink in a browser. Don't use hard-coded, explicit links to
+particular apps to achieve this. Instead, use Android's intent API to launch an activity chooser
+which lists all applications that are set up to handle the particular request. This lets the user
+complete the task with their preferred app. For sharing in particular, consider using the <em>Share
+Action Provider</em> in your action bar to provide faster access to the user's most recently used
+sharing target.</p>
+
+  </div>
+  <div class="layout-content-col span-8">
+
+    <img src="{@docRoot}design/media/migrating_intents.png">
+    <div class="figure-caption">
+      Link to other apps with the activity chooser or use the <em>Share Action Provider</em> in the
+      action bar.
+    </div>
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-5">
+
 <h4>Don't use labeled back buttons on action bars</h4>
 <p>Other platforms use an explicit back button with label to allow the user to navigate up the
 application's hierarchy. Instead, Android uses the main action bar's app icon for hierarchical
diff --git a/docs/html/design/patterns/settings.jd b/docs/html/design/patterns/settings.jd
new file mode 100644
index 0000000..3b28b84
--- /dev/null
+++ b/docs/html/design/patterns/settings.jd
@@ -0,0 +1,689 @@
+page.title=Settings
+@jd:body
+
+<p>Settings is a place in your app where users indicate their preferences for how your app should
+behave. This benefits users because:</p>
+
+<ul>
+<li>You don't need to interrupt them with the same questions over and over when certain situations
+arise. The settings predetermine what will always happen in those situations (see design
+principle: <a href="{@docRoot}design/get-started/principles.html#decide-for-me">Decide for me but
+let me have the final say</a>).</li>
+<li>You help them feel at home and in control (see design principle:
+<a href="{@docRoot}design/get-started/principles.html#make-it-mine">Let me make it mine</a>).</li>
+</ul>
+
+<h2 id="flow-structure">Flow and Structure</h2>
+
+<h4 id="settings-access">Provide access to Settings in the action overflow</h4>
+
+<p>Settings is given low prominence in the UI because it's not frequently needed. Even if there's
+room in the <a href="{@docRoot}design/patterns/actionbar.html">action bar</a>, never make Settings
+an action button. Always keep it in the action overflow and label it "Settings". Place it below
+all other items except "Help".</p>
+
+<img src="{@docRoot}design/media/settings_overflow.png">
+
+<div class="vspace size-2">&nbsp;</div>
+
+<h4 id="what-to-make-a-setting">Avoid the temptation to make everything a setting</h4>
+
+<p>Because Settings is a few navigational steps away, no matter how many items you have, they'll
+never clutter up the core part of your UI. This may seem like good news, but it also poses a
+challenge.</p>
+
+<p>Settings can be a tempting place to keep a lot of stuff&mdash;like a hall closet where things
+get stashed when you tidy up before company comes over. It's not a place where you spend lots of
+time, so it's easy to rationalize and ignore its cluttered condition. But when users visit
+Settings&mdash;however infrequently&mdash;they'll have the same expectations for the experience as
+they do everywhere else in your app. More settings means more choices to make, and too many are
+overwhelming.</p>
+
+<p>So don't punt on the difficult product decisions and debates that can bring on the urge to
+"just make it a setting". For each control you're considering adding to Settings, make sure it
+meets the bar:</p>
+
+<img src="{@docRoot}design/media/settings_flowchart.png">
+
+<div class="vspace size-3">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-5 with-callouts">
+
+<h4 id="group-settings">If you still have lots of settings, group related settings together</h4>
+
+<p>The number of items an average human can hold in short-term memory is 7&plusmn;2. If you
+present a list of 10 or more settings (even after applying the criteria above), users will have
+more difficulty scanning, comprehending, and processing them.</p>
+
+<p>You can remedy this by dividing some or all of the settings into groups, effectively turning
+one long list into multiple shorter lists. A group of related settings can be presented in one of
+two ways:</p>
+
+<ol>
+<li><h4>Under a section divider</h4></li>
+<li><h4>In a separate subscreen</h4></li>
+</ol>
+
+<p>You can use one or both these grouping techniques to organize your app's settings.</p>
+
+<p>For example, in the main screen of the Android Settings app, each item in the list navigates
+to a subscreen of related settings. In addition, the items themselves are grouped under section
+dividers.</p>
+
+  </div>
+  <div class="layout-content-col span-8">
+
+    <img src="{@docRoot}design/media/settings_grouping.png">
+
+  </div>
+</div>
+
+<p>Grouping settings is not an exact science, but here's some advice for how to approach it, based
+on the total number of settings in your app.</p>
+
+<div class="vspace size-1">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-2">
+
+<h4>7 or fewer</h4>
+
+  </div>
+  <div class="layout-content-col span-11">
+
+<p>Don't group them at all. It won't benefit users and will seem like overkill.</p>
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-2">
+
+<h4>8 to 10</h4>
+
+  </div>
+  <div class="layout-content-col span-11">
+
+<p>Try grouping related settings under 1 or 2 section dividers. If you have any "singletons"
+(settings that don't relate to any other settings and can't be grouped under your section
+dividers), treat them as follows:</p>
+
+<ul>
+<li>If they include some of your most important settings, list them at the top without a section
+divider.</li>
+<li>Otherwise, list them at the bottom with a section divider called "OTHER", in order of
+importance.</li>
+</ul>
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-2">
+
+<h4>11 to 15</h4>
+
+  </div>
+  <div class="layout-content-col span-11">
+
+<p>Same advice as above, but try 2 to 4 section dividers.</p>
+
+<p>Also, try the following to reduce the list:</p>
+
+<ul>
+<li>If 2 or more of the settings are mainly for power users, move them out of your main Settings
+screen and into an "Advanced" subscreen. Place an item in the action overflow called "Advanced" to
+navigate to it.</li>
+<li>Look for "doubles": two settings that relate to one another, but not to any other settings.
+Try to combine them into one setting, using the design patterns described later in this section.
+For example, you might be able to redesign two related checkbox settings into one multiple choice
+setting.</li>
+</ul>
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-2">
+
+<h4>16 or more</h4>
+
+  </div>
+  <div class="layout-content-col span-11">
+
+<p>If you have any instances of 4 or more related settings, group them under a subscreen. Then use
+the advice suggested above for the reduced list size.</p>
+
+  </div>
+</div>
+
+
+<h2 id="patterns">Design Patterns</h2>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-3">
+
+<h4>Checkbox</h4>
+<p>Use this pattern for a setting that is either selected or not selected.</p>
+
+  </div>
+  <div class="layout-content-col span-10">
+
+<img src="{@docRoot}design/media/settings_checkbox.png">
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-3">
+
+<h4>Multiple choice</h4>
+<p>Use this pattern for a setting that needs to present a discrete set of options, from which the
+user can choose only one.</p>
+
+  </div>
+  <div class="layout-content-col span-10">
+
+<img src="{@docRoot}design/media/settings_multiple_choice.png">
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-3">
+
+<h4>Slider</h4>
+<p>Use this pattern for a setting where the range of values are not discrete and fall along a
+continuum.</p>
+
+  </div>
+  <div class="layout-content-col span-10">
+
+<img src="{@docRoot}design/media/settings_slider.png">
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-3">
+
+<h4>Date/time</h4>
+<p>Use this pattern for a setting that needs to collect a date and/or time from the user.</p>
+
+  </div>
+  <div class="layout-content-col span-10">
+
+<img src="{@docRoot}design/media/settings_date_time.png">
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-3">
+
+<h4>Subscreen navigation</h4>
+<p>Use this pattern for navigating to a subscreen or sequence of subscreens that guide the user
+through a more complex setup process.</p>
+<ul>
+<li>If navigating to a single subscreen, use the same title in both the subscreen and the label
+navigating to it.</li>
+<li>If navigating to a sequence of subscreens (as in this example), use a title that describes the
+first step in the sequence.</li>
+</ul>
+
+  </div>
+  <div class="layout-content-col span-10">
+
+<img src="{@docRoot}design/media/settings_subscreen_navigation.png">
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-3">
+
+<h4>List subscreen</h4>
+<p>Use this pattern for a setting or category of settings that contains a list of equivalent items.
+</p>
+<p>The label provides the name of the item, and secondary text may be used for status. (In this
+example, status is reinforced with an icon to the right of the label.) Any actions associated with
+the list appear in the action bar rather than the list itself.</p>
+
+  </div>
+  <div class="layout-content-col span-10">
+
+<img src="{@docRoot}design/media/settings_list_subscreen.png">
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-3">
+
+<h4>Master on/off switch</h4>
+<p>Use this pattern for a category of settings that need a mechanism for turning on or off as a
+whole.</p>
+<p>An on/off switch is placed as the first item in the action bar of a subscreen. When the switch
+is turned off, the items in the list disappear, replaced by text that describes why the list is
+empty. If any actions require the switch to be on, they become disabled.</p>
+
+  </div>
+  <div class="layout-content-col span-10">
+
+<img src="{@docRoot}design/media/settings_master_on_off.png">
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-3">
+
+<div class="vspace size-2">&nbsp;</div>
+
+<p>You can also echo the master on/off switch in the menu item that leads to the subscreen.
+However, you should only do this in cases where users rarely need to access the subscreen once
+it's initially set up and more often just want to toggle the switch.</p>
+
+  </div>
+  <div class="layout-content-col span-10">
+
+<img src="{@docRoot}design/media/settings_master_on_off_2.png">
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-3">
+
+<h4>Individual on/off switch</h4>
+<p>Use this pattern for an individual setting that requires a more elaborate description than can
+be provided in checkbox form.</p>
+<p>The on/off switch only appears in the subscreen so that users aren't able to toggle it without
+also being exposed to the descriptive text. Secondary text appears below the setting label to
+reflect the current selection.</p>
+<p>In this example, Android Beam is on by default. Since users might not know what this setting
+does, we made the status more descriptive than just "On".</p>
+
+  </div>
+  <div class="layout-content-col span-10">
+
+<img src="{@docRoot}design/media/settings_individual_on_off.png">
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-3">
+
+<h4>Dependency</h4>
+<p>Use this pattern for a setting that changes availability based on the value of another setting.
+</p>
+<p>The disabled setting appears below its dependency, without any indentation. If the setting
+includes a status line, it says "Unavailable", and if the reason isn't obvious, a brief
+explanation is included in the status.</p>
+<p>If a given setting is a dependency to 3 or more settings, consider using a subscreen with a
+master on/off switch so that your main settings screen isn't cluttered by lots of disabled items.
+</p>
+
+  </div>
+  <div class="layout-content-col span-10">
+
+<img src="{@docRoot}design/media/settings_dependency.png">
+
+  </div>
+</div>
+
+<h2 id="defaults">Defaults</h2>
+
+<p>Take great care in choosing default values for each of your settings. Because settings
+determine app behavior, your choices will contribute to users' first impressions of your app. Even
+though users can change settings, they'll expect the initial states to be sensible. The following
+questions (when applicable) may help inform your decisions:</p>
+
+<ul>
+<li>Which choice would most users be likely to choose on their own if there were no default?</li>
+<li>Which choice is the most neutral or middle-of-the-road?</li>
+<li>Which choice is the least risky, controversial, or over-the-top?</li>
+<li>Which choice uses the least amount of battery or mobile data?</li>
+<li>Which choice best supports the design principle
+<a href="{@docRoot}design/get-started/principles.html#never-lose-my-stuff">Never lose my stuff</a>?</li>
+<li>Which choice best supports the design principle
+<a href="{@docRoot}design/get-started/principles.html#interrupt-only-if-important">Only interrupt
+me if it's important</a>?
+</li>
+</ul>
+
+<h2 id="writing">Writing Guidelines</h2>
+
+<h4>Label clearly and concisely</h4>
+
+<p>Writing a good label for a setting can be challenging because space is very limited. You only
+get one line, and it's incredibly short on the smallest of devices. Follow these guidelines to
+make your labels brief, meaningful, and scannable:</p>
+
+<ul>
+<li>Write each label in sentence case (i.e. only the first word and proper nouns are capitalized).
+</li>
+<li>Don't start a label with an instructional verb like "Set", "Change", "Edit", "Modify",
+"Manage", "Use", "Select", or "Choose". Users already understand that they can do these things to
+settings.</li>
+<li>Likewise, don't end a label with a word like "setting" or "settings". It's already implied.
+</li>
+<li>If the setting is part of a grouping, don't repeat the word(s) used in the section divider or
+subscreen title.</li>
+<li>Avoid starting a label with a negative word like "Don't" or "Never". For example, "Don't
+allow" could be rephrased to "Block".</li>
+<li>Steer clear of technical jargon as much as possible, unless it's a term widely understood by
+your target users. Use common verbs and nouns to convey the setting's purpose rather than its
+underlying technology.</li>
+<li>Don't refer to the user. For example, for a setting allowing the user to turn notifications on
+or off, label it "Notifications" instead of "Notify me".</li>
+</ul>
+
+<p>Once you've decided on labels for your settings, be sure to preview them on an
+<a href="{@docRoot}design/style/metrics-grids.html">LDPI handset</a> in portrait to make sure
+they'll fit everywhere.</p>
+
+<h4>Secondary text below is for status, not description&hellip;</h4>
+
+<p>Before Ice Cream Sandwich, we often displayed secondary text below a label to further describe
+it or provide instructions. Starting in Ice Cream Sandwich, we're using secondary text for status.
+</p>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+    <div class="do-dont-label bad emulate-content-left-padding">Before</div>
+
+    <table class="ui-table bad emulate-content-left-padding">
+    <thead>
+      <tr>
+        <th class="label">
+        Screen timeout
+        </th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td class="secondary-text">
+        Adjust the delay before the screen automatically turns off
+        </td>
+      </tr>
+    </tbody>
+    </table>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <div class="do-dont-label good">After</div>
+
+    <table class="ui-table good">
+    <thead>
+      <tr>
+        <th class="label">
+        Sleep
+        </th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td class="secondary-text">
+        After 10 minutes of activity
+        </td>
+      </tr>
+    </tbody>
+    </table>
+
+  </div>
+</div>
+
+<p>Status in secondary text has the following benefits:</p>
+<ul>
+<li>Users can see at a glance what the current value of a setting is without having to navigate
+any further.</li>
+<li>It applies the design principle
+<a href="{@docRoot}design/get-started/principles.html#keep-it-brief">Keep it brief</a>, which
+users greatly appreciate.</li>
+</ul>
+
+<h4>&hellip;unless it's a checkbox setting</h4>
+<p>There's one important exception to the using secondary text for status: checkbox settings.
+Here, use secondary text for description, not status. Status below a checkbox is unnecessary
+because the checkbox already indicates it. The reason why it's appropriate to have a description
+below a checkbox setting is because&mdash;unlike other controls&mdash;it doesn't display a dialog
+or navigate to another screen where additional information can be provided.</p>
+
+<p>That said, if a checkbox setting's label is clear enough on its own, there's no need to also
+provide a description. Only include one if necessary.</p>
+
+<p>Follow these guidelines to write checkbox setting descriptions:</p>
+<ul>
+<li>Keep it to one sentence and don't use ending punctuation.</li>
+<li>Convey what happens when the setting is checked, phrased in the form of a command. Example:
+"Allow data exchange", not "Allows data exchange".</li>
+<li>Avoid repetition by choosing words that don't already appear in the label.</li>
+<li>Don't refer to the user unless it's necessary for understanding the setting.</li>
+<li>If you must refer to the user, do so in the second person ("you") rather than the first person
+("I"). Android speaks to users, not on behalf of them.</li>
+</ul>
+
+<h4>Writing examples</h4>
+
+<p>The following are examples of changes we made to labels and secondary text in the Settings app
+in Ice Cream Sandwich.</p>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+    <div class="do-dont-label bad emulate-content-left-padding">Before</div>
+
+    <table class="ui-table bad emulate-content-left-padding">
+    <thead>
+      <tr>
+        <th class="label">
+        Use tactile feedback
+        </th>
+      </tr>
+    </thead>
+    </table>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <div class="do-dont-label good">After</div>
+
+    <table class="ui-table good">
+    <thead>
+      <tr>
+        <th class="label">
+        Vibrate on touch
+        </th>
+      </tr>
+    </thead>
+    </table>
+
+  </div>
+  <div class="layout-content-col span-5">
+
+<p>In this checkbox setting, we eliminated the throwaway word "Use" and rephrased the label to be
+more direct and understandable.</p>
+
+  </div>
+
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+    <div class="do-dont-label bad emulate-content-left-padding">Before</div>
+
+    <table class="ui-table bad emulate-content-left-padding">
+    <thead>
+      <tr>
+        <th class="label">
+        Screen timeout
+        </th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td class="secondary-text">
+        Adjust the delay before the screen automatically turns off
+        </td>
+      </tr>
+    </tbody>
+    </table>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <div class="do-dont-label good">After</div>
+
+    <table class="ui-table good">
+    <thead>
+      <tr>
+        <th class="label">
+        Sleep
+        </th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td class="secondary-text">
+        After 10 minutes of activity
+        </td>
+      </tr>
+    </tbody>
+    </table>
+
+  </div>
+  <div class="layout-content-col span-5">
+
+<p>In this multiple choice setting, we changed the label to a friendlier term and also replaced
+the description with status. We put some descriptive words around the selected value, "10
+minutes", because on its own, the meaning could be misinterpreted as "sleep for 10 minutes".</p>
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+    <div class="do-dont-label bad emulate-content-left-padding">Before</div>
+
+    <table class="ui-table bad emulate-content-left-padding">
+    <thead>
+      <tr>
+        <th class="label">
+        Change screen lock
+        </th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td class="secondary-text">
+        Change or disable pattern, PIN, or password security
+        </td>
+      </tr>
+    </tbody>
+    </table>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <div class="do-dont-label good">After</div>
+
+    <table class="ui-table good">
+    <thead>
+      <tr>
+        <th class="label">
+        Screen lock
+        </th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td class="secondary-text">
+        Pattern
+        </td>
+      </tr>
+    </tbody>
+    </table>
+
+  </div>
+  <div class="layout-content-col span-5">
+
+<p>This setting navigates to a a sequence of subscreens that allow users to choose a type of
+screen lock and then set it up. We eliminated the throwaway word "Change" in the label, and
+replaced the description with the current type of screen lock set up by the user. If the user
+hasn't set up a screen lock, the secondary text says "None".</p>
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+    <div class="do-dont-label bad emulate-content-left-padding">Before</div>
+
+    <table class="ui-table bad emulate-content-left-padding">
+    <thead>
+      <tr>
+        <th class="label">
+        NFC
+        </th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td class="secondary-text">
+        Use Near Field Communication to read and exchange tags
+        </td>
+      </tr>
+    </tbody>
+    </table>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <div class="do-dont-label good">After</div>
+
+    <table class="ui-table good">
+    <thead>
+      <tr>
+        <th class="label">
+        NFC
+        </th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td class="secondary-text">
+        Allow data exchange when the phone touches another device
+        </td>
+      </tr>
+    </tbody>
+    </table>
+
+  </div>
+  <div class="layout-content-col span-5">
+
+<p>In this checkbox setting&mdash;although it's technical jargon&mdash;we kept the "NFC" label
+because: (1) we couldn't find a clear, concise alternative, and (2) user familiarity with the
+acronym is expected to increase dramatically in the next couple of years.</p>
+<p>We did, however, rewrite the description. It's far less technical than before and does a better
+job of conveying how and why you'd use NFC. We didn't include what the acronym stands for because
+it doesn't mean anything to most users and would have taken up a lot of space.</p>
+
+  </div>
+</div>
+
+<h2 id="checklist">Checklist</h2>
+<ul>
+<li><p>Make sure each item in Settings meets the criteria for belonging there.</p></li>
+<li><p>If you have more than 7 items, explore ways to group related settings.</p></li>
+<li><p>Use design patterns wherever applicable so users don't face a learning curve.</p></li>
+<li><p>Choose defaults that are safe, neutral, and fit the majority of users.</p></li>
+<li><p>Give each setting a clear, concise label and use secondary text appropriately.</p></li>
+</ul>
\ No newline at end of file
diff --git a/docs/html/design/style/writing.jd b/docs/html/design/style/writing.jd
index 80fd03e..919ea7aa 100644
--- a/docs/html/design/style/writing.jd
+++ b/docs/html/design/style/writing.jd
@@ -1,58 +1,6 @@
 page.title=Writing Style
 @jd:body
 
-<style>
-
-/* UI tables */
-
-.ui_table {
-  width: 100%;
-  background: #282828;
-  color: #fff;
-  border-radius: 2px;
-  box-shadow: 0 2px 4px rgba(0,0,0,0.25);
-  border-collapse: separate;
-}
-
-.ui_table th,
-.ui_table td {
-  padding: 5px 10px;
-}
-
-.ui_table thead th {
-  font-weight: 600;
-}
-
-.ui_table tfoot td {
-  border-top: 1px solid #494949;
-  border-right: 1px solid #494949;
-  text-align: center;
-}
-
-.ui_table tfoot td:last-child {
-  border-right: 0;
-}
-
-.list_item_margins {
-  margin-left: 30px !important;
-}
-
-.example_label {
-  margin-bottom: 10px;
-  padding-left: 20px;
-  background: transparent none no-repeat scroll 0px 3px;
-}
-
-.example_label.bad {
-  background-image: url({@docRoot}assets/design/ico_wrong.png);
-}
-
-.example_label.good {
-  background-image: url({@docRoot}assets/design/ico_good.png);
-}
-
-</style>
-
 <p>When choosing words for your app:</p>
 <ol>
 <li>
@@ -90,20 +38,20 @@
 <ol><li class="value-1"><strong>Keep it brief.</strong> From the setup wizard:</ol>
 
 <div class="layout-content-row">
-  <div class="layout-content-col span-6 list_item_margins">
+  <div class="layout-content-col span-6 layout-with-list-item-margins">
 
-    <div class="example_label bad">Too formal</div>
+    <div class="do-dont-label bad">Too formal</div>
 
-    <table class="ui_table good"><tbody><tr><td>
+    <table class="ui-table good"><tbody><tr><td>
     Consult the documentation that came with your phone for further instructions.
     </td></tr></tbody></table>
 
   </div>
   <div class="layout-content-col span-6">
 
-    <div class="example_label good">Better</div>
+    <div class="do-dont-label good">Better</div>
 
-    <table class="ui_table good"><tbody><tr><td>
+    <table class="ui-table good"><tbody><tr><td>
     Read the instructions that came with your phone.
     </td></tr></tbody></table>
 
@@ -115,11 +63,11 @@
 <ol><li class="value-2"><strong>Keep it simple.</strong> From the Location settings screen:</ol>
 
 <div class="layout-content-row">
-  <div class="layout-content-col span-6 list_item_margins">
+  <div class="layout-content-col span-6 layout-with-list-item-margins">
 
-    <div class="example_label bad">Confusing</div>
+    <div class="do-dont-label bad">Confusing</div>
 
-    <table class="ui_table bad">
+    <table class="ui-table bad">
     <thead>
       <tr>
         <th>
@@ -139,9 +87,9 @@
   </div>
   <div class="layout-content-col span-6">
 
-    <div class="example_label good">Better</div>
+    <div class="do-dont-label good">Better</div>
 
-    <table class="ui_table good">
+    <table class="ui-table good">
     <thead>
       <tr>
         <th>
@@ -167,12 +115,12 @@
 crashes:</ol>
 
 <div class="layout-content-row">
-  <div class="layout-content-col span-6 list_item_margins">
+  <div class="layout-content-col span-6 layout-with-list-item-margins">
 
-    <div class="example_label bad">Confusing and annoying&mdash;"Sorry" just rubs salt in the
+    <div class="do-dont-label bad">Confusing and annoying&mdash;"Sorry" just rubs salt in the
     wound.</div>
 
-    <table class="ui_table bad">
+    <table class="ui-table bad">
     <thead>
       <tr>
         <th colspan="3">
@@ -200,9 +148,9 @@
   </div>
   <div class="layout-content-col span-6">
 
-    <div class="example_label good">Shorter, more direct, no faux-apologetic title:<br><br></div>
+    <div class="do-dont-label good">Shorter, more direct, no faux-apologetic title:<br><br></div>
 
-    <table class="ui_table good">
+    <table class="ui-table good">
     <thead>
       <tr>
         <th colspan="3">
@@ -234,20 +182,20 @@
 <ol><li class="value-4"><strong>Put the most important thing first.</strong></ol>
 
 <div class="layout-content-row">
-  <div class="layout-content-col span-6 list_item_margins">
+  <div class="layout-content-col span-6 layout-with-list-item-margins">
 
-    <div class="example_label bad">Top news last</div>
+    <div class="do-dont-label bad">Top news last</div>
 
-    <table class="ui_table bad"><tbody><tr><td>
+    <table class="ui-table bad"><tbody><tr><td>
     77 other people +1'd this, including Larry Page.
     </td></tr></tbody></table>
 
   </div>
   <div class="layout-content-col span-6">
 
-    <div class="example_label good">Top news first</div>
+    <div class="do-dont-label good">Top news first</div>
 
-    <table class="ui_table good"><tbody><tr><td>
+    <table class="ui-table good"><tbody><tr><td>
     Larry Page and 77 others +1'd this.
     </td></tr></tbody></table>
 
@@ -255,20 +203,20 @@
 </div>
 
 <div class="layout-content-row">
-  <div class="layout-content-col span-6 list_item_margins">
+  <div class="layout-content-col span-6 layout-with-list-item-margins">
 
-    <div class="example_label bad">Task last</div>
+    <div class="do-dont-label bad">Task last</div>
 
-    <table class="ui_table bad"><tbody><tr><td>
+    <table class="ui-table bad"><tbody><tr><td>
     Touch Next to complete setup using a Wi-Fi connection.
     </td></tr></tbody></table>
 
   </div>
   <div class="layout-content-col span-6">
 
-    <div class="example_label good">Task first</div>
+    <div class="do-dont-label good">Task first</div>
 
-    <table class="ui_table good"><tbody><tr><td>
+    <table class="ui-table good"><tbody><tr><td>
     To finish setup using Wi-Fi, touch Next.
     </td></tr></tbody></table>
 
@@ -280,11 +228,11 @@
 <ol><li class="value-5"><strong>Describe only what's necessary, and no more.</strong></ol>
 
 <div class="layout-content-row">
-  <div class="layout-content-col span-6 list_item_margins">
+  <div class="layout-content-col span-6 layout-with-list-item-margins">
 
-    <div class="example_label bad">From a Setup Wizard screen</div>
+    <div class="do-dont-label bad">From a Setup Wizard screen</div>
 
-    <table class="ui_table bad">
+    <table class="ui-table bad">
     <thead>
       <tr>
         <th>
@@ -306,9 +254,9 @@
   </div>
   <div class="layout-content-col span-6">
 
-    <div class="example_label good">From a Setup Wizard screen</div>
+    <div class="do-dont-label good">From a Setup Wizard screen</div>
 
-    <table class="ui_table good">
+    <table class="ui-table good">
     <thead>
       <tr>
         <th>
diff --git a/docs/html/guide/developing/testing/testing_otheride.jd b/docs/html/guide/developing/testing/testing_otheride.jd
index 93af979..7745ae7 100644
--- a/docs/html/guide/developing/testing/testing_otheride.jd
+++ b/docs/html/guide/developing/testing/testing_otheride.jd
@@ -209,7 +209,7 @@
 <p>
   To update a test project with the <code>android</code> tool, enter:
 </p>
-<pre>android update-test-project -m &lt;main_path&gt; -p &lt;test_path&gt;</pre>
+<pre>android update test-project -m &lt;main_path&gt; -p &lt;test_path&gt;</pre>
 
 <table>
     <tr>
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index ec87de8..62d18ae 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -90,21 +90,20 @@
           <ul>
             <li>
                 <a href="<?cs var:toroot ?>guide/topics/providers/content-provider-basics.html">
-                    <span class="en">Content Provider Basics</span>
+                    <span class="en">Content Provider Basics<span
+class="new">&nbsp;new!</span></span>
                 </a>
-                <span class="new">new!</span>
             </li>
             <li>
                 <a href="<?cs var:toroot ?>guide/topics/providers/content-provider-creating.html">
-                    <span class="en">Creating a Content Provider</span>
+                    <span class="en">Creating a Content Provider<span
+class="new">&nbsp;new!</span></span>
                 </a>
-                <span class="new">new!</span>
             </li>
             <li>
                 <a href="<?cs var:toroot ?>guide/topics/providers/calendar-provider.html">
-                    <span class="en">Calendar Provider</span>
+                    <span class="en">Calendar Provider<span class="new">&nbsp;new!</span></span>
                 </a>
-                <span class="new">new!</span>
             </li>
           </ul>
       </li>
@@ -130,8 +129,8 @@
                 <span class="en">Input Events</span>
               </a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/ui/menus.html">
-               <span class="en">Menus</span>
-              </a> <span class="new">updated</span></li>
+               <span class="en">Menus<span class="new">&nbsp;new!</span></span>
+              </a></li>
           <li><a href="<?cs var:toroot ?>guide/topics/ui/actionbar.html">
                <span class="en">Action Bar</span>
               </a></li>
@@ -162,8 +161,7 @@
               </a></li>
           <li class="toggle-list">
             <div><a href="<?cs var:toroot ?>guide/topics/ui/accessibility/index.html">
-                <span class="en">Accessibility</span>
-                <span class="new">new!</span>
+                <span class="en">Accessibility<span class="new">&nbsp;new!</span></span>
             </a></div>
             <ul>
               <li><a href="<?cs var:toroot ?>guide/topics/ui/accessibility/apps.html">
@@ -514,8 +512,7 @@
           <span class="en">Multiple APK Support</span></a>
       </li>
       <li><a href="<?cs var:toroot ?>guide/market/expansion-files.html">
-          <span class="en">APK Expansion Files</span></a>
-          <span class="new">new!</span>
+          <span class="en">APK Expansion Files<span class="new">&nbsp;new!</span></span></a>
       </li>
     </ul>
   </li>
@@ -837,12 +834,6 @@
           <li><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/widget_design.html">
                 <span class="en">App Widget Design</span>
               </a></li>
-          <li><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/activity_task_design.html">
-                <span class="en">Activity and Task Design</span>
-              </a></li>
-          <li><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/menu_design.html">
-                <span class="en">Menu Design</span>
-              </a></li>
         </ul>
       </li>
       </ul>
diff --git a/docs/html/guide/practices/ui_guidelines/activity_task_design.jd b/docs/html/guide/practices/ui_guidelines/activity_task_design.jd
index f8ca3f8..8e4528e 100644
--- a/docs/html/guide/practices/ui_guidelines/activity_task_design.jd
+++ b/docs/html/guide/practices/ui_guidelines/activity_task_design.jd
@@ -3,6 +3,43 @@
 parent.link=index.html
 @jd:body
 
+
+
+
+<div id="deprecatedSticker">
+  <a href="#" 
+     onclick="$('#naMessage').show();$('#deprecatedSticker').hide();return false">
+    <strong>This doc is deprecated</strong></a>
+</div>
+
+
+<div id="naMessage" style="display:block">
+<div><p><strong>This document has been deprecated.</strong></p>
+ <p>For information about designing an activity structure and navigation, read the design guidelines
+for <a href="{@docRoot}design/patterns/app-structure.html">App Structure</a> and
+<a href="{@docRoot}design/patterns/navigation.html">Navigation</a>, or the developer guide
+about <a
+href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks and Back Stack</a>.</p>
+
+ <input style="margin-top:1em;padding:5px" type="button"
+        value="That's nice, but I still want to read this document"
+onclick="$('#naMessage').hide();$('#deprecatedSticker').show()" />
+</div>
+</div>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 <div id="qv-wrapper">
 <div id="qv">
 
diff --git a/docs/html/guide/practices/ui_guidelines/index.jd b/docs/html/guide/practices/ui_guidelines/index.jd
index 3255275..24fb855 100644
--- a/docs/html/guide/practices/ui_guidelines/index.jd
+++ b/docs/html/guide/practices/ui_guidelines/index.jd
@@ -39,26 +39,6 @@
 design widgets that fit with others on the Home screen. They include links to
 graphics files and templates that will make your designer's life easier.</dd>
 </dl>
- <dl>
-  <dt><a href="{@docRoot}guide/practices/ui_guidelines/activity_task_design.html">Activity and Task Design Guidelines</a> </dt>
-  <dd>Activities are the basic, independent building blocks of applications.
-      As you design your application's UI and feature set, you are free to
-      re-use activities from other applications as if they were yours,
-      to enrich and extend your application.   These guidelines
-      describe how activities work, illustrates them with examples, and
-      describes important underlying principles and mechanisms, such as
-      multitasking, activity reuse, intents, the activity stack, and 
-      tasks. It covers this all from a high-level design perspective.
-</dd>
-  <dt><a href="{@docRoot}guide/practices/ui_guidelines/menu_design.html">Menu Design Guidelines</a> </dt>
-  <dd>Android applications make use of Option menus and Context menus 
-      that enable users to perform operations and navigate to other parts
-      of your application or to other applications.  These guidelines describe
-      the difference between Options anontext menus, how to arrange
-      menu items, when to put commands on-screen, and other details about
-      menu design.
-</dd>
-</dl>
 
 
 
diff --git a/docs/html/guide/practices/ui_guidelines/menu_design.jd b/docs/html/guide/practices/ui_guidelines/menu_design.jd
index 7576b6c..b4e2ea7 100644
--- a/docs/html/guide/practices/ui_guidelines/menu_design.jd
+++ b/docs/html/guide/practices/ui_guidelines/menu_design.jd
@@ -2,7 +2,38 @@
 parent.title=UI Guidelines
 parent.link=index.html
 @jd:body
+
+
+
+
+<div id="deprecatedSticker">
+  <a href="#" 
+     onclick="$('#naMessage').show();$('#deprecatedSticker').hide();return false">
+    <strong>This doc is deprecated</strong></a>
+</div>
+
+
+<div id="naMessage" style="display:block">
+<div><p><strong>This document has been deprecated.</strong></p>
+ <p>For design guidelines about adding user actions and other options, read the design guidelines 
+for <a href="{@docRoot}design/patterns/actionbar.html">Action Bar</a> or the developer guide about
+<a href="{@docRoot}guide/topics/ui/menus.html">Menus</a>.</p>
+
+ <input style="margin-top:1em;padding:5px" type="button"
+        value="That's nice, but I still want to read this document"
+onclick="$('#naMessage').hide();$('#deprecatedSticker').show()" />
+</div>
+</div>
 	
+
+
+
+
+
+
+
+
+
 <div id="qv-wrapper">
 <div id="qv">
 			
diff --git a/docs/html/images/training/cool-places.png b/docs/html/images/training/cool-places.png
new file mode 100755
index 0000000..769b5b7
--- /dev/null
+++ b/docs/html/images/training/cool-places.png
Binary files differ
diff --git a/docs/html/images/training/panoramio-grid.png b/docs/html/images/training/panoramio-grid.png
new file mode 100755
index 0000000..45c0eb5
--- /dev/null
+++ b/docs/html/images/training/panoramio-grid.png
Binary files differ
diff --git a/docs/html/resources/resources_toc.cs b/docs/html/resources/resources_toc.cs
index f003e75..5297c23 100644
--- a/docs/html/resources/resources_toc.cs
+++ b/docs/html/resources/resources_toc.cs
@@ -100,8 +100,9 @@
       
       <li class="toggle-list">
         <div><a href="<?cs var:toroot ?>training/efficient-downloads/index.html">
-            <span class="en">Transferring Data Without Draining the Battery</span>
-          </a> <span class="new">new!</span></div>
+            <span class="en">Transferring Data Without Draining the Battery<span
+class="new">&nbsp;new!</span></span>
+          </a></div>
         <ul>
           <li><a href="<?cs var:toroot ?>training/efficient-downloads/efficient-network-access.html">
             <span class="en">Optimizing Downloads for Efficient Network Access</span>
@@ -124,8 +125,8 @@
 
       <li class="toggle-list">
         <div><a href="<?cs var:toroot ?>training/search/index.html">
-            <span class="en">Adding Search Functionality</span>
-          </a> <span class="new">new!</span>
+            <span class="en">Adding Search Functionality<span class="new">&nbsp;new!</span></span>
+          </a>
         </div>
         <ul>
           <li><a href="<?cs var:toroot ?>training/search/setup.html">
@@ -277,12 +278,57 @@
           </a>
           </li>
         </ul>
+       </li>
+       <li class="toggle-list">
+        <div><a href="<?cs var:toroot ?>training/tv/index.html">
+           <span class="en">Designing for TV<span class="new">&nbsp;new!</span></span>
+           </a>
+        </div>
+        <ul>
+          <li><a href="<?cs var:toroot ?>training/tv/optimizing-layouts-tv.html">
+            <span class="en">Optimizing Layouts for TV</span>
+          </a>
+          </li>
+          <li><a href="<?cs var:toroot ?>training/tv/optimizing-navigation-tv.html">
+            <span class="en">Optimizing Navigation for TV</span>
+          </a>
+          </li>
+          <li><a href="<?cs var:toroot ?>training/tv/unsupported-features-tv.html">
+            <span class="en">Handling Features Not Supported on TV</span>
+          </a>
+          </li>
+        </ul>
+      </li>
+      
+      <li class="toggle-list">
+        <div><a href="<?cs var:toroot ?>training/displaying-bitmaps/index.html">
+            <span class="en">Displaying Bitmaps Efficiently<span class="new">&nbsp;new!</span></span>
+          </a>
+        </div>
+        <ul>
+          <li><a href="<?cs var:toroot ?>training/displaying-bitmaps/load-bitmap.html">
+            <span class="en">Loading Large Bitmaps Efficiently</span>
+          </a>
+          </li>
+          <li><a href="<?cs var:toroot ?>training/displaying-bitmaps/process-bitmap.html">
+            <span class="en">Processing Bitmaps Off the UI Thread</span>
+          </a>
+          </li>
+          <li><a href="<?cs var:toroot ?>training/displaying-bitmaps/cache-bitmap.html">
+            <span class="en">Caching Bitmaps</span>
+          </a>
+          </li>
+          <li><a href="<?cs var:toroot ?>training/displaying-bitmaps/display-bitmap.html">
+            <span class="en">Displaying Bitmaps in Your UI</span>
+          </a>
+          </li>
+        </ul>
       </li>
 
       <li class="toggle-list">
         <div><a href="<?cs var:toroot ?>training/accessibility/index.html">
-            <span class="en">Implementing Accessibility</span>
-          </a> <span class="new">new!</span></div>
+            <span class="en">Implementing Accessibility<span class="new">&nbsp;new!</span></span>
+          </a></div>
         <ul>
           <li><a href="<?cs var:toroot ?>training/accessibility/accessible-app.html">
             <span class="en">Developing Accessible Applications</span>
diff --git a/docs/html/shareables/training/BitmapFun.zip b/docs/html/shareables/training/BitmapFun.zip
new file mode 100644
index 0000000..e7e71f9
--- /dev/null
+++ b/docs/html/shareables/training/BitmapFun.zip
Binary files differ
diff --git a/docs/html/shareables/training/LocationAware.zip b/docs/html/shareables/training/LocationAware.zip
index e1926fa..46970cd 100644
--- a/docs/html/shareables/training/LocationAware.zip
+++ b/docs/html/shareables/training/LocationAware.zip
Binary files differ
diff --git a/docs/html/sitemap.txt b/docs/html/sitemap.txt
index 958fe56..3f26dd0 100644
--- a/docs/html/sitemap.txt
+++ b/docs/html/sitemap.txt
@@ -160,8 +160,6 @@
 http://developer.android.com/guide/practices/ui_guidelines/icon_design_dialog.html
 http://developer.android.com/guide/practices/ui_guidelines/icon_design_list.html
 http://developer.android.com/guide/practices/ui_guidelines/widget_design.html
-http://developer.android.com/guide/practices/ui_guidelines/activity_task_design.html
-http://developer.android.com/guide/practices/ui_guidelines/menu_design.html
 http://developer.android.com/guide/practices/design/performance.html
 http://developer.android.com/guide/practices/design/responsiveness.html
 http://developer.android.com/guide/practices/design/seamlessness.html
diff --git a/docs/html/training/accessibility/index.jd b/docs/html/training/accessibility/index.jd
index d5178a9..333f9f2 100644
--- a/docs/html/training/accessibility/index.jd
+++ b/docs/html/training/accessibility/index.jd
@@ -13,7 +13,6 @@
 <h2>Dependencies and prerequisites</h2>
 <ul>
   <li>Android 2.0 (API Level 5) or higher</li>
-Playback</a></li>
 </ul>
 
 <h2>You should also read</h2>
diff --git a/docs/html/training/displaying-bitmaps/cache-bitmap.jd b/docs/html/training/displaying-bitmaps/cache-bitmap.jd
new file mode 100644
index 0000000..94abe21
--- /dev/null
+++ b/docs/html/training/displaying-bitmaps/cache-bitmap.jd
@@ -0,0 +1,337 @@
+page.title=Caching Bitmaps
+parent.title=Displaying Bitmaps Efficiently
+parent.link=index.html
+
+trainingnavtop=true
+next.title=Displaying Bitmaps in Your UI
+next.link=display-bitmap.html
+previous.title=Processing Bitmaps Off the UI Thread
+previous.link=process-bitmap.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#memory-cache">Use a Memory Cache</a></li>
+  <li><a href="#disk-cache">Use a Disk Cache</a></li>
+  <li><a href="#config-changes">Handle Configuration Changes</a></li>
+</ol>
+
+<h2>You should also read</h2>
+<ul>
+  <li><a href="{@docRoot}guide/topics/resources/runtime-changes.html">Handling Runtime Changes</a></li>
+</ul>
+
+<h2>Try it out</h2>
+
+<div class="download-box">
+  <a href="{@docRoot}shareables/training/BitmapFun.zip" class="button">Download the sample</a>
+  <p class="filename">BitmapFun.zip</p>
+</div>
+
+</div>
+</div>
+
+<p>Loading a single bitmap into your user interface (UI) is straightforward, however things get more
+complicated if you need to load a larger set of images at once. In many cases (such as with
+components like {@link android.widget.ListView}, {@link android.widget.GridView} or {@link
+android.support.v4.view.ViewPager }), the total number of images on-screen combined with images that
+might soon scroll onto the screen are essentially unlimited.</p>
+
+<p>Memory usage is kept down with components like this by recycling the child views as they move
+off-screen. The garbage collector also frees up your loaded bitmaps, assuming you don't keep any
+long lived references. This is all good and well, but in order to keep a fluid and fast-loading UI
+you want to avoid continually processing these images each time they come back on-screen. A memory
+and disk cache can often help here, allowing components to quickly reload processed images.</p>
+
+<p>This lesson walks you through using a memory and disk bitmap cache to improve the responsiveness
+and fluidity of your UI when loading multiple bitmaps.</p>
+
+<h2 id="memory-cache">Use a Memory Cache</h2>
+
+<p>A memory cache offers fast access to bitmaps at the cost of taking up valuable application
+memory. The {@link android.util.LruCache} class (also available in the <a
+href="{@docRoot}reference/android/support/v4/util/LruCache.html">Support Library</a> for use back
+to API Level 4) is particularly well suited to the task of caching bitmaps, keeping recently
+referenced objects in a strong referenced {@link java.util.LinkedHashMap} and evicting the least
+recently used member before the cache exceeds its designated size.</p>
+
+<p class="note"><strong>Note:</strong> In the past, a popular memory cache implementation was a
+{@link java.lang.ref.SoftReference} or {@link java.lang.ref.WeakReference} bitmap cache, however
+this is not recommended. Starting from Android 2.3 (API Level 9) the garbage collector is more
+aggressive with collecting soft/weak references which makes them fairly ineffective. In addition,
+prior to Android 3.0 (API Level 11), the backing data of a bitmap was stored in native memory which
+is not released in a predictable manner, potentially causing an application to briefly exceed its
+memory limits and crash.</p>
+
+<p>In order to choose a suitable size for a {@link android.util.LruCache}, a number of factors
+should be taken into consideration, for example:</p>
+
+<ul>
+  <li>How memory intensive is the rest of your activity and/or application?</li>
+  <li>How many images will be on-screen at once? How many need to be available ready to come
+  on-screen?</li>
+  <li>What is the screen size and density of the device? An extra high density screen (xhdpi) device
+  like <a href="http://www.android.com/devices/detail/galaxy-nexus">Galaxy Nexus</a> will need a
+  larger cache to hold the same number of images in memory compared to a device like <a
+  href="http://www.android.com/devices/detail/nexus-s">Nexus S</a> (hdpi).</li>
+  <li>What dimensions and configuration are the bitmaps and therefore how much memory will each take
+  up?</li>
+  <li>How frequently will the images be accessed? Will some be accessed more frequently than others?
+  If so, perhaps you may want to keep certain items always in memory or even have multiple {@link
+  android.util.LruCache} objects for different groups of bitmaps.</li>
+  <li>Can you balance quality against quantity? Sometimes it can be more useful to store a larger
+  number of lower quality bitmaps, potentially loading a higher quality version in another
+  background task.</li>
+</ul>
+
+<p>There is no specific size or formula that suits all applications, it's up to you to analyze your
+usage and come up with a suitable solution. A cache that is too small causes additional overhead with
+no benefit, a cache that is too large can once again cause {@code java.lang.OutOfMemory} exceptions
+and leave the rest of your app little memory to work with.</p>
+
+<p>Here’s an example of setting up a {@link android.util.LruCache} for bitmaps:</p>
+
+<pre>
+private LruCache<String, Bitmap> mMemoryCache;
+
+&#64;Override
+protected void onCreate(Bundle savedInstanceState) {
+    ...
+    // Get memory class of this device, exceeding this amount will throw an
+    // OutOfMemory exception.
+    final int memClass = ((ActivityManager) context.getSystemService(
+            Context.ACTIVITY_SERVICE)).getMemoryClass();
+
+    // Use 1/8th of the available memory for this memory cache.
+    final int cacheSize = 1024 * 1024 * memClass / 8;
+
+    mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
+        &#64;Override
+        protected int sizeOf(String key, Bitmap bitmap) {
+            // The cache size will be measured in bytes rather than number of items.
+            return bitmap.getByteCount();
+        }
+    };
+    ...
+}
+
+public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
+    if (getBitmapFromMemCache(key) == null) {
+        mMemoryCache.put(key, bitmap);
+    }
+}
+
+public Bitmap getBitmapFromMemCache(String key) {
+    return mMemoryCache.get(key);
+}
+</pre>
+
+<p class="note"><strong>Note:</strong> In this example, one eighth of the application memory is
+allocated for our cache. On a normal/hdpi device this is a minimum of around 4MB (32/8). A full
+screen {@link android.widget.GridView} filled with images on a device with 800x480 resolution would
+use around 1.5MB (800*480*4 bytes), so this would cache a minimum of around 2.5 pages of images in
+memory.</p>
+
+<p>When loading a bitmap into an {@link android.widget.ImageView}, the {@link android.util.LruCache}
+is checked first. If an entry is found, it is used immediately to update the {@link
+android.widget.ImageView}, otherwise a background thread is spawned to process the image:</p>
+
+<pre>
+public void loadBitmap(int resId, ImageView imageView) {
+    final String imageKey = String.valueOf(resId);
+
+    final Bitmap bitmap = getBitmapFromMemCache(imageKey);
+    if (bitmap != null) {
+        mImageView.setImageBitmap(bitmap);
+    } else {
+        mImageView.setImageResource(R.drawable.image_placeholder);
+        BitmapWorkerTask task = new BitmapWorkerTask(mImageView);
+        task.execute(resId);
+    }
+}
+</pre>
+
+<p>The <a href="process-bitmap.html#BitmapWorkerTask">{@code BitmapWorkerTask}</a> also needs to be
+updated to add entries to the memory cache:</p>
+
+<pre>
+class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
+    ...
+    // Decode image in background.
+    &#64;Override
+    protected Bitmap doInBackground(Integer... params) {
+        final Bitmap bitmap = decodeSampledBitmapFromResource(
+                getResources(), params[0], 100, 100));
+        addBitmapToMemoryCache(String.valueOf(params[0]), bitmap);
+        return bitmap;
+    }
+    ...
+}
+</pre>
+
+<h2 id="disk-cache">Use a Disk Cache</h2>
+
+<p>A memory cache is useful in speeding up access to recently viewed bitmaps, however you cannot
+rely on images being available in this cache. Components like {@link android.widget.GridView} with
+larger datasets can easily fill up a memory cache. Your application could be interrupted by another
+task like a phone call, and while in the background it might be killed and the memory cache
+destroyed. Once the user resumes, your application it has to process each image again.</p>
+
+<p>A disk cache can be used in these cases to persist processed bitmaps and help decrease loading
+times where images are no longer available in a memory cache. Of course, fetching images from disk
+is slower than loading from memory and should be done in a background thread, as disk read times can
+be unpredictable.</p>
+
+<p class="note"><strong>Note:</strong> A {@link android.content.ContentProvider} might be a more
+appropriate place to store cached images if they are accessed more frequently, for example in an
+image gallery application.</p>
+
+<p>Included in the sample code of this class is a basic {@code DiskLruCache} implementation.
+However, a more robust and recommended {@code DiskLruCache} solution is included in the Android 4.0
+source code ({@code libcore/luni/src/main/java/libcore/io/DiskLruCache.java}). Back-porting this
+class for use on previous Android releases should be fairly straightforward (a <a
+href="http://www.google.com/search?q=disklrucache">quick search</a> shows others who have already
+implemented this solution).</p>
+
+<p>Here’s updated example code that uses the simple {@code DiskLruCache} included in the sample
+application of this class:</p>
+
+<pre>
+private DiskLruCache mDiskCache;
+private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB
+private static final String DISK_CACHE_SUBDIR = "thumbnails";
+
+&#64;Override
+protected void onCreate(Bundle savedInstanceState) {
+    ...
+    // Initialize memory cache
+    ...
+    File cacheDir = getCacheDir(this, DISK_CACHE_SUBDIR);
+    mDiskCache = DiskLruCache.openCache(this, cacheDir, DISK_CACHE_SIZE);
+    ...
+}
+
+class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
+    ...
+    // Decode image in background.
+    &#64;Override
+    protected Bitmap doInBackground(Integer... params) {
+        final String imageKey = String.valueOf(params[0]);
+
+        // Check disk cache in background thread
+        Bitmap bitmap = getBitmapFromDiskCache(imageKey);
+
+        if (bitmap == null) { // Not found in disk cache
+            // Process as normal
+            final Bitmap bitmap = decodeSampledBitmapFromResource(
+                    getResources(), params[0], 100, 100));
+        }
+
+        // Add final bitmap to caches
+        addBitmapToCache(String.valueOf(imageKey, bitmap);
+
+        return bitmap;
+    }
+    ...
+}
+
+public void addBitmapToCache(String key, Bitmap bitmap) {
+    // Add to memory cache as before
+    if (getBitmapFromMemCache(key) == null) {
+        mMemoryCache.put(key, bitmap);
+    }
+
+    // Also add to disk cache
+    if (!mDiskCache.containsKey(key)) {
+        mDiskCache.put(key, bitmap);
+    }
+}
+
+public Bitmap getBitmapFromDiskCache(String key) {
+    return mDiskCache.get(key);
+}
+
+// Creates a unique subdirectory of the designated app cache directory. Tries to use external
+// but if not mounted, falls back on internal storage.
+public static File getCacheDir(Context context, String uniqueName) {
+    // Check if media is mounted or storage is built-in, if so, try and use external cache dir
+    // otherwise use internal cache dir
+    final String cachePath = Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED
+            || !Environment.isExternalStorageRemovable() ?
+                    context.getExternalCacheDir().getPath() : context.getCacheDir().getPath();
+
+    return new File(cachePath + File.separator + uniqueName);
+}
+</pre>
+
+<p>While the memory cache is checked in the UI thread, the disk cache is checked in the background
+thread. Disk operations should never take place on the UI thread. When image processing is
+complete, the final bitmap is added to both the memory and disk cache for future use.</p>
+
+<h2 id="config-changes">Handle Configuration Changes</h2>
+
+<p>Runtime configuration changes, such as a screen orientation change, cause Android to destroy and
+restart the running activity with the new configuration (For more information about this behavior,
+see <a href="{@docRoot}guide/topics/resources/runtime-changes.html">Handling Runtime Changes</a>).
+You want to avoid having to process all your images again so the user has a smooth and fast
+experience when a configuration change occurs.</p>
+
+<p>Luckily, you have a nice memory cache of bitmaps that you built in the <a
+href="#memory-cache">Use a Memory Cache</a> section. This cache can be passed through to the new
+activity instance using a {@link android.app.Fragment} which is preserved by calling {@link
+android.app.Fragment#setRetainInstance setRetainInstance(true)}). After the activity has been
+recreated, this retained {@link android.app.Fragment} is reattached and you gain access to the
+existing cache object, allowing images to be quickly fetched and re-populated into the {@link
+android.widget.ImageView} objects.</p>
+
+<p>Here’s an example of retaining a {@link android.util.LruCache} object across configuration
+changes using a {@link android.app.Fragment}:</p>
+
+<pre>
+private LruCache<String, Bitmap> mMemoryCache;
+
+&#64;Override
+protected void onCreate(Bundle savedInstanceState) {
+    ...
+    RetainFragment mRetainFragment =
+            RetainFragment.findOrCreateRetainFragment(getFragmentManager());
+    mMemoryCache = RetainFragment.mRetainedCache;
+    if (mMemoryCache == null) {
+        mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
+            ... // Initialize cache here as usual
+        }
+        mRetainFragment.mRetainedCache = mMemoryCache;
+    }
+    ...
+}
+
+class RetainFragment extends Fragment {
+    private static final String TAG = "RetainFragment";
+    public LruCache<String, Bitmap> mRetainedCache;
+
+    public RetainFragment() {}
+
+    public static RetainFragment findOrCreateRetainFragment(FragmentManager fm) {
+        RetainFragment fragment = (RetainFragment) fm.findFragmentByTag(TAG);
+        if (fragment == null) {
+            fragment = new RetainFragment();
+        }
+        return fragment;
+    }
+
+    &#64;Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        <strong>setRetainInstance(true);</strong>
+    }
+}
+</pre>
+
+<p>To test this out, try rotating a device both with and without retaining the {@link
+android.app.Fragment}. You should notice little to no lag as the images populate the activity almost
+instantly from memory when you retain the cache. Any images not found in the memory cache are
+hopefully available in the disk cache, if not, they are processed as usual.</p>
diff --git a/docs/html/training/displaying-bitmaps/display-bitmap.jd b/docs/html/training/displaying-bitmaps/display-bitmap.jd
new file mode 100644
index 0000000..7a93313
--- /dev/null
+++ b/docs/html/training/displaying-bitmaps/display-bitmap.jd
@@ -0,0 +1,400 @@
+page.title=Displaying Bitmaps in Your UI
+parent.title=Displaying Bitmaps Efficiently
+parent.link=index.html
+
+trainingnavtop=true
+previous.title=Caching Bitmaps
+previous.link=cache-bitmap.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#viewpager">Load Bitmaps into a ViewPager Implementation</a></li>
+  <li><a href="#gridview">Load Bitmaps into a GridView Implementation</a></li>
+</ol>
+
+<h2>You should also read</h2>
+<ul>
+  <li><a href="{@docRoot}design/patterns/swipe-views.html">Android Design: Swipe Views</a></li>
+  <li><a href="{@docRoot}design/building-blocks/grid-lists.html">Android Design: Grid Lists</a></li>
+</ul>
+
+<h2>Try it out</h2>
+
+<div class="download-box">
+  <a href="{@docRoot}shareables/training/BitmapFun.zip" class="button">Download the sample</a>
+  <p class="filename">BitmapFun.zip</p>
+</div>
+
+</div>
+</div>
+
+<p></p>
+
+<p>This lesson brings together everything from previous lessons, showing you how to load multiple
+bitmaps into {@link android.support.v4.view.ViewPager} and {@link android.widget.GridView}
+components using a background thread and bitmap cache, while dealing with concurrency and
+configuration changes.</p>
+
+<h2 id="viewpager">Load Bitmaps into a ViewPager Implementation</h2>
+
+<p>The <a href="{@docRoot}design/patterns/swipe-views.html">swipe view pattern</a> is an excellent
+way to navigate the detail view of an image gallery. You can implement this pattern using a {@link
+android.support.v4.view.ViewPager} component backed by a {@link
+android.support.v4.view.PagerAdapter}. However, a more suitable backing adapter is the subclass
+{@link android.support.v4.app.FragmentStatePagerAdapter} which automatically destroys and saves
+state of the {@link android.app.Fragment Fragments} in the {@link android.support.v4.view.ViewPager}
+as they disappear off-screen, keeping memory usage down.</p>
+
+<p class="note"><strong>Note:</strong> If you have a smaller number of images and are confident they
+all fit within the application memory limit, then using a regular {@link
+android.support.v4.view.PagerAdapter} or {@link android.support.v4.app.FragmentPagerAdapter} might
+be more appropriate.</p>
+
+<p>Here’s an implementation of a {@link android.support.v4.view.ViewPager} with {@link
+android.widget.ImageView} children. The main activity holds the {@link
+android.support.v4.view.ViewPager} and the adapter:</p>
+
+<pre>
+public class ImageDetailActivity extends FragmentActivity {
+    public static final String EXTRA_IMAGE = "extra_image";
+
+    private ImagePagerAdapter mAdapter;
+    private ViewPager mPager;
+
+    // A static dataset to back the ViewPager adapter
+    public final static Integer[] imageResIds = new Integer[] {
+            R.drawable.sample_image_1, R.drawable.sample_image_2, R.drawable.sample_image_3,
+            R.drawable.sample_image_4, R.drawable.sample_image_5, R.drawable.sample_image_6,
+            R.drawable.sample_image_7, R.drawable.sample_image_8, R.drawable.sample_image_9};
+
+    &#64;Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.image_detail_pager); // Contains just a ViewPager
+
+        mAdapter = new ImagePagerAdapter(getSupportFragmentManager(), imageResIds.length);
+        mPager = (ViewPager) findViewById(R.id.pager);
+        mPager.setAdapter(mAdapter);
+    }
+
+    public static class ImagePagerAdapter extends FragmentStatePagerAdapter {
+        private final int mSize;
+
+        public ImagePagerAdapter(FragmentManager fm, int size) {
+            super(fm);
+            mSize = size;
+        }
+
+        &#64;Override
+        public int getCount() {
+            return mSize;
+        }
+
+        &#64;Override
+        public Fragment getItem(int position) {
+            return ImageDetailFragment.newInstance(position);
+        }
+    }
+}
+</pre>
+
+<p>The details {@link android.app.Fragment} holds the {@link android.widget.ImageView} children:</p>
+
+<pre>
+public class ImageDetailFragment extends Fragment {
+    private static final String IMAGE_DATA_EXTRA = "resId";
+    private int mImageNum;
+    private ImageView mImageView;
+
+    static ImageDetailFragment newInstance(int imageNum) {
+        final ImageDetailFragment f = new ImageDetailFragment();
+        final Bundle args = new Bundle();
+        args.putInt(IMAGE_DATA_EXTRA, imageNum);
+        f.setArguments(args);
+        return f;
+    }
+
+    // Empty constructor, required as per Fragment docs
+    public ImageDetailFragment() {}
+
+    &#64;Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mImageNum = getArguments() != null ? getArguments().getInt(IMAGE_DATA_EXTRA) : -1;
+    }
+
+    &#64;Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        // image_detail_fragment.xml contains just an ImageView
+        final View v = inflater.inflate(R.layout.image_detail_fragment, container, false);
+        mImageView = (ImageView) v.findViewById(R.id.imageView);
+        return v;
+    }
+
+    &#64;Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        final int resId = ImageDetailActivity.imageResIds[mImageNum];
+        <strong>mImageView.setImageResource(resId);</strong> // Load image into ImageView
+    }
+}
+</pre>
+
+<p>Hopefully you noticed the issue with this implementation; The images are being read from
+resources on the UI thread which can lead to an application hanging and being force closed. Using an
+{@link android.os.AsyncTask} as described in the <a href="process-bitmap.html">Processing Bitmaps Off
+the UI Thread</a> lesson, it’s straightforward to move image loading and processing to a background
+thread:</p>
+
+<pre>
+public class ImageDetailActivity extends FragmentActivity {
+    ...
+
+    public void loadBitmap(int resId, ImageView imageView) {
+        mImageView.setImageResource(R.drawable.image_placeholder);
+        BitmapWorkerTask task = new BitmapWorkerTask(mImageView);
+        task.execute(resId);
+    }
+
+    ... // include <a href="process-bitmap.html#BitmapWorkerTask">{@code BitmapWorkerTask}</a> class
+}
+
+public class ImageDetailFragment extends Fragment {
+    ...
+
+    &#64;Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        if (ImageDetailActivity.class.isInstance(getActivity())) {
+            final int resId = ImageDetailActivity.imageResIds[mImageNum];
+            // Call out to ImageDetailActivity to load the bitmap in a background thread
+            ((ImageDetailActivity) getActivity()).loadBitmap(resId, mImageView);
+        }
+    }
+}
+</pre>
+
+<p>Any additional processing (such as resizing or fetching images from the network) can take place
+in the <a href="process-bitmap.html#BitmapWorkerTask">{@code BitmapWorkerTask}</a> without affecting
+responsiveness of the main UI. If the background thread is doing more than just loading an image
+directly from disk, it can also be beneficial to add a memory and/or disk cache as described in the
+lesson <a href="cache-bitmap.html#memory-cache">Caching Bitmaps</a>. Here's the additional
+modifications for a memory cache:</p>
+
+<pre>
+public class ImageDetailActivity extends FragmentActivity {
+    ...
+    private LruCache<String, Bitmap> mMemoryCache;
+
+    &#64;Override
+    public void onCreate(Bundle savedInstanceState) {
+        ...
+        // initialize LruCache as per <a href="cache-bitmap.html#memory-cache">Use a Memory Cache</a> section
+    }
+
+    public void loadBitmap(int resId, ImageView imageView) {
+        final String imageKey = String.valueOf(resId);
+
+        final Bitmap bitmap = mMemoryCache.get(imageKey);
+        if (bitmap != null) {
+            mImageView.setImageBitmap(bitmap);
+        } else {
+            mImageView.setImageResource(R.drawable.image_placeholder);
+            BitmapWorkerTask task = new BitmapWorkerTask(mImageView);
+            task.execute(resId);
+        }
+    }
+
+    ... // include updated BitmapWorkerTask from <a href="cache-bitmap.html#memory-cache">Use a Memory Cache</a> section
+}
+</pre>
+
+<p>Putting all these pieces together gives you a responsive {@link
+android.support.v4.view.ViewPager} implementation with minimal image loading latency and the ability
+to do as much or as little background processing on your images as needed.</p>
+
+<h2 id="gridview">Load Bitmaps into a GridView Implementation</h2>
+
+<p>The <a href="{@docRoot}design/building-blocks/grid-lists.html">grid list building block</a> is
+useful for showing image data sets and can be implemented using a {@link android.widget.GridView}
+component in which many images can be on-screen at any one time and many more need to be ready to
+appear if the user scrolls up or down. When implementing this type of control, you must ensure the
+UI remains fluid, memory usage remains under control and concurrency is handled correctly (due to
+the way {@link android.widget.GridView} recycles its children views).</p>
+
+<p>To start with, here is a standard {@link android.widget.GridView} implementation with {@link
+android.widget.ImageView} children placed inside a {@link android.app.Fragment}:</p>
+
+<pre>
+public class ImageGridFragment extends Fragment implements AdapterView.OnItemClickListener {
+    private ImageAdapter mAdapter;
+
+    // A static dataset to back the GridView adapter
+    public final static Integer[] imageResIds = new Integer[] {
+            R.drawable.sample_image_1, R.drawable.sample_image_2, R.drawable.sample_image_3,
+            R.drawable.sample_image_4, R.drawable.sample_image_5, R.drawable.sample_image_6,
+            R.drawable.sample_image_7, R.drawable.sample_image_8, R.drawable.sample_image_9};
+
+    // Empty constructor as per Fragment docs
+    public ImageGridFragment() {}
+
+    &#64;Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mAdapter = new ImageAdapter(getActivity());
+    }
+
+    &#64;Override
+    public View onCreateView(
+            LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        final View v = inflater.inflate(R.layout.image_grid_fragment, container, false);
+        final GridView mGridView = (GridView) v.findViewById(R.id.gridView);
+        mGridView.setAdapter(mAdapter);
+        mGridView.setOnItemClickListener(this);
+        return v;
+    }
+
+    &#64;Override
+    public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
+        final Intent i = new Intent(getActivity(), ImageDetailActivity.class);
+        i.putExtra(ImageDetailActivity.EXTRA_IMAGE, position);
+        startActivity(i);
+    }
+
+    private class ImageAdapter extends BaseAdapter {
+        private final Context mContext;
+
+        public ImageAdapter(Context context) {
+            super();
+            mContext = context;
+        }
+
+        &#64;Override
+        public int getCount() {
+            return imageResIds.length;
+        }
+
+        &#64;Override
+        public Object getItem(int position) {
+            return imageResIds[position];
+        }
+
+        &#64;Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        &#64;Override
+        public View getView(int position, View convertView, ViewGroup container) {
+            ImageView imageView;
+            if (convertView == null) { // if it's not recycled, initialize some attributes
+                imageView = new ImageView(mContext);
+                imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
+                imageView.setLayoutParams(new GridView.LayoutParams(
+                        LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+            } else {
+                imageView = (ImageView) convertView;
+            }
+            <strong>imageView.setImageResource(imageResIds[position]);</strong> // Load image into ImageView
+            return imageView;
+        }
+    }
+}
+</pre>
+
+<p>Once again, the problem with this implementation is that the image is being set in the UI thread.
+While this may work for small, simple images (due to system resource loading and caching), if any
+additional processing needs to be done, your UI grinds to a halt.</p>
+
+<p>The same asynchronous processing and caching methods from the previous section can be implemented
+here. However, you also need to wary of concurrency issues as the {@link android.widget.GridView}
+recycles its children views. To handle this, use the techniques discussed in the <a
+href="process-bitmap#concurrency">Processing Bitmaps Off the UI Thread</a> lesson. Here is the updated
+solution:</p>
+
+<pre>
+public class ImageGridFragment extends Fragment implements AdapterView.OnItemClickListener {
+    ...
+
+    private class ImageAdapter extends BaseAdapter {
+        ...
+
+        &#64;Override
+        public View getView(int position, View convertView, ViewGroup container) {
+            ...
+            <strong>loadBitmap(imageResIds[position], imageView)</strong>
+            return imageView;
+        }
+    }
+
+    public void loadBitmap(int resId, ImageView imageView) {
+        if (cancelPotentialWork(resId, imageView)) {
+            final BitmapWorkerTask task = new BitmapWorkerTask(imageView);
+            final AsyncDrawable asyncDrawable =
+                    new AsyncDrawable(getResources(), mPlaceHolderBitmap, task);
+            imageView.setImageDrawable(asyncDrawable);
+            task.execute(resId);
+        }
+    }
+
+    static class AsyncDrawable extends BitmapDrawable {
+        private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;
+
+        public AsyncDrawable(Resources res, Bitmap bitmap,
+                BitmapWorkerTask bitmapWorkerTask) {
+            super(res, bitmap);
+            bitmapWorkerTaskReference =
+                new WeakReference<BitmapWorkerTask>(bitmapWorkerTask);
+        }
+
+        public BitmapWorkerTask getBitmapWorkerTask() {
+            return bitmapWorkerTaskReference.get();
+        }
+    }
+
+    public static boolean cancelPotentialWork(int data, ImageView imageView) {
+        final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
+
+        if (bitmapWorkerTask != null) {
+            final int bitmapData = bitmapWorkerTask.data;
+            if (bitmapData != data) {
+                // Cancel previous task
+                bitmapWorkerTask.cancel(true);
+            } else {
+                // The same work is already in progress
+                return false;
+            }
+        }
+        // No task associated with the ImageView, or an existing task was cancelled
+        return true;
+    }
+
+    private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
+       if (imageView != null) {
+           final Drawable drawable = imageView.getDrawable();
+           if (drawable instanceof AsyncDrawable) {
+               final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
+               return asyncDrawable.getBitmapWorkerTask();
+           }
+        }
+        return null;
+    }
+
+    ... // include updated <a href="process-bitmap.html#BitmapWorkerTaskUpdated">{@code BitmapWorkerTask}</a> class
+</pre>
+
+<p class="note"><strong>Note:</strong> The same code can easily be adapted to work with {@link
+android.widget.ListView} as well.</p>
+
+<p>This implementation allows for flexibility in how the images are processed and loaded without
+impeding the smoothness of the UI. In the background task you can load images from the network or
+resize large digital camera photos and the images appear as the tasks finish processing.</p>
+
+<p>For a full example of this and other concepts discussed in this lesson, please see the included
+sample application.</p>
diff --git a/docs/html/training/displaying-bitmaps/index.jd b/docs/html/training/displaying-bitmaps/index.jd
new file mode 100644
index 0000000..6755c24
--- /dev/null
+++ b/docs/html/training/displaying-bitmaps/index.jd
@@ -0,0 +1,78 @@
+page.title=Displaying Bitmaps Efficiently
+
+trainingnavtop=true
+startpage=true
+next.title=Loading Large Bitmaps Efficiently
+next.link=load-bitmap.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>Dependencies and prerequisites</h2>
+<ul>
+  <li>Android 2.1 (API Level 7) or higher</li>
+  <li><a href="{@docRoot}sdk/compatibility-library.html">Support Library</a></li>
+</ul>
+
+<h2>Try it out</h2>
+
+<div class="download-box">
+  <a href="{@docRoot}shareables/training/BitmapFun.zip" class="button">Download the sample</a>
+  <p class="filename">BitmapFun.zip</p>
+</div>
+
+</div>
+</div>
+
+<p>This class covers some common techniques for processing and loading {@link
+android.graphics.Bitmap} objects in a way that keeps your user interface (UI) components responsive
+and avoids exceeding your application memory limit. If you're not careful, bitmaps can quickly
+consume your available memory budget leading to an application crash due to the dreaded
+exception:<br />{@code java.lang.OutofMemoryError: bitmap size exceeds VM budget}.</p>
+
+<p>There are a number of reasons why loading bitmaps in your Android application is tricky:</p>
+
+<ul>
+  <li>Mobile devices typically have constrained system resources. Android devices can have as little
+  as 16MB of memory available to a single application. The <a
+  href="http://source.android.com/compatibility/downloads.html">Android Compatibility Definition
+  Document</a> (CDD), <i>Section 3.7. Virtual Machine Compatibility</i> gives the required minimum
+  application memory for various screen sizes and densities. Applications should be optimized to
+  perform under this minimum memory limit. However, keep in mind many devices are configured with
+  higher limits.</li>
+  <li>Bitmaps take up a lot of memory, especially for rich images like photographs. For example, the
+  camera on the <a href="http://www.google.com/nexus/">Galaxy Nexus</a> takes photos up to 2592x1936
+  pixels (5 megapixels). If the bitmap configuration used is {@link
+  android.graphics.Bitmap.Config ARGB_8888} (the default from the Android 2.3 onward) then loading
+  this image into memory takes about 19MB of memory (2592*1936*4 bytes), immediately exhausting the
+  per-app limit on some devices.</li>
+  <li>Android app UI’s frequently require several bitmaps to be loaded at once. Components such as
+  {@link android.widget.ListView}, {@link android.widget.GridView} and {@link
+  android.support.v4.view.ViewPager} commonly include multiple bitmaps on-screen at once with many
+  more potentially off-screen ready to show at the flick of a finger.</li>
+</ul>
+
+<h2>Lessons</h2>
+
+<dl>
+  <dt><b><a href="load-bitmap.html">Loading Large Bitmaps Efficiently</a></b></dt>
+    <dd>This lesson walks you through decoding large bitmaps without exceeding the per application
+    memory limit.</dd>
+
+  <dt><b><a href="process-bitmap.html">Processing Bitmaps Off the UI Thread</a></b></dt>
+    <dd>Bitmap processing (resizing, downloading from a remote source, etc.) should never take place
+    on the main UI thread. This lesson walks you through processing bitmaps in a background thread
+    using {@link android.os.AsyncTask} and explains how to handle concurrency issues.</dd>
+
+  <dt><b><a href="cache-bitmap.html">Caching Bitmaps</a></b></dt>
+    <dd>This lesson walks you through using a memory and disk bitmap cache to improve the
+    responsiveness and fluidity of your UI when loading multiple bitmaps.</dd>
+
+  <dt><b><a href="display-bitmap.html">Displaying Bitmaps in Your UI</a></b></dt>
+    <dd>This lesson brings everything together, showing you how to load multiple bitmaps into
+    components like {@link android.support.v4.view.ViewPager} and {@link android.widget.GridView}
+    using a background thread and bitmap cache.</dd>
+
+</dl>
\ No newline at end of file
diff --git a/docs/html/training/displaying-bitmaps/load-bitmap.jd b/docs/html/training/displaying-bitmaps/load-bitmap.jd
new file mode 100644
index 0000000..c0a5709
--- /dev/null
+++ b/docs/html/training/displaying-bitmaps/load-bitmap.jd
@@ -0,0 +1,165 @@
+page.title=Loading Large Bitmaps Efficiently
+parent.title=Displaying Bitmaps Efficiently
+parent.link=index.html
+
+trainingnavtop=true
+next.title=Processing Bitmaps Off the UI Thread
+next.link=process-bitmap.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#read-bitmap">Read Bitmap Dimensions and Type</a></li>
+  <li><a href="#load-bitmap">Load a Scaled Down Version into Memory</a></li>
+</ol>
+
+<h2>Try it out</h2>
+
+<div class="download-box">
+  <a href="{@docRoot}shareables/training/BitmapFun.zip" class="button">Download the sample</a>
+  <p class="filename">BitmapFun.zip</p>
+</div>
+
+</div>
+</div>
+
+<p>Images come in all shapes and sizes. In many cases they are larger than required for a typical
+application user interface (UI). For example, the system Gallery application displays photos taken
+using your Android devices's camera which are typically much higher resolution than the screen
+density of your device.</p>
+
+<p>Given that you are working with limited memory, ideally you only want to load a lower resolution
+version in memory. The lower resolution version should match the size of the UI component that
+displays it. An image with a higher resolution does not provide any visible benefit, but still takes
+up precious memory and incurs additional performance overhead due to additional on the fly
+scaling.</p>
+
+<p>This lesson walks you through decoding large bitmaps without exceeding the per application
+memory limit by loading a smaller subsampled version in memory.</p>
+
+<h2 id="read-bitmap">Read Bitmap Dimensions and Type</h2>
+
+<p>The {@link android.graphics.BitmapFactory} class provides several decoding methods ({@link
+android.graphics.BitmapFactory#decodeByteArray(byte[],int,int,android.graphics.BitmapFactory.Options)
+decodeByteArray()}, {@link
+android.graphics.BitmapFactory#decodeFile(java.lang.String,android.graphics.BitmapFactory.Options)
+decodeFile()}, {@link
+android.graphics.BitmapFactory#decodeResource(android.content.res.Resources,int,android.graphics.BitmapFactory.Options)
+decodeResource()}, etc.) for creating a {@link android.graphics.Bitmap} from various sources. Choose
+the most appropriate decode method based on your image data source. These methods attempt to
+allocate memory for the constructed bitmap and therefore can easily result in an {@code OutOfMemory}
+exception. Each type of decode method has additional signatures that let you specify decoding
+options via the {@link android.graphics.BitmapFactory.Options} class. Setting the {@link
+android.graphics.BitmapFactory.Options#inJustDecodeBounds} property to {@code true} while decoding
+avoids memory allocation, returning {@code null} for the bitmap object but setting {@link
+android.graphics.BitmapFactory.Options#outWidth}, {@link
+android.graphics.BitmapFactory.Options#outHeight} and {@link
+android.graphics.BitmapFactory.Options#outMimeType}. This technique allows you to read the
+dimensions and type of the image data prior to construction (and memory allocation) of the
+bitmap.</p>
+
+<pre>
+BitmapFactory.Options options = new BitmapFactory.Options();
+options.inJustDecodeBounds = true;
+BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
+int imageHeight = options.outHeight;
+int imageWidth = options.outWidth;
+String imageType = options.outMimeType;
+</pre>
+
+<p>To avoid {@code java.lang.OutOfMemory} exceptions, check the dimensions of a bitmap before
+decoding it, unless you absolutely trust the source to provide you with predictably sized image data
+that comfortably fits within the available memory.</p>
+
+<h2 id="load-bitmap">Load a Scaled Down Version into Memory</h2>
+
+<p>Now that the image dimensions are known, they can be used to decide if the full image should be
+loaded into memory or if a subsampled version should be loaded instead. Here are some factors to
+consider:</p>
+
+<ul>
+  <li>Estimated memory usage of loading the full image in memory.</li>
+  <li>Amount of memory you are willing to commit to loading this image given any other memory
+  requirements of your application.</li>
+  <li>Dimensions of the target {@link android.widget.ImageView} or UI component that the image
+  is to be loaded into.</li>
+  <li>Screen size and density of the current device.</li>
+</ul>
+
+<p>For example, it’s not worth loading a 1024x768 pixel image into memory if it will eventually be
+displayed in a 128x96 pixel thumbnail in an {@link android.widget.ImageView}.</p>
+
+<p>To tell the decoder to subsample the image, loading a smaller version into memory, set {@link
+android.graphics.BitmapFactory.Options#inSampleSize} to {@code true} in your {@link
+android.graphics.BitmapFactory.Options} object. For example, an image with resolution 2048x1536 that
+is decoded with an {@link android.graphics.BitmapFactory.Options#inSampleSize} of 4 produces a
+bitmap of approximately 512x384. Loading this into memory uses 0.75MB rather than 12MB for the full
+image (assuming a bitmap configuration of {@link android.graphics.Bitmap.Config ARGB_8888}). Here’s
+a method to calculate a the sample size value based on a target width and height:</p>
+
+<pre>
+public static int calculateInSampleSize(
+            BitmapFactory.Options options, int reqWidth, int reqHeight) {
+    // Raw height and width of image
+    final int height = options.outHeight;
+    final int width = options.outWidth;
+    int inSampleSize = 1;
+
+    if (height > reqHeight || width > reqWidth) {
+        if (width > height) {
+            inSampleSize = Math.round((float)height / (float)reqHeight);
+        } else {
+            inSampleSize = Math.round((float)width / (float)reqWidth);
+        }
+    }
+    return inSampleSize;
+}
+</pre>
+
+<p class="note"><strong>Note:</strong> Using powers of 2 for {@link
+android.graphics.BitmapFactory.Options#inSampleSize} values is faster and more efficient for the
+decoder. However, if you plan to cache the resized versions in memory or on disk, it’s usually still
+worth decoding to the most appropriate image dimensions to save space.</p>
+
+<p>To use this method, first decode with {@link
+android.graphics.BitmapFactory.Options#inJustDecodeBounds} set to {@code true}, pass the options
+through and then decode again using the new {@link
+android.graphics.BitmapFactory.Options#inSampleSize} value and {@link
+android.graphics.BitmapFactory.Options#inJustDecodeBounds} set to {@code false}:</p>
+
+<a name="decodeSampledBitmapFromResource"></a>
+<pre>
+public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
+        int reqWidth, int reqHeight) {
+
+    // First decode with inJustDecodeBounds=true to check dimensions
+    final BitmapFactory.Options options = new BitmapFactory.Options();
+    options.inJustDecodeBounds = true;
+    BitmapFactory.decodeResource(res, resId, options);
+
+    // Calculate inSampleSize
+    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
+
+    // Decode bitmap with inSampleSize set
+    options.inJustDecodeBounds = false;
+    return BitmapFactory.decodeResource(res, resId, options);
+}
+</pre>
+
+<p>This method makes it easy to load a bitmap of arbitrarily large size into an {@link
+android.widget.ImageView} that displays a 100x100 pixel thumbnail, as shown in the following example
+code:</p>
+
+<pre>
+mImageView.setImageBitmap(
+    decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));
+</pre>
+
+<p>You can follow a similar process to decode bitmaps from other sources, by substituting the
+appropriate {@link
+android.graphics.BitmapFactory#decodeByteArray(byte[],int,int,android.graphics.BitmapFactory.Options)
+BitmapFactory.decode*} method as needed.</p>
\ No newline at end of file
diff --git a/docs/html/training/displaying-bitmaps/process-bitmap.jd b/docs/html/training/displaying-bitmaps/process-bitmap.jd
new file mode 100644
index 0000000..c1450b4
--- /dev/null
+++ b/docs/html/training/displaying-bitmaps/process-bitmap.jd
@@ -0,0 +1,239 @@
+page.title=Processing Bitmaps Off the UI Thread
+parent.title=Displaying Bitmaps Efficiently
+parent.link=index.html
+
+trainingnavtop=true
+next.title=Caching Bitmaps
+next.link=cache-bitmap.html
+previous.title=Loading Large Bitmaps Efficiently
+previous.link=load-bitmap.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#async-task">Use an AsyncTask</a></li>
+  <li><a href="#concurrency">Handle Concurrency</a></li>
+</ol>
+
+<h2>You should also read</h2>
+<ul>
+  <li><a href="{@docRoot}guide/practices/design/responsiveness.html">Designing for Responsiveness</a></li>
+  <li><a
+  href="http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html">Multithreading
+  for Performance</a></li>
+</ul>
+
+<h2>Try it out</h2>
+
+<div class="download-box">
+  <a href="{@docRoot}shareables/training/BitmapFun.zip" class="button">Download the sample</a>
+  <p class="filename">BitmapFun.zip</p>
+</div>
+
+</div>
+</div>
+
+<p>The {@link
+android.graphics.BitmapFactory#decodeByteArray(byte[],int,int,android.graphics.BitmapFactory.Options)
+BitmapFactory.decode*} methods, discussed in the <a href="load-bitmap.html">Load Large Bitmaps
+Efficiently</a> lesson, should not be executed on the main UI thread if the source data is read from
+disk or a network location (or really any source other than memory). The time this data takes to
+load is unpredictable and depends on a variety of factors (speed of reading from disk or network,
+size of image, power of CPU, etc.). If one of these tasks blocks the UI thread, the system flags
+your application as non-responsive and the user has the option of closing it (see <a
+href="{@docRoot}guide/practices/design/responsiveness.html">Designing for Responsiveness</a> for
+more information).</p>
+
+<p>This lesson walks you through processing bitmaps in a background thread using
+{@link android.os.AsyncTask} and shows you how to handle concurrency issues.</p>
+
+<h2 id="async-task">Use an AsyncTask</h2>
+
+<p>The {@link android.os.AsyncTask} class provides an easy way to execute some work in a background
+thread and publish the results back on the UI thread. To use it, create a subclass and override the
+provided methods. Here’s an example of loading a large image into an {@link
+android.widget.ImageView} using {@link android.os.AsyncTask} and <a
+href="load-bitmap.html#decodeSampledBitmapFromResource">{@code
+decodeSampledBitmapFromResource()}</a>: </p>
+
+<a name="BitmapWorkerTask"></a>
+<pre>
+class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
+    private final WeakReference<ImageView> imageViewReference;
+    private int data = 0;
+
+    public BitmapWorkerTask(ImageView imageView) {
+        // Use a WeakReference to ensure the ImageView can be garbage collected
+        imageViewReference = new WeakReference<ImageView>(imageView);
+    }
+
+    // Decode image in background.
+    &#64;Override
+    protected Bitmap doInBackground(Integer... params) {
+        data = params[0];
+        return decodeSampledBitmapFromResource(getResources(), data, 100, 100));
+    }
+
+    // Once complete, see if ImageView is still around and set bitmap.
+    &#64;Override
+    protected void onPostExecute(Bitmap bitmap) {
+        if (imageViewReference != null && bitmap != null) {
+            final ImageView imageView = imageViewReference.get();
+            if (imageView != null) {
+                imageView.setImageBitmap(bitmap);
+            }
+        }
+    }
+}
+</pre>
+
+<p>The {@link java.lang.ref.WeakReference} to the {@link android.widget.ImageView} ensures that the
+{@link android.os.AsyncTask} does not prevent the {@link android.widget.ImageView} and anything it
+references from being garbage collected. There’s no guarantee the {@link android.widget.ImageView}
+is still around when the task finishes, so you must also check the reference in {@link
+android.os.AsyncTask#onPostExecute(Result) onPostExecute()}. The {@link android.widget.ImageView}
+may no longer exist, if for example, the user navigates away from the activity or if a
+configuration change happens before the task finishes.</p>
+
+<p>To start loading the bitmap asynchronously, simply create a new task and execute it:</p>
+
+<pre>
+public void loadBitmap(int resId, ImageView imageView) {
+    BitmapWorkerTask task = new BitmapWorkerTask(imageView);
+    task.execute(resId);
+}
+</pre>
+
+<h2 id="concurrency">Handle Concurrency</h2>
+
+<p>Common view components such as {@link android.widget.ListView} and {@link
+android.widget.GridView} introduce another issue when used in conjunction with the {@link
+android.os.AsyncTask} as demonstrated in the previous section. In order to be efficient with memory,
+these components recycle child views as the user scrolls. If each child view triggers an {@link
+android.os.AsyncTask}, there is no guarantee that when it completes, the associated view has not
+already been recycled for use in another child view. Furthermore, there is no guarantee that the
+order in which asynchronous tasks are started is the order that they complete.</p>
+
+<p>The blog post <a
+href="http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html">Multithreading
+for Performance</a> further discusses dealing with concurrency, and offers a solution where the
+{@link android.widget.ImageView} stores a reference to the most recent {@link android.os.AsyncTask}
+which can later be checked when the task completes. Using a similar method, the {@link
+android.os.AsyncTask} from the previous section can be extended to follow a similar pattern.</p>
+
+<p>Create a dedicated {@link android.graphics.drawable.Drawable} subclass to store a reference
+back to the worker task. In this case, a {@link android.graphics.drawable.BitmapDrawable} is used so
+that a placeholder image can be displayed in the {@link android.widget.ImageView} while the task
+completes:</p>
+
+<a name="AsyncDrawable"></a>
+<pre>
+static class AsyncDrawable extends BitmapDrawable {
+    private final WeakReference<BitmapWorkerTask> bitmapWorkerTaskReference;
+
+    public AsyncDrawable(Resources res, Bitmap bitmap,
+            BitmapWorkerTask bitmapWorkerTask) {
+        super(res, bitmap);
+        bitmapWorkerTaskReference =
+            new WeakReference<BitmapWorkerTask>(bitmapWorkerTask);
+    }
+
+    public BitmapWorkerTask getBitmapWorkerTask() {
+        return bitmapWorkerTaskReference.get();
+    }
+}
+</pre>
+
+<p>Before executing the <a href="#BitmapWorkerTask">{@code BitmapWorkerTask}</a>, you create an <a
+href="#AsyncDrawable">{@code AsyncDrawable}</a> and bind it to the target {@link
+android.widget.ImageView}:</p>
+
+<pre>
+public void loadBitmap(int resId, ImageView imageView) {
+    if (cancelPotentialWork(resId, imageView)) {
+        final BitmapWorkerTask task = new BitmapWorkerTask(imageView);
+        final AsyncDrawable asyncDrawable =
+                new AsyncDrawable(getResources(), mPlaceHolderBitmap, task);
+        imageView.setImageDrawable(asyncDrawable);
+        task.execute(resId);
+    }
+}
+</pre>
+
+<p>The {@code cancelPotentialWork} method referenced in the code sample above checks if another
+running task is already associated with the {@link android.widget.ImageView}. If so, it attempts to
+cancel the previous task by calling {@link android.os.AsyncTask#cancel cancel()}. In a small number
+of cases, the new task data matches the existing task and nothing further needs to happen. Here is
+the implementation of {@code cancelPotentialWork}:</p>
+
+<pre>
+public static boolean cancelPotentialWork(int data, ImageView imageView) {
+    final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
+
+    if (bitmapWorkerTask != null) {
+        final int bitmapData = bitmapWorkerTask.data;
+        if (bitmapData != data) {
+            // Cancel previous task
+            bitmapWorkerTask.cancel(true);
+        } else {
+            // The same work is already in progress
+            return false;
+        }
+    }
+    // No task associated with the ImageView, or an existing task was cancelled
+    return true;
+}
+</pre>
+
+<p>A helper method, {@code getBitmapWorkerTask()}, is used above to retrieve the task associated
+with a particular {@link android.widget.ImageView}:</p>
+
+<pre>
+private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
+   if (imageView != null) {
+       final Drawable drawable = imageView.getDrawable();
+       if (drawable instanceof AsyncDrawable) {
+           final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
+           return asyncDrawable.getBitmapWorkerTask();
+       }
+    }
+    return null;
+}
+</pre>
+
+<p>The last step is updating {@code onPostExecute()} in <a href="#BitmapWorkerTask">{@code
+BitmapWorkerTask}</a> so that it checks if the task is cancelled and if the current task matches the
+one associated with the {@link android.widget.ImageView}:</p>
+
+<a name="BitmapWorkerTaskUpdated"></a>
+<pre>
+class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
+    ...
+
+    &#64;Override
+    protected void onPostExecute(Bitmap bitmap) {
+        <strong>if (isCancelled()) {
+            bitmap = null;
+        }</strong>
+
+        if (imageViewReference != null && bitmap != null) {
+            final ImageView imageView = imageViewReference.get();
+            <strong>final BitmapWorkerTask bitmapWorkerTask =
+                    getBitmapWorkerTask(imageView);</strong>
+            if (<strong>this == bitmapWorkerTask &&</strong> imageView != null) {
+                imageView.setImageBitmap(bitmap);
+            }
+        }
+    }
+}
+</pre>
+
+<p>This implementation is now suitable for use in {@link android.widget.ListView} and {@link
+android.widget.GridView} components as well as any other components that recycle their child
+views. Simply call {@code loadBitmap} where you normally set an image to your {@link
+android.widget.ImageView}. For example, in a {@link android.widget.GridView} implementation this
+would be in the {@link android.widget.Adapter#getView getView()} method of the backing adapter.</p>
\ No newline at end of file
diff --git a/docs/html/training/tv/index.jd b/docs/html/training/tv/index.jd
new file mode 100644
index 0000000..ae13c4a
--- /dev/null
+++ b/docs/html/training/tv/index.jd
@@ -0,0 +1,52 @@
+page.title=Designing for TV
+
+trainingnavtop=true
+startpage=true
+next.title=Optimizing layouts for TV
+next.link=optimizing-layouts-tv.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<!-- Required platform, tools, add-ons, devices, knowledge, etc. -->
+<h2>Dependencies and prerequisites</h2>
+<ul>
+  <li>Android 2.0 (API Level 5) or higher</li>
+</ul>
+
+</div>
+</div>
+<p> 
+  Smart TVs powered by Android bring your favorite Android apps to the best screen in your house. 
+  Thousands of apps in the Google Play Store are already optimized for TVs. This class shows how 
+  you can optimize your Android app for TVs, including how to build a layout that 
+  works great when the user is ten feet away and navigating with a remote control. 
+</p> 
+
+<h2>Lessons</h2> 
+ 
+<dl> 
+  <dt><b><a href="optimizing-layouts-tv.html">Optimizing Layouts for TV</a></b></dt>
+    <dd>Shows you how to optimize app layouts for TV screens, which have some unique characteristics such as:
+    <ul>
+      <li>permanent "landscape" mode</li>
+      <li>high-resolution displays</li>
+      <li>"10 foot UI" environment.</li>
+    </ul>
+    </dd>
+ 
+  <dt><b><a href="optimizing-navigation-tv.html">Optimizing Navigation for TV</a></b></dt>
+    <dd>Shows you how to design navigation for TVs, including: 
+    <ul>
+      <li>handling D-pad navigation</li>
+      <li>providing navigational feedback</li>
+      <li>providing easily-accessible controls on the screen.</li>
+    </ul>
+    </dd>
+
+  <dt><b><a href="unsupported-features-tv.html">Handling features not supported on TV</a></b></dt>
+    <dd>Lists the hardware features that are usually not available on TVs. This lesson also shows you how to 
+    provide alternatives for missing features or check for missing features and disable code at run time.</dd>
+</dl> 
\ No newline at end of file
diff --git a/docs/html/training/tv/optimizing-layouts-tv.jd b/docs/html/training/tv/optimizing-layouts-tv.jd
new file mode 100644
index 0000000..6eac6d3
--- /dev/null
+++ b/docs/html/training/tv/optimizing-layouts-tv.jd
@@ -0,0 +1,246 @@
+page.title=Optimizing Layouts for TV
+parent.title=Designing for TV
+parent.link=index.html
+
+trainingnavtop=true
+next.title=Optimizing Navigation for TV
+next.link=optimizing-navigation-tv.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#DesignLandscapeLayouts">Design Landscape Layouts</a></li>
+  <li><a href="#MakeTextControlsEasyToSee">Make Text and Controls Easy to See</a></li>
+  <li><a href="#DesignForLargeScreens">Design for High-Density Large Screens</a></li>
+  <li><a href="#HandleLargeBitmaps">Handle Large Bitmaps in Your Application</a></li>
+</ol>
+
+<h2>You should also read</h2>
+<ul>
+  <li><a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a></li>
+</ul>
+
+</div>
+</div>
+
+<p>
+When your application is running on a television set, you should assume that the user is sitting about 
+ten feet away from the screen. This user environment is referred to as the 
+<a href="http://en.wikipedia.org/wiki/10-foot_user_interface">10-foot UI</a>. To provide your 
+users with a usable and enjoyable experience, you should style and lay out your UI accordingly..
+</p>
+<p>
+This lesson shows you how to optimize layouts for TV by:
+</p>
+<ul>
+  <li>Providing appropriate layout resources for landscape mode.</li>
+  <li>Ensuring that text and controls are large enough to be visible from a distance.</li>
+  <li>Providing high resolution bitmaps and icons for HD TV screens.</li>
+</ul>
+
+<h2 id="DesignLandscapeLayouts">Design Landscape Layouts</h2> 
+
+<p>
+TV screens are always in landscape orientation. Follow these tips to build landscape layouts optimized for TV screens:
+</p> 
+<ul>
+  <li>Put on-screen navigational controls on the left or right side of the screen and save the 
+  vertical space for content.</li>
+  <li>Create UIs that are divided into sections, by using <a href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> 
+  and use view groups like {@link android.widget.GridView} instead 
+  of {@link android.widget.ListView} to make better use of the 
+  horizontal screen space.</li>
+  <li>Use view groups such as {@link android.widget.RelativeLayout} 
+  or {@link android.widget.LinearLayout} to arrange views. 
+  This allows the Android system to adjust the position of the views to the size, alignment, 
+  aspect ratio, and pixel density of the TV screen.</li>
+  <li>Add sufficient margins between layout controls to avoid a cluttered UI.</li>
+</ul> 
+ 
+<p>
+For example, the following layout is optimized for TV:
+</p>
+
+<img src="{@docRoot}images/training/panoramio-grid.png" />
+
+<p>
+In this layout, the controls are on the lefthand side. The UI is displayed within a 
+{@link android.widget.GridView}, which is well-suited to landscape orientation.
+In this layout both GridView and Fragment have the width and height set 
+dynamically, so they can adjust to the screen resolution. Controls are added to the left side Fragment programatically at runtime.
+The layout file for this UI is {@code res/layout-land-large/photogrid_tv.xml}.
+(This layout file is placed in {@code layout-land-large} because TVs have large screens with landscape orientation. For details refer to 
+<a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.)</p>
+
+res/layout-land-large/photogrid_tv.xml
+<pre>
+&lt;RelativeLayout
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent" &gt;
+
+    &lt;fragment
+        android:id="@+id/leftsidecontrols"
+        android:layout_width="0dip"
+        android:layout_marginLeft="5dip"
+        android:layout_height="match_parent" /&gt;
+
+    &lt;GridView        
+        android:id="@+id/gridview"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" /&gt;
+
+&lt;/RelativeLayout>
+</pre>
+
+<p>
+To set up action bar items on the left side of the screen, you can also include the <a
+href="http://code.google.com/p/googletv-android-samples/source/browse/#git%2FLeftNavBarLibrary">
+Left navigation bar library</a> in your application to set up action items on the left side 
+of the screen, instead of creating a custom Fragment to add controls:
+</p>
+
+<pre>
+LeftNavBar bar = (LeftNavBarService.instance()).getLeftNavBar(this);
+</pre>
+
+<p>
+When you have an activity in which the content scrolls vertically, always use a left navigation bar; 
+otherwise, your users have to scroll to the top of the content to switch between the content view and 
+the ActionBar. Look at the  
+<a href="http://code.google.com/p/googletv-android-samples/source/browse/#git%2FLeftNavBarDemo">
+Left navigation bar sample app</a> to see how to simple it is to include the left navigation bar in your app.
+</p>
+
+<h2 id="MakeTextControlsEasyToSee">Make Text and Controls Easy to See</h2>
+<p>
+The text and controls in a TV application's UI should be easily visible and navigable from a distance.
+Follow these tips to make them easier to see from a distance :
+</p>
+
+<ul>
+  <li>Break text into small chunks that users can quickly scan.</li>
+  <li>Use light text on a dark background. This style is easier to read on a TV.</li>
+  <li>Avoid lightweight fonts or fonts that have both very narrow and very broad strokes. Use simple sans-serif 
+  fonts and use anti-aliasing to increase readability.</li>
+  <li>Use Android's standard font sizes:
+  <pre>
+  &lt;TextView
+        android:id="@+id/atext"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:gravity="center_vertical"
+        android:singleLine="true"
+        android:textAppearance="?android:attr/textAppearanceMedium"/&gt;
+  </pre></li>
+  <li>Ensure that all your view widgets are large enough to be clearly visible to someone sitting 10 feet away 
+  from the screen (this distance is greater for very large screens).  The best way to do this is to use 
+  layout-relative sizing rather than absolute sizing, and density-independent pixel units instead of absolute 
+  pixel units. For example, to set the width of a widget, use wrap_content instead of a pixel measurement, 
+  and to set the margin for a widget, use dip instead of px values.
+  </li>
+</ul>
+<p>
+
+</p>
+
+<h2 id="DesignForLargeScreens">Design for High-Density Large Screens</h2>
+
+<p>
+The common HDTV display resolutions are 720p, 1080i, and 1080p. Design your UI for 1080p, and then 
+allow the Android system to downscale your UI to 720p if necessary. In general, downscaling (removing pixels) 
+does not degrade the UI (Notice that the converse is not true; you should avoid upscaling because it degrades 
+UI quality).
+</p>
+
+<p>
+To get the best scaling results for images, provide them as <a href="{@docRoot}guide/developing/tools/draw9patch.html">
+9-patch image</a> elements if possible.
+If you provide low quality or small images in your layouts, they will appear pixelated, fuzzy, or grainy. This 
+is not a good experience for the user. Instead, use high-quality images. 
+</p>
+
+<p>
+For more information on optimizing apps for large screens see <a href="{@docRoot}training/multiscreen/index.html">
+Designing for multiple screens</a>.
+</p>
+
+<h2 id="HandleLargeBitmaps">Design to Handle Large Bitmaps</h2>
+
+<p>
+The Android system has a limited amount of memory, so downloading and storing high-resolution images can often 
+cause out-of-memory errors in your app. To avoid this, follow these tips:
+</p>
+
+<ul>
+  <li>Load images only when they're displayed on the screen. For example, when displaying multiple images in 
+      a {@link android.widget.GridView} or 
+      {@link android.widget.Gallery}, only load an image when 
+      {@link android.widget.Adapter#getView(int, View, ViewGroup) getView()} 
+      is called on the View's {@link android.widget.Adapter}.
+  </li>
+  <li>Call {@link android.graphics.Bitmap#recycle()} on 
+      {@link android.graphics.Bitmap} views that are no longer needed.
+  </li>
+  <li>Use {@link java.lang.ref.WeakReference} for storing references 
+      to {@link android.graphics.Bitmap} objects in a in-memory 
+      <a href="{@link java.util.Collection}.</li>
+  <li>If you fetch images from the network, use {@link android.os.AsyncTask} 
+      to fetch them and store them on the SD card for faster access.
+      Never do network transactions on the application's UI thread.
+  </li>
+  <li>Scale down really large images to a more appropriate size as you download them; otherwise, downloading the image 
+  itself may cause an "Out of Memory" exception. Here is sample code that scales down images while downloading:
+  
+  <pre>
+  // Get the source image's dimensions
+  BitmapFactory.Options options = new BitmapFactory.Options();
+  // This does not download the actual image, just downloads headers.
+  options.inJustDecodeBounds = true; 
+  BitmapFactory.decodeFile(IMAGE_FILE_URL, options);
+  // The actual width of the image.
+  int srcWidth = options.outWidth;  
+  // The actual height of the image.
+  int srcHeight = options.outHeight;  
+
+  // Only scale if the source is bigger than the width of the destination view.
+  if(desiredWidth > srcWidth)
+    desiredWidth = srcWidth;
+
+  // Calculate the correct inSampleSize/scale value. This helps reduce memory use. It should be a power of 2.
+  int inSampleSize = 1;
+  while(srcWidth / 2 > desiredWidth){
+    srcWidth /= 2;
+    srcHeight /= 2;
+    inSampleSize *= 2;
+  }
+
+  float desiredScale = (float) desiredWidth / srcWidth;
+
+  // Decode with inSampleSize
+  options.inJustDecodeBounds = false;
+  options.inDither = false;
+  options.inSampleSize = inSampleSize;
+  options.inScaled = false;
+  // Ensures the image stays as a 32-bit ARGB_8888 image.
+  // This preserves image quality.
+  options.inPreferredConfig = Bitmap.Config.ARGB_8888;  
+                                                	
+  Bitmap sampledSrcBitmap = BitmapFactory.decodeFile(IMAGE_FILE_URL, options);
+
+  // Resize
+  Matrix matrix = new Matrix();
+  matrix.postScale(desiredScale, desiredScale);
+  Bitmap scaledBitmap = Bitmap.createBitmap(sampledSrcBitmap, 0, 0,
+      sampledSrcBitmap.getWidth(), sampledSrcBitmap.getHeight(), matrix, true);
+  sampledSrcBitmap = null;
+
+  // Save
+  FileOutputStream out = new FileOutputStream(LOCAL_PATH_TO_STORE_IMAGE);
+  scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
+  scaledBitmap = null;
+   </pre>
+  </li> </ul>
\ No newline at end of file
diff --git a/docs/html/training/tv/optimizing-navigation-tv.jd b/docs/html/training/tv/optimizing-navigation-tv.jd
new file mode 100644
index 0000000..8b5878e
--- /dev/null
+++ b/docs/html/training/tv/optimizing-navigation-tv.jd
@@ -0,0 +1,206 @@
+page.title=Optimizing Navigation for TV
+parent.title=Designing for TV
+parent.link=index.html
+
+trainingnavtop=true
+previous.title=Optimizing Layouts for TV
+previous.link=optimizing-layouts-tv.html
+next.title=Handling features not supported on TV
+next.link=unsupported-features-tv.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#HandleDpadNavigation">Handle D-pad Navigation</a></li>
+  <li><a href="#HandleFocusSelection">Provide Clear Visual Indication for Focus and Selection</a></li>
+  <li><a href="#DesignForEasyNavigation">Design for Easy Navigation</a></li>
+</ol>
+
+<h2>You should also read</h2>
+<ul>
+  <li><a href="{@docRoot}training/design-navigation/index.html">Designing Effective Navigation</a></li>
+</ul>
+
+</div>
+</div>
+
+<p>
+An important aspect of the user experience when operating a TV is the direct human interface: a remote control. 
+As you optimize your Android application for TVs, you should pay special attention to how the user actually navigates 
+around your application when using a remote control instead of a touchscreen.
+</p>
+<p>
+This lesson shows you how to optimize navigation for TV by:
+</p>
+
+<ul>
+  <li>Ensuring all layout controls are D-pad navigable.</li>
+  <li>Providing highly obvious feedback for UI navigation.</li>
+  <li>Placing layout controls for easy access.</li>
+</ul>
+
+<h2 id="HandleDpadNavigation">Handle D-pad Navigation</h2> 
+
+<p>
+On a TV, users navigate with controls on a TV remote, using either a D-pad or arrow keys. 
+This limits movement to up, down, left, and right. 
+To build a great TV-optimized app, you must provide a navigation scheme in which the user can 
+quickly learn how to navigate your app using the remote.
+</p>
+
+<p>
+When you design navigation for D-pad, follow these guidelines:
+</p>
+
+<ul>
+  <li>Ensure that the D-pad  can navigate to all the visible controls on the screen.</li>
+  <li>For scrolling lists with focus, D-pad up/down keys scroll the list and Enter key selects an item in the list. Ensure that users can 
+  select an element in the list and that the list still scrolls when an element is selected.</li> 
+  <li>Ensure that movement between controls is straightforward and predictable.</li>
+</ul>
+
+<p>
+Android usually handles navigation order between layout elements automatically, so you don't need to do anything extra. If the screen layout 
+makes navigation difficult, or if you want users to move through the layout in a specific way, you can set up explicit navigation for your 
+controls.  
+For example, for an {@code android.widget.EditText}, to define the next control to receive focus, use:
+<pre>
+&lt;EditText android:id="@+id/LastNameField" android:nextFocusDown="@+id/FirstNameField"\&gt;
+</pre>
+The following table lists all of the available navigation attributes:
+</p>
+
+<table>
+<tr>
+<th>Attribute</th>
+<th>Function</th>
+</tr>
+<tr>
+<td>{@link android.R.attr#nextFocusDown}</td>
+<td>Defines the next view to receive focus when the user navigates down.</td>
+</tr>
+<tr>
+<td>{@link android.R.attr#nextFocusLeft}</td>
+<td>Defines the next view to receive focus when the user navigates left.</td>
+</tr>
+<tr>
+<td>{@link android.R.attr#nextFocusRight}</td>
+<td>Defines the next view to receive focus when the user navigates right.</td>
+</tr>
+<tr>
+<td>{@link android.R.attr#nextFocusUp}</td>
+<td>Defines the next view to receive focus when the user navigates up.</td>
+</tr>
+</table>
+
+<p>
+To use one of these explicit navigation attributes, set the value to the ID (android:id value) of another widget in the layout. You should set 
+up the navigation order as a loop, so that the last control directs focus back to the first one.
+</p>
+
+<p>
+Note: You should only use these attributes to modify the navigation order if the default order that the system applies does not work well.
+</p>
+
+<h2 id="HandleFocusSelection">Provide Clear Visual Indication for Focus and Selection</h2>
+
+<p>
+Use appropriate color highlights for all navigable and selectable elements in the UI. This makes it easy for users to know whether the control 
+is currently focused or selected when they navigate with a D-pad. Also, use uniform highlight scheme across your application.
+</p>
+
+<p>
+Android provides <a href="{@docRoot}guide/topics/resources/drawable-resource.html#StateList">Drawable State List Resources</a> to implement highlights 
+for selected and focused controls. For example:
+</p>
+
+res/drawable/button.xml:
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;selector xmlns:android="http://schemas.android.com/apk/res/android"&gt;
+    &lt;item android:state_pressed="true"
+          android:drawable="@drawable/button_pressed" /&gt; &lt;!-- pressed --&gt;
+    &lt;item android:state_focused="true"
+          android:drawable="@drawable/button_focused" /&gt; &lt;!-- focused --&gt;
+    &lt;item android:state_hovered="true"
+          android:drawable="@drawable/button_focused" /&gt; &lt;!-- hovered --&gt;
+    &lt;item android:drawable="@drawable/button_normal" /&gt; &lt;!-- default --&gt;
+&lt;/selector&gt;
+</pre>
+
+<p>
+This layout XML applies the above state list drawable to a {@link android.widget.Button}:
+</p>
+<pre>
+&lt;Button
+    android:layout_height="wrap_content"
+    android:layout_width="wrap_content"
+    android:background="@drawable/button" /&gt;
+</pre>
+
+<p>
+Provide sufficient padding within the focusable and selectable controls so that the highlights around them are clearly visible. 
+</p>
+
+<h2 id="DesignForEasyNavigation">Design for Easy Navigation</h2>
+
+<p>
+Users should be able to navigate to any UI control with a couple of D-pad clicks. Navigation should be easy and  intuitive to 
+understand.  For any non-intuitive actions, provide users with written help, using a dialog triggered by a help button or action bar icon. 
+</p>
+
+<p>
+Predict the next screen that the user will want to navigate to and provide one click navigation to it. If the current screen UI is very sparse, 
+consider making it a multi pane screen. Use fragments for making multi-pane screens. For example, consider the multi-pane UI below with continent names 
+on the left and list of cool places in each continent on the right. 
+</p>
+
+<img src="{@docRoot}images/training/cool-places.png" alt="" />
+
+<p>
+The above UI consists of three Fragments - <code>left_side_action_controls</code>, <code>continents</code> and 
+<code>places</code> - as shown in its layout 
+xml file below. Such multi-pane UIs make D-pad navigation easier and make good use of the horizontal screen space for 
+TVs.
+</p>
+res/layout/cool_places.xml
+<pre>
+&lt;LinearLayout   
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="horizontal"
+   &gt;
+   &lt;fragment
+        android:id="@+id/left_side_action_controls"
+        android:layout_width="0px"
+        android:layout_height="match_parent"
+        android:layout_marginLeft="10dip"
+        android:layout_weight="0.2"/&gt;
+    &lt;fragment
+        android:id="@+id/continents"
+        android:layout_width="0px"
+        android:layout_height="match_parent"
+        android:layout_marginLeft="10dip"
+        android:layout_weight="0.2"/&gt;
+
+    &lt;fragment
+        android:id="@+id/places"
+        android:layout_width="0px"
+        android:layout_height="match_parent"
+        android:layout_marginLeft="10dip"
+        android:layout_weight="0.6"/&gt;
+
+&lt;/LinearLayout&gt;
+</pre>
+
+<p>
+Also, notice in the UI layout above action controls are on the left hand side of a vertically scrolling list to make 
+them easily accessible using D-pad. 
+In general, for layouts with horizontally scrolling components, place action controls on left or right hand side and 
+vice versa for vertically scrolling components.
+</p>
+
diff --git a/docs/html/training/tv/unsupported-features-tv.jd b/docs/html/training/tv/unsupported-features-tv.jd
new file mode 100644
index 0000000..6b0f8c8
--- /dev/null
+++ b/docs/html/training/tv/unsupported-features-tv.jd
@@ -0,0 +1,156 @@
+page.title=Handling Features Not Supported on TV
+parent.title=Designing for TV
+parent.link=index.html
+
+trainingnavtop=true
+previous.title=Optimizing Navigation for TV
+previous.link=optimizing-navigation-tv.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#WorkaroundUnsupportedFeatures">Work Around Features Not Supported on TV</a></li>
+  <li><a href="#CheckAvailableFeatures">Check for Available Features at Runtime</a></li>
+</ol>
+
+</div>
+</div>
+
+<p>
+TVs are much different from other Android-powered devices:
+</p>
+<ul>
+  <li>They're not mobile.</li>
+  <li>Out of habit, people use them for watching media with little or no interaction.</li>
+  <li>People interact with them from a distance.</li>
+</ul>
+
+<p>
+Because TVs have a different purpose from other devices, they usually don't have hardware features 
+that other Android-powered devices often have. For this reason, the Android system does not 
+support the following features for a TV device:
+<table>
+<tr>
+<th>Hardware</th>
+<th>Android feature descriptor</th>
+</tr>
+<tr>
+<td>Camera</td>
+<td>android.hardware.camera</td>
+</tr>
+<tr>
+<td>GPS</td>
+<td>android.hardware.location.gps</td>
+</tr>
+<tr>
+<td>Microphone</td>
+<td>android.hardware.microphone</td>
+</tr>
+<tr>
+<td>Near Field Communications (NFC)</td>
+<td>android.hardware.nfc</td>
+</tr>
+<tr>
+<td>Telephony</td>
+<td>android.hardware.telephony</td>
+</tr>
+<tr>
+<td>Touchscreen</td>
+<td>android.hardware.touchscreen</td>
+</tr>
+</table>
+</p>
+
+<p>
+This lesson shows you how to work around features that are not available on TV by:
+<ul>
+  <li>Providing work arounds for some non-supported features.</li>
+  <li>Checking for available features at runtime and conditionally activating/deactivating certain code 
+  paths based on availability of those features.</li>
+</ul>
+</p>
+
+
+<h2 id="WorkaroundUnsupportedFeatures">Work Around Features Not Supported on TV</h2> 
+
+<p>
+Android doesn't support touchscreen interaction for TV devices, most TVs don't have touch screens, 
+and interacting with a TV using a touchscreen is not consistent with the 10 foot environment. For 
+these reasons, users interact with Android-powered TVs using a remote. In consideration of this, 
+ensure that every control in your app can be accessed with the D-pad. Refer back to the previous two lessons 
+<a href="{@docRoot}training/tv/optimizing-layouts-tv">Optimizing Layouts for TV</a> and 
+<a href="{@docRoot}training/tv/optimizing-navigation-tv">Optimize Navigation for TV</a> for more details 
+on this topic. The Android system assumes that a device has a touchscreen, so if you want your application 
+to run on a TV, you must <strong>explicitly</strong> disable the touchscreen requirement in your manifest file:
+<pre>
+&lt;uses-feature android:name="android.hardware.touchscreen" android:required="false"/&gt;
+</pre>
+</p> 
+
+<p>
+Although a TV doesn't have a camera, you can still provide a photography-related application on a TV. 
+For example, if you have an app that takes, views and edits photos, you can disable its picture-taking 
+functionality for TVs and still allow users to view and even edit photos. The next section talks about how to 
+deactivate or activate specific functions in the application based on runtime device type detection.
+</p>
+
+<p>
+Because TVs are stationary, indoor devices, they don't have built-in GPS. If your application uses location 
+information, allow users to search for a location or use a "static" location provider to get 
+a location from the zip code configured during the TV setup.
+<pre>
+LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
+Location location = locationManager.getLastKnownLocation("static");
+Geocoder geocoder = new Geocoder(this);
+Address address = null;
+
+try {
+  address = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1).get(0);
+  Log.d("Zip code", address.getPostalCode());
+
+} catch (IOException e) {
+  Log.e(TAG, "Geocoder error", e);
+}
+</pre>
+</p>
+
+<p>
+TVs usually don't support microphones, but if you have an application that uses voice control, 
+you can create a mobile device app that takes voice input and then acts as a remote control for a TV.
+</p>
+
+<h2 id="CheckAvailableFeatures">Check for Available Features at Runtime</h2>
+
+<p>
+To check if a feature is available at runtime, call 
+{@link android.content.pm.PackageManager#hasSystemFeature(String)}.
+ This method takes a single argument : a string corresponding to the 
+feature you want to check. For example, to check for touchscreen, use 
+{@link android.content.pm.PackageManager#hasSystemFeature(String)} with the argument 
+{@link android.content.pm.PackageManager#FEATURE_TOUCHSCREEN}.
+</p>
+
+<p>
+The following code snippet demonstrates how to detect device type at runtime based on supported features:
+
+<pre>
+// Check if android.hardware.telephony feature is available.
+if (getPackageManager().hasSystemFeature("android.hardware.telephony")) {
+   Log.d("Mobile Test", "Running on phone");
+// Check if android.hardware.touchscreen feature is available.
+} else if (getPackageManager().hasSystemFeature("android.hardware.touchscreen")) {
+   Log.d("Tablet Test", "Running on devices that don't support telphony but have a touchscreen.");
+} else {
+    Log.d("TV Test", "Running on a TV!");
+}
+</pre>
+</p>
+
+<p>
+This is just one example of using runtime checks to deactivate app functionality that depends on features 
+that aren't available on TVs.
+</p>
\ No newline at end of file
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 6f939be..ed5b2f6 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -16,9 +16,12 @@
 
 package android.graphics;
 
+import android.os.Debug;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.DisplayMetrics;
+import android.util.Log;
+
 import java.io.OutputStream;
 import java.nio.Buffer;
 import java.nio.ByteBuffer;
@@ -57,6 +60,7 @@
 
     private final boolean mIsMutable;
     private byte[] mNinePatchChunk;   // may be null
+    private int[] mLayoutBounds;   // may be null
     private int mWidth = -1;
     private int mHeight = -1;
     private boolean mRecycled;
@@ -95,6 +99,19 @@
     */
     /*package*/ Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
             int density) {
+        this(nativeBitmap, buffer, isMutable, ninePatchChunk, null, density);
+    }
+
+    /**
+     * @noinspection UnusedDeclaration
+     */
+    /*  Private constructor that must received an already allocated native
+        bitmap int (pointer).
+
+        This can be called from JNI code.
+    */
+    /*package*/ Bitmap(int nativeBitmap, byte[] buffer, boolean isMutable, byte[] ninePatchChunk,
+            int[] layoutBounds, int density) {
         if (nativeBitmap == 0) {
             throw new RuntimeException("internal error: native bitmap is 0");
         }
@@ -106,6 +123,7 @@
 
         mIsMutable = isMutable;
         mNinePatchChunk = ninePatchChunk;
+        mLayoutBounds = layoutBounds;
         if (density >= 0) {
             mDensity = density;
         }
@@ -164,6 +182,16 @@
     }
 
     /**
+     * Sets the layout bounds as an array of left, top, right, bottom integers
+     * @param padding the array containing the padding values
+     *
+     * @hide
+     */
+    public void setLayoutBounds(int[] bounds) {
+        mLayoutBounds = bounds;
+    }
+
+    /**
      * Free the native object associated with this bitmap, and clear the
      * reference to the pixel data. This will not free the pixel data synchronously;
      * it simply allows it to be garbage collected if there are no other references.
@@ -690,6 +718,14 @@
     }
 
     /**
+     * @hide
+     * @return the layout padding [left, right, top, bottom]
+     */
+    public int[] getLayoutBounds() {
+        return mLayoutBounds;
+    }
+
+    /**
      * Specifies the known formats a bitmap can be compressed into
      */
     public enum CompressFormat {
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index c5705f6..1599e40 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -424,6 +424,7 @@
             throw new ArrayIndexOutOfBoundsException();
         }
         Bitmap bm = nativeDecodeByteArray(data, offset, length, opts);
+
         if (bm == null && opts != null && opts.inBitmap != null) {
             throw new IllegalArgumentException("Problem decoding into existing bitmap");
         }
@@ -554,7 +555,6 @@
         if (targetDensity == 0 || density == targetDensity || density == opts.inScreenDensity) {
             return bm;
         }
-        
         byte[] np = bm.getNinePatchChunk();
         final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np);
         if (opts.inScaled || isNinePatch) {
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index dcda67d..7e92973 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -40,14 +40,8 @@
     // assigned in constructors, freed in finalizer
     final int mNativeCanvas;
     
-    /*  Our native canvas can be either a raster, gl, or picture canvas.
-        If we are raster, then mGL will be null, and mBitmap may or may not be
-        present (our default constructor creates a raster canvas but no
-        java-bitmap is). If we are a gl-based, then mBitmap will be null, and
-        mGL will not be null. Thus both cannot be non-null, but its possible
-        for both to be null.
-    */
-    private Bitmap  mBitmap;    // if not null, mGL must be null
+    // may be null
+    private Bitmap mBitmap;
     
     // optional field set by the caller
     private DrawFilter mDrawFilter;
@@ -66,7 +60,7 @@
     
     // Used by native code
     @SuppressWarnings({"UnusedDeclaration"})
-    private int         mSurfaceFormat;
+    private int mSurfaceFormat;
 
     /**
      * Flag for drawTextRun indicating left-to-right run direction.
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 043adae..86e824b 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -773,7 +773,13 @@
                 np = null;
                 pad = null;
             }
-            return drawableFromBitmap(res, bm, np, pad, srcName);
+            int[] layoutBounds = bm.getLayoutBounds();
+            Rect layoutBoundsRect = null;
+            if (layoutBounds != null) {
+                layoutBoundsRect = new Rect(layoutBounds[0], layoutBounds[1],
+                                             layoutBounds[2], layoutBounds[3]);
+            }
+            return drawableFromBitmap(res, bm, np, pad, layoutBoundsRect, srcName);
         }
         return null;
     }
@@ -875,7 +881,7 @@
 
         Bitmap bm = BitmapFactory.decodeFile(pathName);
         if (bm != null) {
-            return drawableFromBitmap(null, bm, null, null, pathName);
+            return drawableFromBitmap(null, bm, null, null, null, pathName);
         }
 
         return null;
@@ -956,10 +962,12 @@
     }
 
     private static Drawable drawableFromBitmap(Resources res, Bitmap bm, byte[] np,
-            Rect pad, String srcName) {
+            Rect pad, Rect layoutBounds, String srcName) {
 
         if (np != null) {
-            return new NinePatchDrawable(res, bm, np, pad, srcName);
+            NinePatchDrawable npd = new NinePatchDrawable(res, bm, np, pad, srcName);
+            npd.setLayoutBounds(layoutBounds);
+            return npd;
         }
 
         return new BitmapDrawable(res, bm);
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 18b8bc7..1272071 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -47,6 +47,7 @@
     private NinePatchState mNinePatchState;
     private NinePatch mNinePatch;
     private Rect mPadding;
+    private Rect mLayoutBounds;
     private Paint mPaint;
     private boolean mMutated;
 
@@ -98,6 +99,13 @@
         mNinePatchState.mTargetDensity = mTargetDensity;
     }
 
+    /**
+     * @hide
+     */
+    void setLayoutBounds(Rect layoutBounds) {
+        mLayoutBounds = layoutBounds;
+    }
+
     private void setNinePatchState(NinePatchState state, Resources res) {
         mNinePatchState = state;
         mNinePatch = state.mNinePatch;
@@ -258,7 +266,7 @@
         }
         options.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
 
-        final Rect padding = new Rect();        
+        final Rect padding = new Rect();
         Bitmap bitmap = null;
 
         try {
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 18a0a0c..cd5300d 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -184,9 +184,9 @@
 
     private int getIDSafe() {
         if (mAdaptedAllocation != null) {
-            return mAdaptedAllocation.getID();
+            return mAdaptedAllocation.getID(mRS);
         }
-        return getID();
+        return getID(mRS);
     }
 
 
@@ -321,7 +321,7 @@
     @Override
     void updateFromNative() {
         super.updateFromNative();
-        int typeID = mRS.nAllocationGetType(getID());
+        int typeID = mRS.nAllocationGetType(getID(mRS));
         if(typeID != 0) {
             mType = new Type(typeID, mRS);
             mType.updateFromNative();
@@ -371,7 +371,7 @@
                 "Can only send buffer if IO_OUTPUT usage specified.");
         }
         mRS.validate();
-        mRS.nAllocationIoSend(getID());
+        mRS.nAllocationIoSend(getID(mRS));
     }
 
     /**
@@ -394,7 +394,7 @@
                 "Can only receive if IO_INPUT usage specified.");
         }
         mRS.validate();
-        mRS.nAllocationIoReceive(getID());
+        mRS.nAllocationIoReceive(getID(mRS));
     }
 
     /**
@@ -411,7 +411,7 @@
         }
         int i[] = new int[d.length];
         for (int ct=0; ct < d.length; ct++) {
-            i[ct] = d[ct].getID();
+            i[ct] = d[ct].getID(mRS);
         }
         copy1DRangeFromUnchecked(0, mCurrentCount, i);
     }
@@ -571,7 +571,7 @@
         mRS.validate();
         validateBitmapSize(b);
         validateBitmapFormat(b);
-        mRS.nAllocationCopyFromBitmap(getID(), b);
+        mRS.nAllocationCopyFromBitmap(getID(mRS), b);
     }
 
     /**
@@ -652,7 +652,7 @@
      * followup sync will be required.
      */
     public void generateMipmaps() {
-        mRS.nAllocationGenerateMipmaps(getID());
+        mRS.nAllocationGenerateMipmaps(getID(mRS));
     }
 
     /**
@@ -780,7 +780,7 @@
     public void copy1DRangeFrom(int off, int count, Allocation data, int dataOff) {
         mRS.nAllocationData2D(getIDSafe(), off, 0,
                               mSelectedLOD, mSelectedFace.mID,
-                              count, 1, data.getID(), dataOff, 0,
+                              count, 1, data.getID(mRS), dataOff, 0,
                               data.mSelectedLOD, data.mSelectedFace.mID);
     }
 
@@ -857,7 +857,7 @@
         validate2DRange(xoff, yoff, w, h);
         mRS.nAllocationData2D(getIDSafe(), xoff, yoff,
                               mSelectedLOD, mSelectedFace.mID,
-                              w, h, data.getID(), dataXoff, dataYoff,
+                              w, h, data.getID(mRS), dataXoff, dataYoff,
                               data.mSelectedLOD, data.mSelectedFace.mID);
     }
 
@@ -888,7 +888,7 @@
         mRS.validate();
         validateBitmapFormat(b);
         validateBitmapSize(b);
-        mRS.nAllocationCopyToBitmap(getID(), b);
+        mRS.nAllocationCopyToBitmap(getID(mRS), b);
     }
 
     /**
@@ -901,7 +901,7 @@
     public void copyTo(byte[] d) {
         validateIsInt8();
         mRS.validate();
-        mRS.nAllocationRead(getID(), d);
+        mRS.nAllocationRead(getID(mRS), d);
     }
 
     /**
@@ -914,7 +914,7 @@
     public void copyTo(short[] d) {
         validateIsInt16();
         mRS.validate();
-        mRS.nAllocationRead(getID(), d);
+        mRS.nAllocationRead(getID(mRS), d);
     }
 
     /**
@@ -927,7 +927,7 @@
     public void copyTo(int[] d) {
         validateIsInt32();
         mRS.validate();
-        mRS.nAllocationRead(getID(), d);
+        mRS.nAllocationRead(getID(mRS), d);
     }
 
     /**
@@ -940,7 +940,7 @@
     public void copyTo(float[] d) {
         validateIsFloat32();
         mRS.validate();
-        mRS.nAllocationRead(getID(), d);
+        mRS.nAllocationRead(getID(mRS), d);
     }
 
     /**
@@ -959,10 +959,10 @@
         if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
             throw new RSInvalidStateException("Resize only support for 1D allocations at this time.");
         }
-        mRS.nAllocationResize1D(getID(), dimX);
+        mRS.nAllocationResize1D(getID(mRS), dimX);
         mRS.finish();  // Necessary because resize is fifoed and update is async.
 
-        int typeID = mRS.nAllocationGetType(getID());
+        int typeID = mRS.nAllocationGetType(getID(mRS));
         mType = new Type(typeID, mRS);
         mType.updateFromNative();
         updateCacheInfo(mType);
@@ -991,10 +991,10 @@
             throw new RSInvalidStateException(
                 "Resize only support for 2D allocations at this time.");
         }
-        mRS.nAllocationResize2D(getID(), dimX, dimY);
+        mRS.nAllocationResize2D(getID(mRS), dimX, dimY);
         mRS.finish();  // Necessary because resize is fifoed and update is async.
 
-        int typeID = mRS.nAllocationGetType(getID());
+        int typeID = mRS.nAllocationGetType(getID(mRS));
         mType = new Type(typeID, mRS);
         mType.updateFromNative();
         updateCacheInfo(mType);
@@ -1019,10 +1019,10 @@
      */
     static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mips, int usage) {
         rs.validate();
-        if (type.getID() == 0) {
+        if (type.getID(rs) == 0) {
             throw new RSInvalidStateException("Bad Type");
         }
-        int id = rs.nAllocationCreateTyped(type.getID(), mips.mID, usage, 0);
+        int id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, 0);
         if (id == 0) {
             throw new RSRuntimeException("Allocation creation failed.");
         }
@@ -1043,10 +1043,10 @@
     static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mips,
                                          int usage, int pointer) {
         rs.validate();
-        if (type.getID() == 0) {
+        if (type.getID(rs) == 0) {
             throw new RSInvalidStateException("Bad Type");
         }
-        int id = rs.nAllocationCreateTyped(type.getID(), mips.mID, usage, pointer);
+        int id = rs.nAllocationCreateTyped(type.getID(rs), mips.mID, usage, pointer);
         if (id == 0) {
             throw new RSRuntimeException("Allocation creation failed.");
         }
@@ -1101,7 +1101,7 @@
         b.setX(count);
         Type t = b.create();
 
-        int id = rs.nAllocationCreateTyped(t.getID(), MipmapControl.MIPMAP_NONE.mID, usage, 0);
+        int id = rs.nAllocationCreateTyped(t.getID(rs), MipmapControl.MIPMAP_NONE.mID, usage, 0);
         if (id == 0) {
             throw new RSRuntimeException("Allocation creation failed.");
         }
@@ -1168,7 +1168,7 @@
         rs.validate();
         Type t = typeFromBitmap(rs, b, mips);
 
-        int id = rs.nAllocationCreateFromBitmap(t.getID(), mips.mID, b, usage);
+        int id = rs.nAllocationCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
         if (id == 0) {
             throw new RSRuntimeException("Load failed.");
         }
@@ -1186,9 +1186,9 @@
             throw new RSInvalidStateException("Allocation is not a surface texture.");
         }
 
-        int id = mRS.nAllocationGetSurfaceTextureID(getID());
+        int id = mRS.nAllocationGetSurfaceTextureID(getID(mRS));
         SurfaceTexture st = new SurfaceTexture(id);
-        mRS.nAllocationGetSurfaceTextureID2(getID(), st);
+        mRS.nAllocationGetSurfaceTextureID2(getID(mRS), st);
 
         return st;
     }
@@ -1211,7 +1211,7 @@
             throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT.");
         }
 
-        mRS.nAllocationSetSurface(getID(), sur);
+        mRS.nAllocationSetSurface(getID(mRS), sur);
     }
 
     /**
@@ -1224,7 +1224,7 @@
         }
 
         Surface s = new Surface(st);
-        mRS.nAllocationSetSurface(getID(), s);
+        mRS.nAllocationSetSurface(getID(mRS), s);
     }
 
     /**
@@ -1283,7 +1283,7 @@
         tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL);
         Type t = tb.create();
 
-        int id = rs.nAllocationCubeCreateFromBitmap(t.getID(), mips.mID, b, usage);
+        int id = rs.nAllocationCubeCreateFromBitmap(t.getID(rs), mips.mID, b, usage);
         if(id == 0) {
             throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e);
         }
diff --git a/graphics/java/android/renderscript/AllocationAdapter.java b/graphics/java/android/renderscript/AllocationAdapter.java
index d38f2df..85d86e5 100644
--- a/graphics/java/android/renderscript/AllocationAdapter.java
+++ b/graphics/java/android/renderscript/AllocationAdapter.java
@@ -30,7 +30,7 @@
         mAdaptedAllocation = alloc;
     }
 
-    int getID() {
+    int getID(RenderScript rs) {
         throw new RSInvalidStateException(
             "This operation is not supported with adapters at this time.");
     }
diff --git a/graphics/java/android/renderscript/BaseObj.java b/graphics/java/android/renderscript/BaseObj.java
index 2e55c48..f464f9b 100644
--- a/graphics/java/android/renderscript/BaseObj.java
+++ b/graphics/java/android/renderscript/BaseObj.java
@@ -43,16 +43,22 @@
      * Lookup the native object ID for this object.  Primarily used by the
      * generated reflected code.
      *
+     * @param rs Context to verify against internal context for
+     *           match.
      *
      * @return int
      */
-    int getID() {
+    int getID(RenderScript rs) {
+        mRS.validate();
         if (mDestroyed) {
             throw new RSInvalidStateException("using a destroyed object.");
         }
         if (mID == 0) {
             throw new RSRuntimeException("Internal error: Object id 0.");
         }
+        if ((rs != null) && (rs != mRS)) {
+            throw new RSInvalidStateException("using object with mismatched context.");
+        }
         return mID;
     }
 
@@ -138,7 +144,7 @@
      */
     void updateFromNative() {
         mRS.validate();
-        mName = mRS.nGetName(getID());
+        mName = mRS.nGetName(getID(mRS));
     }
 
     /**
diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java
index 3d4951f..d75c951 100644
--- a/graphics/java/android/renderscript/Element.java
+++ b/graphics/java/android/renderscript/Element.java
@@ -778,7 +778,7 @@
 
         // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements
         int[] dataBuffer = new int[5];
-        mRS.nElementGetNativeData(getID(), dataBuffer);
+        mRS.nElementGetNativeData(getID(mRS), dataBuffer);
 
         mNormalized = dataBuffer[2] == 1 ? true : false;
         mVectorSize = dataBuffer[3];
@@ -803,7 +803,7 @@
             mOffsetInBytes = new int[numSubElements];
 
             int[] subElementIds = new int[numSubElements];
-            mRS.nElementGetSubElements(getID(), subElementIds, mElementNames, mArraySizes);
+            mRS.nElementGetSubElements(getID(mRS), subElementIds, mElementNames, mArraySizes);
             for(int i = 0; i < numSubElements; i ++) {
                 mElements[i] = new Element(subElementIds[i], mRS);
                 mElements[i].updateFromNative();
@@ -1062,7 +1062,7 @@
 
             int[] ids = new int[ein.length];
             for (int ct = 0; ct < ein.length; ct++ ) {
-                ids[ct] = ein[ct].getID();
+                ids[ct] = ein[ct].getID(mRS);
             }
             int id = mRS.nElementCreate2(ids, sin, asin);
             return new Element(id, mRS, ein, sin, asin);
diff --git a/graphics/java/android/renderscript/FieldPacker.java b/graphics/java/android/renderscript/FieldPacker.java
index 2739a4b8..a215a57 100644
--- a/graphics/java/android/renderscript/FieldPacker.java
+++ b/graphics/java/android/renderscript/FieldPacker.java
@@ -143,7 +143,7 @@
 
     public void addObj(BaseObj obj) {
         if (obj != null) {
-            addI32(obj.getID());
+            addI32(obj.getID(null));
         } else {
             addI32(0);
         }
diff --git a/graphics/java/android/renderscript/FileA3D.java b/graphics/java/android/renderscript/FileA3D.java
index b5419a7..61793171 100644
--- a/graphics/java/android/renderscript/FileA3D.java
+++ b/graphics/java/android/renderscript/FileA3D.java
@@ -165,7 +165,7 @@
     }
 
     private void initEntries() {
-        int numFileEntries = mRS.nFileA3DGetNumIndexEntries(getID());
+        int numFileEntries = mRS.nFileA3DGetNumIndexEntries(getID(mRS));
         if(numFileEntries <= 0) {
             return;
         }
@@ -174,10 +174,10 @@
         int[] ids = new int[numFileEntries];
         String[] names = new String[numFileEntries];
 
-        mRS.nFileA3DGetIndexEntries(getID(), numFileEntries, ids, names);
+        mRS.nFileA3DGetIndexEntries(getID(mRS), numFileEntries, ids, names);
 
         for(int i = 0; i < numFileEntries; i ++) {
-            mFileEntries[i] = new IndexEntry(mRS, i, getID(), names[i], EntryType.toEntryType(ids[i]));
+            mFileEntries[i] = new IndexEntry(mRS, i, getID(mRS), names[i], EntryType.toEntryType(ids[i]));
         }
     }
 
diff --git a/graphics/java/android/renderscript/Mesh.java b/graphics/java/android/renderscript/Mesh.java
index f641117..ffbb41d 100644
--- a/graphics/java/android/renderscript/Mesh.java
+++ b/graphics/java/android/renderscript/Mesh.java
@@ -137,15 +137,15 @@
     @Override
     void updateFromNative() {
         super.updateFromNative();
-        int vtxCount = mRS.nMeshGetVertexBufferCount(getID());
-        int idxCount = mRS.nMeshGetIndexCount(getID());
+        int vtxCount = mRS.nMeshGetVertexBufferCount(getID(mRS));
+        int idxCount = mRS.nMeshGetIndexCount(getID(mRS));
 
         int[] vtxIDs = new int[vtxCount];
         int[] idxIDs = new int[idxCount];
         int[] primitives = new int[idxCount];
 
-        mRS.nMeshGetVertices(getID(), vtxIDs, vtxCount);
-        mRS.nMeshGetIndices(getID(), idxIDs, primitives, idxCount);
+        mRS.nMeshGetVertices(getID(mRS), vtxIDs, vtxCount);
+        mRS.nMeshGetIndices(getID(mRS), idxIDs, primitives, idxCount);
 
         mVertexBuffers = new Allocation[vtxCount];
         mIndexBuffers = new Allocation[idxCount];
@@ -343,7 +343,7 @@
                     alloc = Allocation.createSized(mRS, entry.e, entry.size, mUsage);
                 }
                 vertexBuffers[ct] = alloc;
-                vtx[ct] = alloc.getID();
+                vtx[ct] = alloc.getID(mRS);
             }
 
             for(int ct = 0; ct < mIndexTypes.size(); ct ++) {
@@ -354,7 +354,7 @@
                 } else if(entry.e != null) {
                     alloc = Allocation.createSized(mRS, entry.e, entry.size, mUsage);
                 }
-                int allocID = (alloc == null) ? 0 : alloc.getID();
+                int allocID = (alloc == null) ? 0 : alloc.getID(mRS);
                 indexBuffers[ct] = alloc;
                 primitives[ct] = entry.prim;
 
@@ -483,12 +483,12 @@
             for(int ct = 0; ct < mVertexTypeCount; ct ++) {
                 Entry entry = mVertexTypes[ct];
                 vertexBuffers[ct] = entry.a;
-                vtx[ct] = entry.a.getID();
+                vtx[ct] = entry.a.getID(mRS);
             }
 
             for(int ct = 0; ct < mIndexTypes.size(); ct ++) {
                 Entry entry = (Entry)mIndexTypes.elementAt(ct);
-                int allocID = (entry.a == null) ? 0 : entry.a.getID();
+                int allocID = (entry.a == null) ? 0 : entry.a.getID(mRS);
                 indexBuffers[ct] = entry.a;
                 primitives[ct] = entry.prim;
 
diff --git a/graphics/java/android/renderscript/Path.java b/graphics/java/android/renderscript/Path.java
index 83ae150..9c4d41b 100644
--- a/graphics/java/android/renderscript/Path.java
+++ b/graphics/java/android/renderscript/Path.java
@@ -67,7 +67,7 @@
 
 
     public static Path createStaticPath(RenderScript rs, Primitive p, float quality, Allocation vtx) {
-        int id = rs.nPathCreate(p.mID, false, vtx.getID(), 0, quality);
+        int id = rs.nPathCreate(p.mID, false, vtx.getID(rs), 0, quality);
         Path newPath = new Path(id, rs, p, null, null, quality);
         return newPath;
     }
diff --git a/graphics/java/android/renderscript/Program.java b/graphics/java/android/renderscript/Program.java
index 4d60ac8..104d1cd 100644
--- a/graphics/java/android/renderscript/Program.java
+++ b/graphics/java/android/renderscript/Program.java
@@ -134,11 +134,11 @@
             throw new IllegalArgumentException("Slot ID out of range.");
         }
         if (a != null &&
-            a.getType().getID() != mConstants[slot].getID()) {
+            a.getType().getID(mRS) != mConstants[slot].getID(mRS)) {
             throw new IllegalArgumentException("Allocation type does not match slot type.");
         }
-        int id = a != null ? a.getID() : 0;
-        mRS.nProgramBindConstants(getID(), slot, id);
+        int id = a != null ? a.getID(mRS) : 0;
+        mRS.nProgramBindConstants(getID(mRS), slot, id);
     }
 
     /**
@@ -159,8 +159,8 @@
             throw new IllegalArgumentException("Cannot bind cubemap to 2d texture slot");
         }
 
-        int id = va != null ? va.getID() : 0;
-        mRS.nProgramBindTexture(getID(), slot, id);
+        int id = va != null ? va.getID(mRS) : 0;
+        mRS.nProgramBindTexture(getID(mRS), slot, id);
     }
 
     /**
@@ -179,8 +179,8 @@
             throw new IllegalArgumentException("Slot ID out of range.");
         }
 
-        int id = vs != null ? vs.getID() : 0;
-        mRS.nProgramBindSampler(getID(), slot, id);
+        int id = vs != null ? vs.getID(mRS) : 0;
+        mRS.nProgramBindSampler(getID(mRS), slot, id);
     }
 
 
diff --git a/graphics/java/android/renderscript/ProgramFragment.java b/graphics/java/android/renderscript/ProgramFragment.java
index ebc15e5..fa6e2d4 100644
--- a/graphics/java/android/renderscript/ProgramFragment.java
+++ b/graphics/java/android/renderscript/ProgramFragment.java
@@ -64,15 +64,15 @@
 
             for (int i=0; i < mInputCount; i++) {
                 tmp[idx++] = ProgramParam.INPUT.mID;
-                tmp[idx++] = mInputs[i].getID();
+                tmp[idx++] = mInputs[i].getID(mRS);
             }
             for (int i=0; i < mOutputCount; i++) {
                 tmp[idx++] = ProgramParam.OUTPUT.mID;
-                tmp[idx++] = mOutputs[i].getID();
+                tmp[idx++] = mOutputs[i].getID(mRS);
             }
             for (int i=0; i < mConstantCount; i++) {
                 tmp[idx++] = ProgramParam.CONSTANT.mID;
-                tmp[idx++] = mConstants[i].getID();
+                tmp[idx++] = mConstants[i].getID(mRS);
             }
             for (int i=0; i < mTextureCount; i++) {
                 tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
diff --git a/graphics/java/android/renderscript/ProgramFragmentFixedFunction.java b/graphics/java/android/renderscript/ProgramFragmentFixedFunction.java
index cd31db3..14f10f1 100644
--- a/graphics/java/android/renderscript/ProgramFragmentFixedFunction.java
+++ b/graphics/java/android/renderscript/ProgramFragmentFixedFunction.java
@@ -52,15 +52,15 @@
 
             for (int i=0; i < mInputCount; i++) {
                 tmp[idx++] = ProgramParam.INPUT.mID;
-                tmp[idx++] = mInputs[i].getID();
+                tmp[idx++] = mInputs[i].getID(mRS);
             }
             for (int i=0; i < mOutputCount; i++) {
                 tmp[idx++] = ProgramParam.OUTPUT.mID;
-                tmp[idx++] = mOutputs[i].getID();
+                tmp[idx++] = mOutputs[i].getID(mRS);
             }
             for (int i=0; i < mConstantCount; i++) {
                 tmp[idx++] = ProgramParam.CONSTANT.mID;
-                tmp[idx++] = mConstants[i].getID();
+                tmp[idx++] = mConstants[i].getID(mRS);
             }
             for (int i=0; i < mTextureCount; i++) {
                 tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
diff --git a/graphics/java/android/renderscript/ProgramVertex.java b/graphics/java/android/renderscript/ProgramVertex.java
index a6cd15b..32c908e 100644
--- a/graphics/java/android/renderscript/ProgramVertex.java
+++ b/graphics/java/android/renderscript/ProgramVertex.java
@@ -121,15 +121,15 @@
 
             for (int i=0; i < mInputCount; i++) {
                 tmp[idx++] = ProgramParam.INPUT.mID;
-                tmp[idx++] = mInputs[i].getID();
+                tmp[idx++] = mInputs[i].getID(mRS);
             }
             for (int i=0; i < mOutputCount; i++) {
                 tmp[idx++] = ProgramParam.OUTPUT.mID;
-                tmp[idx++] = mOutputs[i].getID();
+                tmp[idx++] = mOutputs[i].getID(mRS);
             }
             for (int i=0; i < mConstantCount; i++) {
                 tmp[idx++] = ProgramParam.CONSTANT.mID;
-                tmp[idx++] = mConstants[i].getID();
+                tmp[idx++] = mConstants[i].getID(mRS);
             }
             for (int i=0; i < mTextureCount; i++) {
                 tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
diff --git a/graphics/java/android/renderscript/ProgramVertexFixedFunction.java b/graphics/java/android/renderscript/ProgramVertexFixedFunction.java
index 9a43943..fac4c3d 100644
--- a/graphics/java/android/renderscript/ProgramVertexFixedFunction.java
+++ b/graphics/java/android/renderscript/ProgramVertexFixedFunction.java
@@ -75,15 +75,15 @@
 
             for (int i=0; i < mInputCount; i++) {
                 tmp[idx++] = ProgramParam.INPUT.mID;
-                tmp[idx++] = mInputs[i].getID();
+                tmp[idx++] = mInputs[i].getID(mRS);
             }
             for (int i=0; i < mOutputCount; i++) {
                 tmp[idx++] = ProgramParam.OUTPUT.mID;
-                tmp[idx++] = mOutputs[i].getID();
+                tmp[idx++] = mOutputs[i].getID(mRS);
             }
             for (int i=0; i < mConstantCount; i++) {
                 tmp[idx++] = ProgramParam.CONSTANT.mID;
-                tmp[idx++] = mConstants[i].getID();
+                tmp[idx++] = mConstants[i].getID(mRS);
             }
             for (int i=0; i < mTextureCount; i++) {
                 tmp[idx++] = ProgramParam.TEXTURE_TYPE.mID;
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index dffd400..03294b5 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -1000,7 +1000,7 @@
 
     int safeID(BaseObj o) {
         if(o != null) {
-            return o.getID();
+            return o.getID(this);
         }
         return 0;
     }
diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java
index d00c428..4f59ae3 100644
--- a/graphics/java/android/renderscript/Script.java
+++ b/graphics/java/android/renderscript/Script.java
@@ -26,7 +26,7 @@
      * @param slot
      */
     protected void invoke(int slot) {
-        mRS.nScriptInvoke(getID(), slot);
+        mRS.nScriptInvoke(getID(mRS), slot);
     }
 
     /**
@@ -37,9 +37,9 @@
      */
     protected void invoke(int slot, FieldPacker v) {
         if (v != null) {
-            mRS.nScriptInvokeV(getID(), slot, v.getData());
+            mRS.nScriptInvokeV(getID(mRS), slot, v.getData());
         } else {
-            mRS.nScriptInvoke(getID(), slot);
+            mRS.nScriptInvoke(getID(mRS), slot);
         }
     }
 
@@ -58,17 +58,17 @@
         }
         int in_id = 0;
         if (ain != null) {
-            in_id = ain.getID();
+            in_id = ain.getID(mRS);
         }
         int out_id = 0;
         if (aout != null) {
-            out_id = aout.getID();
+            out_id = aout.getID(mRS);
         }
         byte[] params = null;
         if (v != null) {
             params = v.getData();
         }
-        mRS.nScriptForEach(getID(), slot, in_id, out_id, params);
+        mRS.nScriptForEach(getID(mRS), slot, in_id, out_id, params);
     }
 
 
@@ -86,9 +86,9 @@
     public void bindAllocation(Allocation va, int slot) {
         mRS.validate();
         if (va != null) {
-            mRS.nScriptBindAllocation(getID(), va.getID(), slot);
+            mRS.nScriptBindAllocation(getID(mRS), va.getID(mRS), slot);
         } else {
-            mRS.nScriptBindAllocation(getID(), 0, slot);
+            mRS.nScriptBindAllocation(getID(mRS), 0, slot);
         }
     }
 
@@ -99,7 +99,7 @@
      * @param v
      */
     public void setVar(int index, float v) {
-        mRS.nScriptSetVarF(getID(), index, v);
+        mRS.nScriptSetVarF(getID(mRS), index, v);
     }
 
     /**
@@ -109,7 +109,7 @@
      * @param v
      */
     public void setVar(int index, double v) {
-        mRS.nScriptSetVarD(getID(), index, v);
+        mRS.nScriptSetVarD(getID(mRS), index, v);
     }
 
     /**
@@ -119,7 +119,7 @@
      * @param v
      */
     public void setVar(int index, int v) {
-        mRS.nScriptSetVarI(getID(), index, v);
+        mRS.nScriptSetVarI(getID(mRS), index, v);
     }
 
     /**
@@ -129,7 +129,7 @@
      * @param v
      */
     public void setVar(int index, long v) {
-        mRS.nScriptSetVarJ(getID(), index, v);
+        mRS.nScriptSetVarJ(getID(mRS), index, v);
     }
 
     /**
@@ -139,7 +139,7 @@
      * @param v
      */
     public void setVar(int index, boolean v) {
-        mRS.nScriptSetVarI(getID(), index, v ? 1 : 0);
+        mRS.nScriptSetVarI(getID(mRS), index, v ? 1 : 0);
     }
 
     /**
@@ -149,7 +149,7 @@
      * @param o
      */
     public void setVar(int index, BaseObj o) {
-        mRS.nScriptSetVarObj(getID(), index, (o == null) ? 0 : o.getID());
+        mRS.nScriptSetVarObj(getID(mRS), index, (o == null) ? 0 : o.getID(mRS));
     }
 
     /**
@@ -159,13 +159,13 @@
      * @param v
      */
     public void setVar(int index, FieldPacker v) {
-        mRS.nScriptSetVarV(getID(), index, v.getData());
+        mRS.nScriptSetVarV(getID(mRS), index, v.getData());
     }
 
     public void setTimeZone(String timeZone) {
         mRS.validate();
         try {
-            mRS.nScriptSetTimeZone(getID(), timeZone.getBytes("UTF-8"));
+            mRS.nScriptSetTimeZone(getID(mRS), timeZone.getBytes("UTF-8"));
         } catch (java.io.UnsupportedEncodingException e) {
             throw new RuntimeException(e);
         }
diff --git a/graphics/java/android/renderscript/Type.java b/graphics/java/android/renderscript/Type.java
index 70d1de4..a707df2 100644
--- a/graphics/java/android/renderscript/Type.java
+++ b/graphics/java/android/renderscript/Type.java
@@ -180,7 +180,7 @@
         // We have 6 integer to obtain mDimX; mDimY; mDimZ;
         // mDimLOD; mDimFaces; mElement;
         int[] dataBuffer = new int[6];
-        mRS.nTypeGetNativeData(getID(), dataBuffer);
+        mRS.nTypeGetNativeData(getID(mRS), dataBuffer);
 
         mDimX = dataBuffer[0];
         mDimY = dataBuffer[1];
@@ -280,7 +280,8 @@
                 }
             }
 
-            int id = mRS.nTypeCreate(mElement.getID(), mDimX, mDimY, mDimZ, mDimMipmaps, mDimFaces);
+            int id = mRS.nTypeCreate(mElement.getID(mRS),
+                                     mDimX, mDimY, mDimZ, mDimMipmaps, mDimFaces);
             Type t = new Type(id, mRS);
             t.mElement = mElement;
             t.mDimX = mDimX;
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index f37bfd2..9f2bacd 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -112,6 +112,7 @@
     mClipChildren = true;
     mAlpha = 1;
     mMultipliedAlpha = 255;
+    mHasOverlappingRendering = true;
     mTranslationX = 0;
     mTranslationY = 0;
     mRotation = 0;
@@ -772,18 +773,23 @@
             }
         }
         if (mAlpha < 1 && !mCaching) {
-            // TODO: should be able to store the size of a DL at record time and not
-            // have to pass it into this call. In fact, this information might be in the
-            // location/size info that we store with the new native transform data.
-            int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
-            if (mClipChildren) {
-                flags |= SkCanvas::kClipToLayer_SaveFlag;
+            if (!mHasOverlappingRendering) {
+                DISPLAY_LIST_LOGD("%s%s %.2f", indent, "SetAlpha", mAlpha);
+                renderer.setAlpha(mAlpha);
+            } else {
+                // TODO: should be able to store the size of a DL at record time and not
+                // have to pass it into this call. In fact, this information might be in the
+                // location/size info that we store with the new native transform data.
+                int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
+                if (mClipChildren) {
+                    flags |= SkCanvas::kClipToLayer_SaveFlag;
+                }
+                DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha",
+                        (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop,
+                        mMultipliedAlpha, flags);
+                renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop,
+                        mMultipliedAlpha, flags);
             }
-            DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha",
-                    (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop,
-                    mMultipliedAlpha, flags);
-            renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop,
-                    mMultipliedAlpha, flags);
         }
         if (mClipChildren) {
             DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f", indent, "ClipRect", 0.0f, 0.0f,
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 38b0a6d..fe0c94d 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -181,6 +181,10 @@
         }
     }
 
+    void setHasOverlappingRendering(bool hasOverlappingRendering) {
+        mHasOverlappingRendering = hasOverlappingRendering;
+    }
+
     void setTranslationX(float translationX) {
         if (translationX != mTranslationX) {
             mTranslationX = translationX;
@@ -496,6 +500,7 @@
     bool mClipChildren;
     float mAlpha;
     int mMultipliedAlpha;
+    bool mHasOverlappingRendering;
     float mTranslationX, mTranslationY;
     float mRotation, mRotationX, mRotationY;
     float mScaleX, mScaleY;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 115787c..39d2e39 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -631,6 +631,9 @@
     const bool fboLayer = current->flags & Snapshot::kFlagIsFboLayer;
 
     if (fboLayer) {
+        // Detach the texture from the FBO
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
+
         // Unbind current FBO and restore previous one
         glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo);
     }
@@ -671,11 +674,6 @@
         //       code path
         // See LayerRenderer::destroyLayer(Layer*)
 
-        // Detach the texture from the FBO
-        glBindFramebuffer(GL_FRAMEBUFFER, current->fbo);
-        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
-        glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo);
-
         // Put the FBO name back in the cache, if it doesn't fit, it will be destroyed
         mCaches.fboCache.put(current->fbo);
         layer->setFbo(0);
@@ -1101,6 +1099,7 @@
 
 void OpenGLRenderer::setupDrawColor(int color, int alpha) {
     mColorA = alpha / 255.0f;
+    mColorA *= mSnapshot->alpha;
     // Second divide of a by 255 is an optimization, allowing us to simply multiply
     // the rgb values by a instead of also dividing by 255
     const float a = mColorA / 255.0f;
@@ -1329,18 +1328,18 @@
  * are set up for each individual segment.
  */
 void OpenGLRenderer::setupDrawAALine(GLvoid* vertices, GLvoid* widthCoords,
-        GLvoid* lengthCoords, float boundaryWidthProportion) {
+        GLvoid* lengthCoords, float boundaryWidthProportion, int& widthSlot, int& lengthSlot) {
     bool force = mCaches.unbindMeshBuffer();
     mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position,
             vertices, gAAVertexStride);
     mCaches.resetTexCoordsVertexPointer();
     mCaches.unbindIndicesBuffer();
 
-    int widthSlot = mCaches.currentProgram->getAttrib("vtxWidth");
+    widthSlot = mCaches.currentProgram->getAttrib("vtxWidth");
     glEnableVertexAttribArray(widthSlot);
     glVertexAttribPointer(widthSlot, 1, GL_FLOAT, GL_FALSE, gAAVertexStride, widthCoords);
 
-    int lengthSlot = mCaches.currentProgram->getAttrib("vtxLength");
+    lengthSlot = mCaches.currentProgram->getAttrib("vtxLength");
     glEnableVertexAttribArray(lengthSlot);
     glVertexAttribPointer(lengthSlot, 1, GL_FLOAT, GL_FALSE, gAAVertexStride, lengthCoords);
 
@@ -1349,7 +1348,12 @@
 
     // Setting the inverse value saves computations per-fragment in the shader
     int inverseBoundaryWidthSlot = mCaches.currentProgram->getUniform("inverseBoundaryWidth");
-    glUniform1f(inverseBoundaryWidthSlot, (1 / boundaryWidthProportion));
+    glUniform1f(inverseBoundaryWidthSlot, 1.0f / boundaryWidthProportion);
+}
+
+void OpenGLRenderer::finishDrawAALine(const int widthSlot, const int lengthSlot) {
+    glDisableVertexAttribArray(widthSlot);
+    glDisableVertexAttribArray(lengthSlot);
 }
 
 void OpenGLRenderer::finishDrawTexture() {
@@ -1721,13 +1725,18 @@
     float width = right - left;
     float height = bottom - top;
 
+    int widthSlot;
+    int lengthSlot;
+
     float boundaryWidthProportion = (width != 0) ? (2 * boundarySizeX) / width : 0;
     float boundaryHeightProportion = (height != 0) ? (2 * boundarySizeY) / height : 0;
-    setupDrawAALine((void*) aaVertices, widthCoords, lengthCoords, boundaryWidthProportion);
+    setupDrawAALine((void*) aaVertices, widthCoords, lengthCoords,
+            boundaryWidthProportion, widthSlot, lengthSlot);
+
     int boundaryLengthSlot = mCaches.currentProgram->getUniform("boundaryLength");
     int inverseBoundaryLengthSlot = mCaches.currentProgram->getUniform("inverseBoundaryLength");
     glUniform1f(boundaryLengthSlot, boundaryHeightProportion);
-    glUniform1f(inverseBoundaryLengthSlot, (1 / boundaryHeightProportion));
+    glUniform1f(inverseBoundaryLengthSlot, (1.0f / boundaryHeightProportion));
 
     if (!quickReject(left, top, right, bottom)) {
         AAVertex::set(aaVertices++, left, bottom, 1, 1);
@@ -1737,6 +1746,8 @@
         dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
     }
+
+    finishDrawAALine(widthSlot, lengthSlot);
 }
 
 /**
@@ -1767,11 +1778,14 @@
     // A stroke width of 0 has a special meaning in Skia:
     // it draws a line 1 px wide regardless of current transform
     bool isHairLine = paint->getStrokeWidth() == 0.0f;
+
     float inverseScaleX = 1.0f;
     float inverseScaleY = 1.0f;
     bool scaled = false;
+
     int alpha;
     SkXfermode::Mode mode;
+
     int generatedVerticesCount = 0;
     int verticesCount = count;
     if (count > 4) {
@@ -1791,10 +1805,13 @@
             float m10 = mat->data[Matrix4::kSkewX];
             float m11 = mat->data[Matrix4::kScaleX];
             float m12 = mat->data[6];
+
             float scaleX = sqrtf(m00 * m00 + m01 * m01);
             float scaleY = sqrtf(m10 * m10 + m11 * m11);
+
             inverseScaleX = (scaleX != 0) ? (inverseScaleX / scaleX) : 0;
             inverseScaleY = (scaleY != 0) ? (inverseScaleY / scaleY) : 0;
+
             if (inverseScaleX != 1.0f || inverseScaleY != 1.0f) {
                 scaled = true;
             }
@@ -1824,10 +1841,16 @@
         // Expand boundary to enable AA calculations on the quad border
         halfStrokeWidth += .5f;
     }
+
+    int widthSlot;
+    int lengthSlot;
+
     Vertex lines[verticesCount];
     Vertex* vertices = &lines[0];
+
     AAVertex wLines[verticesCount];
     AAVertex* aaVertices = &wLines[0];
+
     if (CC_UNLIKELY(!isAA)) {
         setupDrawVertices(vertices);
     } else {
@@ -1839,7 +1862,8 @@
         // We will need to calculate the actual width proportion on each segment for
         // scaled non-hairlines, since the boundary proportion may differ per-axis when scaled.
         float boundaryWidthProportion = 1 / (2 * halfStrokeWidth);
-        setupDrawAALine((void*) aaVertices, widthCoords, lengthCoords, boundaryWidthProportion);
+        setupDrawAALine((void*) aaVertices, widthCoords, lengthCoords,
+                boundaryWidthProportion, widthSlot, lengthSlot);
     }
 
     AAVertex* prevAAVertex = NULL;
@@ -1849,10 +1873,12 @@
     int inverseBoundaryLengthSlot = -1;
     int boundaryWidthSlot = -1;
     int inverseBoundaryWidthSlot = -1;
+
     for (int i = 0; i < count; i += 4) {
         // a = start point, b = end point
         vec2 a(points[i], points[i + 1]);
         vec2 b(points[i + 2], points[i + 3]);
+
         float length = 0;
         float boundaryLengthProportion = 0;
         float boundaryWidthProportion = 0;
@@ -1869,6 +1895,7 @@
                 }
                 n *= wideningFactor;
             }
+
             if (scaled) {
                 n.x *= inverseScaleX;
                 n.y *= inverseScaleY;
@@ -1879,11 +1906,13 @@
             extendedN /= 2;
             extendedN.x *= inverseScaleX;
             extendedN.y *= inverseScaleY;
+
             float extendedNLength = extendedN.length();
             // We need to set this value on the shader prior to drawing
             boundaryWidthProportion = extendedNLength / (halfStrokeWidth + extendedNLength);
             n += extendedN;
         }
+
         float x = n.x;
         n.x = -n.y;
         n.y = x;
@@ -1893,6 +1922,7 @@
             vec2 abVector = (b - a);
             length = abVector.length();
             abVector.normalize();
+
             if (scaled) {
                 abVector.x *= inverseScaleX;
                 abVector.y *= inverseScaleY;
@@ -1901,6 +1931,7 @@
             } else {
                 boundaryLengthProportion = .5 / (length + 1);
             }
+
             abVector /= 2;
             a -= abVector;
             b += abVector;
@@ -1929,10 +1960,12 @@
                     Vertex::set(vertices++, p1.x, p1.y);
                     generatedVerticesCount += 2;
                 }
+
                 Vertex::set(vertices++, p1.x, p1.y);
                 Vertex::set(vertices++, p2.x, p2.y);
                 Vertex::set(vertices++, p4.x, p4.y);
                 Vertex::set(vertices++, p3.x, p3.y);
+
                 prevVertex = vertices - 1;
                 generatedVerticesCount += 4;
             } else {
@@ -1945,14 +1978,17 @@
                         inverseBoundaryWidthSlot =
                                 mCaches.currentProgram->getUniform("inverseBoundaryWidth");
                     }
+
                     glUniform1f(boundaryWidthSlot, boundaryWidthProportion);
                     glUniform1f(inverseBoundaryWidthSlot, (1 / boundaryWidthProportion));
                 }
+
                 if (boundaryLengthSlot < 0) {
                     boundaryLengthSlot = mCaches.currentProgram->getUniform("boundaryLength");
                     inverseBoundaryLengthSlot =
                             mCaches.currentProgram->getUniform("inverseBoundaryLength");
                 }
+
                 glUniform1f(boundaryLengthSlot, boundaryLengthProportion);
                 glUniform1f(inverseBoundaryLengthSlot, (1 / boundaryLengthProportion));
 
@@ -1966,21 +2002,29 @@
                     AAVertex::set(aaVertices++, p4.x, p4.y, 1, 1);
                     generatedVerticesCount += 2;
                 }
+
                 AAVertex::set(aaVertices++, p4.x, p4.y, 1, 1);
                 AAVertex::set(aaVertices++, p1.x, p1.y, 1, 0);
                 AAVertex::set(aaVertices++, p3.x, p3.y, 0, 1);
                 AAVertex::set(aaVertices++, p2.x, p2.y, 0, 0);
+
                 prevAAVertex = aaVertices - 1;
                 generatedVerticesCount += 4;
             }
+
             dirtyLayer(a.x == b.x ? left - 1 : left, a.y == b.y ? top - 1 : top,
                     a.x == b.x ? right: right, a.y == b.y ? bottom: bottom,
                     *mSnapshot->transform);
         }
     }
+
     if (generatedVerticesCount > 0) {
        glDrawArrays(GL_TRIANGLE_STRIP, 0, generatedVerticesCount);
     }
+
+    if (isAA) {
+        finishDrawAALine(widthSlot, lengthSlot);
+    }
 }
 
 void OpenGLRenderer::drawPoints(float* points, int count, SkPaint* paint) {
@@ -2026,10 +2070,12 @@
     for (int i = 0; i < count; i += 2) {
         TextureVertex::set(vertex++, points[i], points[i + 1], 0.0f, 0.0f);
         generatedVerticesCount++;
+
         float left = points[i] - halfWidth;
         float right = points[i] + halfWidth;
         float top = points[i + 1] - halfWidth;
         float bottom = points [i + 1] + halfWidth;
+
         dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
     }
 
@@ -2800,6 +2846,7 @@
         *mode = SkXfermode::kSrcOver_Mode;
         *alpha = 255;
     }
+    *alpha *= mSnapshot->alpha;
 }
 
 SkXfermode::Mode OpenGLRenderer::getXfermode(SkXfermode* mode) {
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index b651904..b52d2b0 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -85,6 +85,10 @@
     virtual int saveLayerAlpha(float left, float top, float right, float bottom,
             int alpha, int flags);
 
+    virtual void setAlpha(float alpha) {
+        mSnapshot->alpha = alpha;
+    }
+
     virtual void translate(float dx, float dy);
     virtual void rotate(float degrees);
     virtual void scale(float sx, float sy);
@@ -549,7 +553,8 @@
     void setupDrawMeshIndices(GLvoid* vertices, GLvoid* texCoords);
     void setupDrawVertices(GLvoid* vertices);
     void setupDrawAALine(GLvoid* vertices, GLvoid* distanceCoords, GLvoid* lengthCoords,
-            float strokeWidth);
+            float strokeWidth, int& widthSlot, int& lengthSlot);
+    void finishDrawAALine(const int widthSlot, const int lengthSlot);
     void finishDrawTexture();
     void accountForClear(SkXfermode::Mode mode);
 
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index de2c674..5d5961a 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -26,7 +26,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 Snapshot::Snapshot(): flags(0), previous(NULL), layer(NULL), fbo(0),
-        invisible(false), empty(false) {
+        invisible(false), empty(false), alpha(1.0f) {
 
     transform = &mTransformRoot;
     clipRect = &mClipRectRoot;
@@ -41,7 +41,7 @@
 Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags):
         flags(0), previous(s), layer(NULL), fbo(s->fbo),
         invisible(s->invisible), empty(false),
-        viewport(s->viewport), height(s->height) {
+        viewport(s->viewport), height(s->height), alpha(s->alpha) {
 
     clipRegion = NULL;
 
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index b2bc879..30b03fc 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -208,6 +208,17 @@
      */
     Region* region;
 
+    /**
+     * Current alpha value. This value is 1 by default, but may be set by a DisplayList which
+     * has translucent rendering in a non-overlapping View. This value will be used by
+     * the renderer to set the alpha in the current color being used for ensuing drawing
+     * operations. The value is inherited by child snapshots because the same value should
+     * be applied to descendents of the current DisplayList (for example, a TextView contains
+     * the base alpha value which should be applied to the child DisplayLists used for drawing
+     * the actual text).
+     */
+    float alpha;
+
 private:
     void ensureClipRegion();
     void copyClipRectFromRegion();
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 82dd308..c7e71eb 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -903,9 +903,18 @@
      * @hide
      */
     public void setMasterMute(boolean state) {
+        setMasterMute(state, FLAG_SHOW_UI);
+    }
+
+    /**
+     * set master mute state with optional flags.
+     *
+     * @hide
+     */
+    public void setMasterMute(boolean state, int flags) {
         IAudioService service = getService();
         try {
-            service.setMasterMute(state, mICallBack);
+            service.setMasterMute(state, flags, mICallBack);
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in setMasterMute", e);
         }
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index c66a03f..2e456f0 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -126,6 +126,7 @@
     private static final int MSG_RCDISPLAY_CLEAR = 13;
     private static final int MSG_RCDISPLAY_UPDATE = 14;
     private static final int MSG_SET_ALL_VOLUMES = 15;
+    private static final int MSG_PERSIST_MASTER_VOLUME_MUTE = 16;
 
 
     // flags for MSG_PERSIST_VOLUME indicating if current and/or last audible volume should be
@@ -501,6 +502,10 @@
                 System.MUTE_STREAMS_AFFECTED,
                 ((1 << AudioSystem.STREAM_MUSIC)|(1 << AudioSystem.STREAM_RING)|(1 << AudioSystem.STREAM_SYSTEM)));
 
+        boolean masterMute = System.getInt(cr, System.VOLUME_MASTER_MUTE, 0) == 1;
+        AudioSystem.setMasterMute(masterMute);
+        broadcastMasterMuteStatus(masterMute);
+
         // Each stream will read its own persisted settings
 
         // Broadcast the sticky intent
@@ -740,9 +745,14 @@
     // UI update and Broadcast Intent
     private void sendMasterMuteUpdate(boolean muted, int flags) {
         mVolumePanel.postMasterMuteChanged(flags);
+        broadcastMasterMuteStatus(muted);
+    }
 
+    private void broadcastMasterMuteStatus(boolean muted) {
         Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION);
         intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, muted);
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
+                | Intent.FLAG_RECEIVER_REPLACE_PENDING);
         long origCallerIdentityToken = Binder.clearCallingIdentity();
         mContext.sendStickyBroadcast(intent);
         Binder.restoreCallingIdentity(origCallerIdentityToken);
@@ -817,10 +827,13 @@
     }
 
     /** @see AudioManager#setMasterMute(boolean, IBinder) */
-    public void setMasterMute(boolean state, IBinder cb) {
+    public void setMasterMute(boolean state, int flags, IBinder cb) {
         if (state != AudioSystem.getMasterMute()) {
             AudioSystem.setMasterMute(state);
-            sendMasterMuteUpdate(state, AudioManager.FLAG_SHOW_UI);
+            // Post a persist master volume msg
+            sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, state ? 1
+                    : 0, 0, null, PERSIST_DELAY);
+            sendMasterMuteUpdate(state, flags);
         }
     }
 
@@ -2551,6 +2564,11 @@
                             (float)msg.arg1 / (float)1000.0);
                     break;
 
+                case MSG_PERSIST_MASTER_VOLUME_MUTE:
+                    Settings.System.putInt(mContentResolver, Settings.System.VOLUME_MASTER_MUTE,
+                            msg.arg1);
+                    break;
+
                 case MSG_PERSIST_RINGER_MODE:
                     // note that the value persisted is the current ringer mode, not the
                     // value of ringer mode as of the time the request was made to persist
@@ -3038,11 +3056,6 @@
                     adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener,
                                             BluetoothProfile.A2DP);
                 }
-
-                if (mUseMasterVolume) {
-                    // Send sticky broadcast for initial master mute state
-                    sendMasterMuteUpdate(false, 0);
-                }
             } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) {
                 if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
                     // a package is being removed, not replaced
diff --git a/media/java/android/media/Crypto.java b/media/java/android/media/Crypto.java
new file mode 100644
index 0000000..43e34fb
--- /dev/null
+++ b/media/java/android/media/Crypto.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+/**
+ * Crypto class can be used in conjunction with MediaCodec to decode
+ * encrypted media data.
+ * @hide
+*/
+public final class Crypto {
+    public static final native boolean isCryptoSchemeSupported(byte[] uuid);
+
+    public Crypto(byte[] uuid, byte[] initData) {
+        native_setup(uuid, initData);
+    }
+
+    public final native boolean requiresSecureDecoderComponent(String mime);
+
+    @Override
+    protected void finalize() {
+        native_finalize();
+    }
+
+    public native final void release();
+    private static native final void native_init();
+    private native final void native_setup(byte[] uuid, byte[] initData);
+    private native final void native_finalize();
+
+    static {
+        System.loadLibrary("media_jni");
+        native_init();
+    }
+
+    private int mNativeContext;
+}
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 17d8e4d..b775095 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -45,7 +45,7 @@
 
     boolean isStreamMute(int streamType);
 
-    void setMasterMute(boolean state, IBinder cb);
+    void setMasterMute(boolean state, int flags, IBinder cb);
 
     boolean isMasterMute();
 
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index d06e302..66cea9d4 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.media.Crypto;
 import android.view.Surface;
 import java.nio.ByteBuffer;
 import java.util.Map;
@@ -25,8 +26,7 @@
  * encoder/decoder components.
  * @hide
 */
-public class MediaCodec
-{
+final public class MediaCodec {
     /** Per buffer metadata includes an offset and size specifying
         the range of valid data in the associated codec buffer.
     */
@@ -83,7 +83,6 @@
     public native final void release();
 
     public static int CONFIGURE_FLAG_ENCODE = 1;
-    public static int CONFIGURE_FLAG_SECURE = 2;
 
     /** Configures a component.
      *  @param format A map of string/value pairs describing the input format
@@ -114,11 +113,14 @@
      *
      *  @param surface Specify a surface on which to render the output of this
      *                 decoder.
+     *  @param crypto  Specify a crypto object to facilitate secure decryption
+     *                 of the media data.
      *  @param flags   Specify {@link #CONFIGURE_FLAG_ENCODE} to configure the
      *                 component as an encoder.
     */
     public void configure(
-            Map<String, Object> format, Surface surface, int flags) {
+            Map<String, Object> format,
+            Surface surface, Crypto crypto, int flags) {
         String[] keys = null;
         Object[] values = null;
 
@@ -134,11 +136,12 @@
             }
         }
 
-        native_configure(keys, values, surface, flags);
+        native_configure(keys, values, surface, crypto, flags);
     }
 
     private native final void native_configure(
-            String[] keys, Object[] values, Surface surface, int flags);
+            String[] keys, Object[] values,
+            Surface surface, Crypto crypto, int flags);
 
     /** After successfully configuring the component, call start. On return
      *  you can query the component for its input/output buffers.
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 9ea3d0e..9c3b6a7 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -23,8 +23,7 @@
  * MediaExtractor
  * @hide
 */
-public class MediaExtractor
-{
+final public class MediaExtractor {
     public MediaExtractor(String path) {
         native_setup(path);
     }
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 2f4ed89..26089ad 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -609,6 +609,10 @@
                 mCompilation = parseSubstring(value, 0, 0);
             } else if (name.equalsIgnoreCase("isdrm")) {
                 mIsDrm = (parseSubstring(value, 0, 0) == 1);
+            } else if (name.equalsIgnoreCase("width")) {
+                mWidth = parseSubstring(value, 0, 0);
+            } else if (name.equalsIgnoreCase("height")) {
+                mHeight = parseSubstring(value, 0, 0);
             } else {
                 //Log.v(TAG, "unknown tag: " + name + " (" + mProcessGenres + ")");
             }
@@ -734,9 +738,11 @@
             map.put(MediaStore.MediaColumns.MIME_TYPE, mMimeType);
             map.put(MediaStore.MediaColumns.IS_DRM, mIsDrm);
 
+            String resolution = null;
             if (mWidth > 0 && mHeight > 0) {
                 map.put(MediaStore.MediaColumns.WIDTH, mWidth);
                 map.put(MediaStore.MediaColumns.HEIGHT, mHeight);
+                resolution = mWidth + "x" + mHeight;
             }
 
             if (!mNoMedia) {
@@ -746,7 +752,9 @@
                     map.put(Video.Media.ALBUM, (mAlbum != null && mAlbum.length() > 0
                             ? mAlbum : MediaStore.UNKNOWN_STRING));
                     map.put(Video.Media.DURATION, mDuration);
-                    // FIXME - add RESOLUTION
+                    if (resolution != null) {
+                        map.put(Video.Media.RESOLUTION, resolution);
+                    }
                 } else if (MediaFile.isImageFileType(mFileType)) {
                     // FIXME - add DESCRIPTION
                 } else if (MediaFile.isAudioFileType(mFileType)) {
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index dd1e505..a3361d4 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -2,6 +2,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
+    android_media_Crypto.cpp \
     android_media_MediaCodec.cpp \
     android_media_MediaCodecList.cpp \
     android_media_MediaExtractor.cpp \
diff --git a/media/jni/android_media_Crypto.cpp b/media/jni/android_media_Crypto.cpp
new file mode 100644
index 0000000..e1a60a1
--- /dev/null
+++ b/media/jni/android_media_Crypto.cpp
@@ -0,0 +1,291 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Crypto-JNI"
+#include <utils/Log.h>
+
+#include "android_media_Crypto.h"
+
+#include "android_runtime/AndroidRuntime.h"
+#include "jni.h"
+#include "JNIHelp.h"
+
+#include <binder/IServiceManager.h>
+#include <media/ICrypto.h>
+#include <media/IMediaPlayerService.h>
+#include <media/stagefright/foundation/ADebug.h>
+
+namespace android {
+
+struct fields_t {
+    jfieldID context;
+};
+
+static fields_t gFields;
+
+static sp<JCrypto> getCrypto(JNIEnv *env, jobject thiz) {
+    return (JCrypto *)env->GetIntField(thiz, gFields.context);
+}
+
+JCrypto::JCrypto(
+        JNIEnv *env, jobject thiz,
+        const uint8_t uuid[16], const void *initData, size_t initSize) {
+    mObject = env->NewWeakGlobalRef(thiz);
+
+    mCrypto = MakeCrypto(uuid, initData, initSize);
+}
+
+JCrypto::~JCrypto() {
+    mCrypto.clear();
+
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+
+    env->DeleteWeakGlobalRef(mObject);
+    mObject = NULL;
+}
+
+// static
+sp<ICrypto> JCrypto::MakeCrypto() {
+    sp<IServiceManager> sm = defaultServiceManager();
+
+    sp<IBinder> binder =
+        sm->getService(String16("media.player"));
+
+    sp<IMediaPlayerService> service =
+        interface_cast<IMediaPlayerService>(binder);
+
+    if (service == NULL) {
+        return NULL;
+    }
+
+    sp<ICrypto> crypto = service->makeCrypto();
+
+    if (crypto == NULL || crypto->initCheck() != OK) {
+        return NULL;
+    }
+
+    return crypto;
+}
+
+// static
+sp<ICrypto> JCrypto::MakeCrypto(
+        const uint8_t uuid[16], const void *initData, size_t initSize) {
+    sp<ICrypto> crypto = MakeCrypto();
+
+    if (crypto == NULL) {
+        return NULL;
+    }
+
+    status_t err = crypto->createPlugin(uuid, initData, initSize);
+
+    if (err != OK) {
+        return NULL;
+    }
+
+    return crypto;
+}
+
+bool JCrypto::requiresSecureDecoderComponent(const char *mime) const {
+    if (mCrypto == NULL) {
+        return false;
+    }
+
+    return mCrypto->requiresSecureDecoderComponent(mime);
+}
+
+// static
+bool JCrypto::IsCryptoSchemeSupported(const uint8_t uuid[16]) {
+    sp<ICrypto> crypto = MakeCrypto();
+
+    if (crypto == NULL) {
+        return false;
+    }
+
+    return crypto->isCryptoSchemeSupported(uuid);
+}
+
+status_t JCrypto::initCheck() const {
+    return mCrypto == NULL ? NO_INIT : OK;
+}
+
+// static
+sp<ICrypto> JCrypto::GetCrypto(JNIEnv *env, jobject obj) {
+    jclass clazz = env->FindClass("android/media/Crypto");
+    CHECK(clazz != NULL);
+
+    if (!env->IsInstanceOf(obj, clazz)) {
+        return NULL;
+    }
+
+    sp<JCrypto> jcrypto = getCrypto(env, obj);
+
+    if (jcrypto == NULL) {
+        return NULL;
+    }
+
+    return jcrypto->mCrypto;
+}
+
+}  // namespace android
+
+using namespace android;
+
+static sp<JCrypto> setCrypto(
+        JNIEnv *env, jobject thiz, const sp<JCrypto> &crypto) {
+    sp<JCrypto> old = (JCrypto *)env->GetIntField(thiz, gFields.context);
+    if (crypto != NULL) {
+        crypto->incStrong(thiz);
+    }
+    if (old != NULL) {
+        old->decStrong(thiz);
+    }
+    env->SetIntField(thiz, gFields.context, (int)crypto.get());
+
+    return old;
+}
+
+static void android_media_Crypto_release(JNIEnv *env, jobject thiz) {
+    setCrypto(env, thiz, NULL);
+}
+
+static void android_media_Crypto_native_init(JNIEnv *env) {
+    jclass clazz = env->FindClass("android/media/Crypto");
+    CHECK(clazz != NULL);
+
+    gFields.context = env->GetFieldID(clazz, "mNativeContext", "I");
+    CHECK(gFields.context != NULL);
+}
+
+static void android_media_Crypto_native_setup(
+        JNIEnv *env, jobject thiz,
+        jbyteArray uuidObj, jbyteArray initDataObj) {
+    jsize uuidLength = env->GetArrayLength(uuidObj);
+
+    if (uuidLength != 16) {
+        jniThrowException(
+                env,
+                "java/lang/IllegalArgumentException",
+                NULL);
+        return;
+    }
+
+    jboolean isCopy;
+    jbyte *uuid = env->GetByteArrayElements(uuidObj, &isCopy);
+
+    jsize initDataLength = env->GetArrayLength(initDataObj);
+    jbyte *initData = env->GetByteArrayElements(initDataObj, &isCopy);
+
+    sp<JCrypto> crypto = new JCrypto(
+            env, thiz, (const uint8_t *)uuid, initData, initDataLength);
+
+    status_t err = crypto->initCheck();
+
+    env->ReleaseByteArrayElements(initDataObj, initData, 0);
+    initData = NULL;
+
+    env->ReleaseByteArrayElements(uuidObj, uuid, 0);
+    uuid = NULL;
+
+    if (err != OK) {
+        jniThrowException(
+                env,
+                "java/io/IOException",
+                "Failed to instantiate crypto object.");
+        return;
+    }
+
+    setCrypto(env,thiz, crypto);
+}
+
+static void android_media_Crypto_native_finalize(
+        JNIEnv *env, jobject thiz) {
+    android_media_Crypto_release(env, thiz);
+}
+
+static jboolean android_media_Crypto_isCryptoSchemeSupported(
+        JNIEnv *env, jobject thiz, jbyteArray uuidObj) {
+    jsize uuidLength = env->GetArrayLength(uuidObj);
+
+    if (uuidLength != 16) {
+        jniThrowException(
+                env,
+                "java/lang/IllegalArgumentException",
+                NULL);
+        return false;
+    }
+
+    jboolean isCopy;
+    jbyte *uuid = env->GetByteArrayElements(uuidObj, &isCopy);
+
+    bool result = JCrypto::IsCryptoSchemeSupported((const uint8_t *)uuid);
+
+    env->ReleaseByteArrayElements(uuidObj, uuid, 0);
+    uuid = NULL;
+
+    return result;
+}
+
+static jboolean android_media_Crypto_requiresSecureDecoderComponent(
+        JNIEnv *env, jobject thiz, jstring mimeObj) {
+    if (mimeObj == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return false;
+    }
+
+    sp<JCrypto> crypto = getCrypto(env, thiz);
+
+    if (crypto == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return false;
+    }
+
+    const char *mime = env->GetStringUTFChars(mimeObj, NULL);
+
+    if (mime == NULL) {
+        return false;
+    }
+
+    bool result = crypto->requiresSecureDecoderComponent(mime);
+
+    env->ReleaseStringUTFChars(mimeObj, mime);
+    mime = NULL;
+
+    return result;
+}
+
+static JNINativeMethod gMethods[] = {
+    { "release", "()V", (void *)android_media_Crypto_release },
+    { "native_init", "()V", (void *)android_media_Crypto_native_init },
+
+    { "native_setup", "([B[B)V",
+      (void *)android_media_Crypto_native_setup },
+
+    { "native_finalize", "()V",
+      (void *)android_media_Crypto_native_finalize },
+
+    { "isCryptoSchemeSupported", "([B)Z",
+      (void *)android_media_Crypto_isCryptoSchemeSupported },
+
+    { "requiresSecureDecoderComponent", "(Ljava/lang/String;)Z",
+      (void *)android_media_Crypto_requiresSecureDecoderComponent },
+};
+
+int register_android_media_Crypto(JNIEnv *env) {
+    return AndroidRuntime::registerNativeMethods(env,
+                "android/media/Crypto", gMethods, NELEM(gMethods));
+}
+
diff --git a/media/jni/android_media_Crypto.h b/media/jni/android_media_Crypto.h
new file mode 100644
index 0000000..505725e
--- /dev/null
+++ b/media/jni/android_media_Crypto.h
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#ifndef _ANDROID_MEDIA_CRYPTO_H_
+#define _ANDROID_MEDIA_CRYPTO_H_
+
+#include "jni.h"
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct ICrypto;
+
+struct JCrypto : public RefBase {
+    static bool IsCryptoSchemeSupported(const uint8_t uuid[16]);
+
+    JCrypto(JNIEnv *env, jobject thiz,
+            const uint8_t uuid[16], const void *initData, size_t initSize);
+
+    status_t initCheck() const;
+
+    bool requiresSecureDecoderComponent(const char *mime) const;
+
+    static sp<ICrypto> GetCrypto(JNIEnv *env, jobject obj);
+
+protected:
+    virtual ~JCrypto();
+
+private:
+    jweak mObject;
+    sp<ICrypto> mCrypto;
+
+    static sp<ICrypto> MakeCrypto();
+
+    static sp<ICrypto> MakeCrypto(
+            const uint8_t uuid[16], const void *initData, size_t initSize);
+
+    DISALLOW_EVIL_CONSTRUCTORS(JCrypto);
+};
+
+}  // namespace android
+
+#endif  // _ANDROID_MEDIA_CRYPTO_H_
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 04d7c22..217216a 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -20,6 +20,7 @@
 
 #include "android_media_MediaCodec.h"
 
+#include "android_media_Crypto.h"
 #include "android_media_Utils.h"
 #include "android_runtime/AndroidRuntime.h"
 #include "android_runtime/android_view_Surface.h"
@@ -29,6 +30,7 @@
 #include <gui/Surface.h>
 #include <gui/SurfaceTextureClient.h>
 
+#include <media/ICrypto.h>
 #include <media/stagefright/MediaCodec.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -97,12 +99,13 @@
 status_t JMediaCodec::configure(
         const sp<AMessage> &format,
         const sp<ISurfaceTexture> &surfaceTexture,
+        const sp<ICrypto> &crypto,
         int flags) {
     sp<SurfaceTextureClient> client;
     if (surfaceTexture != NULL) {
         client = new SurfaceTextureClient(surfaceTexture);
     }
-    return mCodec->configure(format, client, flags);
+    return mCodec->configure(format, client, crypto, flags);
 }
 
 status_t JMediaCodec::start() {
@@ -255,6 +258,7 @@
         jobject thiz,
         jobjectArray keys, jobjectArray values,
         jobject jsurface,
+        jobject jcrypto,
         jint flags) {
     sp<JMediaCodec> codec = getMediaCodec(env, thiz);
 
@@ -285,7 +289,12 @@
         }
     }
 
-    err = codec->configure(format, surfaceTexture, flags);
+    sp<ICrypto> crypto;
+    if (jcrypto != NULL) {
+        crypto = JCrypto::GetCrypto(env, jcrypto);
+    }
+
+    err = codec->configure(format, surfaceTexture, crypto, flags);
 
     throwExceptionAsNecessary(env, err);
 }
@@ -387,7 +396,7 @@
 
     if (codec == NULL) {
         jniThrowException(env, "java/lang/IllegalStateException", NULL);
-        return NULL;
+        return 0;
     }
 
     size_t index;
@@ -512,7 +521,8 @@
     { "release", "()V", (void *)android_media_MediaCodec_release },
 
     { "native_configure",
-      "([Ljava/lang/String;[Ljava/lang/Object;Landroid/view/Surface;I)V",
+      "([Ljava/lang/String;[Ljava/lang/Object;Landroid/view/Surface;"
+      "Landroid/media/Crypto;I)V",
       (void *)android_media_MediaCodec_native_configure },
 
     { "start", "()V", (void *)android_media_MediaCodec_start },
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index 6b1257d..6bb4071 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -27,6 +27,7 @@
 
 struct ALooper;
 struct AMessage;
+struct ICrypto;
 struct ISurfaceTexture;
 struct MediaCodec;
 
@@ -40,6 +41,7 @@
     status_t configure(
             const sp<AMessage> &format,
             const sp<ISurfaceTexture> &surfaceTexture,
+            const sp<ICrypto> &crypto,
             int flags);
 
     status_t start();
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 3074bb1..2e74ffd 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -879,6 +879,7 @@
                 "android/media/MediaPlayer", gMethods, NELEM(gMethods));
 }
 
+extern int register_android_media_Crypto(JNIEnv *env);
 extern int register_android_media_MediaCodec(JNIEnv *env);
 extern int register_android_media_MediaExtractor(JNIEnv *env);
 extern int register_android_media_MediaCodecList(JNIEnv *env);
@@ -968,6 +969,11 @@
         goto bail;
     }
 
+    if (register_android_media_Crypto(env) < 0) {
+        ALOGE("ERROR: MediaCodec native registration failed");
+        goto bail;
+    }
+
     /* success -- return valid version number */
     result = JNI_VERSION_1_4;
 
diff --git a/media/tests/MediaFrameworkTest/AndroidManifest.xml b/media/tests/MediaFrameworkTest/AndroidManifest.xml
index dd5e026..b698705 100644
--- a/media/tests/MediaFrameworkTest/AndroidManifest.xml
+++ b/media/tests/MediaFrameworkTest/AndroidManifest.xml
@@ -4,9 +4,9 @@
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
      You may obtain a copy of the License at
-  
+
           http://www.apache.org/licenses/LICENSE-2.0
-  
+
      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -16,7 +16,7 @@
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.mediaframeworktest">
-    
+
     <uses-permission android:name="android.permission.RECORD_AUDIO" />
     <uses-permission android:name="android.permission.CAMERA" />
     <uses-permission android:name="android.permission.INTERNET" />
@@ -24,7 +24,7 @@
     <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
     <uses-permission android:name="android.permission.WAKE_LOCK" />
 
-    <application>    
+    <application>
         <uses-library android:name="android.test.runner" />
         <activity android:label="@string/app_name"
                 android:name="MediaFrameworkTest"
@@ -34,12 +34,18 @@
                 <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
-    </application>   
+    </application>
+
+    <instrumentation android:name=".CameraStressTestRunner"
+        android:targetPackage="com.android.mediaframeworktest"
+        android:label="Camera stress tests InstrumentationRunner">
+    </instrumentation>
+
     <instrumentation android:name=".MediaFrameworkTestRunner"
          android:targetPackage="com.android.mediaframeworktest"
          android:label="MediaFramework tests InstrumentationRunner">
      </instrumentation>
-     
+
       <instrumentation android:name=".MediaFrameworkPerfTestRunner"
          android:targetPackage="com.android.mediaframeworktest"
          android:label="MediaFramework Performance tests InstrumentationRunner">
@@ -49,7 +55,7 @@
          android:targetPackage="com.android.mediaframeworktest"
          android:label="MediaFramework unit tests InstrumentationRunner">
      </instrumentation>
-     
+
      <instrumentation android:name=".MediaRecorderStressTestRunner"
          android:targetPackage="com.android.mediaframeworktest"
          android:label="MediaRecorder stress tests InstrumentationRunner">
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/CameraStressTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/CameraStressTestRunner.java
new file mode 100644
index 0000000..fa59fa4
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/CameraStressTestRunner.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest;
+
+import android.test.InstrumentationTestRunner;
+import android.test.InstrumentationTestSuite;
+import com.android.mediaframeworktest.stress.CameraStressTest;
+
+import junit.framework.TestSuite;
+
+public class CameraStressTestRunner extends InstrumentationTestRunner {
+
+    @Override
+    public TestSuite getAllTests() {
+        TestSuite suite = new InstrumentationTestSuite(this);
+        suite.addTestSuite(CameraStressTest.class);
+        return suite;
+    }
+
+    @Override
+    public ClassLoader getLoader() {
+        return CameraStressTestRunner.class.getClassLoader();
+    }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediaplayback/MediaPlayerApiTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediaplayback/MediaPlayerApiTest.java
index c501d3f..7be2707 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediaplayback/MediaPlayerApiTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/mediaplayback/MediaPlayerApiTest.java
@@ -22,7 +22,7 @@
 import com.android.mediaframeworktest.functional.CodecTest;
 
 import android.content.Context;
-import android.test.ActivityInstrumentationTestCase;
+import android.test.ActivityInstrumentationTestCase2;
 import android.util.Log;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.MediumTest;
@@ -33,25 +33,28 @@
 /**
  * Junit / Instrumentation test case for the media player api
  */
-public class MediaPlayerApiTest extends ActivityInstrumentationTestCase<MediaFrameworkTest> {
-   private boolean duratoinWithinTolerence = false;
-   private String TAG = "MediaPlayerApiTest";
-   private boolean isWMAEnable = false;
-   private boolean isWMVEnable = false;
+public class MediaPlayerApiTest extends  ActivityInstrumentationTestCase2<MediaFrameworkTest> {
+    private boolean duratoinWithinTolerence = false;
+    private String TAG = "MediaPlayerApiTest";
+    private boolean isWMAEnable = false;
+    private boolean isWMVEnable = false;
 
-   Context mContext;
+    Context mContext;
 
-   public MediaPlayerApiTest() {
-     super("com.android.mediaframeworktest", MediaFrameworkTest.class);
-     isWMAEnable = MediaProfileReader.getWMAEnable();
-     isWMVEnable = MediaProfileReader.getWMVEnable();
-   }
+    public MediaPlayerApiTest() {
+       super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+       isWMAEnable = MediaProfileReader.getWMAEnable();
+       isWMVEnable = MediaProfileReader.getWMVEnable();
+    }
 
     protected void setUp() throws Exception {
-      super.setUp();
-   
-  }
-    
+       //Insert a 2 second before launching the test activity. This is
+       //the workaround for the race condition of requesting the updated surface.
+       Thread.sleep(2000);
+       getActivity();
+       super.setUp();
+    }
+
     public boolean verifyDuration(int duration, int expectedDuration){
       if ((duration > expectedDuration * 1.1) || (duration < expectedDuration * 0.9))
          return false;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/CameraStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/CameraStressTest.java
new file mode 100644
index 0000000..a9c6119
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/CameraStressTest.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.stress;
+
+import com.android.mediaframeworktest.MediaFrameworkTest;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.FileWriter;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import android.hardware.Camera;
+import android.hardware.Camera.PictureCallback;
+import android.hardware.Camera.ShutterCallback;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.Looper;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import com.android.mediaframeworktest.CameraStressTestRunner;
+
+import junit.framework.Assert;
+
+/**
+ * Junit / Instrumentation test case for the camera zoom api
+ *
+ * adb shell am instrument
+ *  -e class com.android.mediaframeworktest.stress.CameraStressTest
+ *  -w com.android.mediaframeworktest/.CameraStressTestRunner
+ */
+public class CameraStressTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
+    private String TAG = "CameraStressTest";
+    private Camera mCamera;
+
+    private static final int NUMBER_OF_ZOOM_LOOPS = 100;
+    private static final long WAIT_GENERIC = 3 * 1000; // 3 seconds
+    private static final long WAIT_TIMEOUT = 10 * 1000; // 10 seconds
+    private static final long WAIT_ZOOM_ANIMATION = 5 * 1000; // 5 seconds
+    private static final String CAMERA_STRESS_OUTPUT =
+            "/sdcard/cameraStressOutput.txt";
+    private final CameraErrorCallback mCameraErrorCallback = new CameraErrorCallback();
+
+    private Thread mLooperThread;
+    private Handler mHandler;
+
+    public CameraStressTest() {
+        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+    }
+
+    protected void setUp() throws Exception {
+        final Semaphore sem = new Semaphore(0);
+        mLooperThread = new Thread() {
+            @Override
+            public void run() {
+                Log.v(TAG, "starting looper");
+                Looper.prepare();
+                mHandler = new Handler();
+                sem.release();
+                Looper.loop();
+                Log.v(TAG, "quit looper");
+            }
+        };
+        mLooperThread.start();
+        if (!sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
+            fail("Failed to start the looper.");
+        }
+        getActivity();
+        super.setUp();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mHandler != null) {
+            mHandler.getLooper().quit();
+            mHandler = null;
+        }
+        if (mLooperThread != null) {
+            mLooperThread.join(WAIT_TIMEOUT);
+            if (mLooperThread.isAlive()) {
+                fail("Failed to stop the looper.");
+            }
+            mLooperThread = null;
+        }
+
+        super.tearDown();
+    }
+
+    private void runOnLooper(final Runnable command) throws InterruptedException {
+        final Semaphore sem = new Semaphore(0);
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    command.run();
+                } finally {
+                    sem.release();
+                }
+            }
+        });
+        if (!sem.tryAcquire(WAIT_TIMEOUT, TimeUnit.MILLISECONDS)) {
+            fail("Failed to run the command on the looper.");
+        }
+    }
+
+    private final class CameraErrorCallback implements android.hardware.Camera.ErrorCallback {
+        public void onError(int error, android.hardware.Camera camera) {
+            if (error == android.hardware.Camera.CAMERA_ERROR_SERVER_DIED) {
+                assertTrue("Camera test mediaserver died", false);
+            }
+        }
+    }
+
+    private ShutterCallback shutterCallback = new ShutterCallback() {
+        @Override
+        public void onShutter() {
+            Log.v(TAG, "Shutter");
+        }
+    };
+
+    private PictureCallback rawCallback = new PictureCallback() {
+        @Override
+        public void onPictureTaken(byte[] data, Camera camera) {
+            Log.v(TAG, "Raw picture taken");
+        }
+    };
+
+    private PictureCallback jpegCallback = new PictureCallback() {
+        @Override
+        public void onPictureTaken(byte[] data, Camera camera) {
+            FileOutputStream fos = null;
+
+            try {
+                Log.v(TAG, "JPEG picture taken");
+                fos = new FileOutputStream(String.format("%s/zoom-test-%d.jpg",
+                        Environment.getExternalStorageDirectory(), System.currentTimeMillis()));
+                fos.write(data);
+            }
+            catch (FileNotFoundException e) {
+                Log.v(TAG, "File not found: " + e.toString());
+            }
+            catch (IOException e) {
+                Log.v(TAG, "Error accessing file: " + e.toString());
+            }
+            finally {
+                try {
+                    if (fos != null) {
+                        fos.close();
+                    }
+                }
+                catch (IOException e) {
+                    Log.v(TAG, "Error closing file: " + e.toString());
+                }
+            }
+        }
+    };
+
+    // Helper method for cleaning up pics taken during testStressCameraZoom
+    private void cleanupZoomImages() {
+        try {
+            File sdcard = Environment.getExternalStorageDirectory();
+            File[] zoomImages = null;
+
+            FilenameFilter filter = new FilenameFilter() {
+                public boolean accept(File dir, String name) {
+                    return name.startsWith("zoom-test-");
+                }
+            };
+
+            zoomImages = sdcard.listFiles(filter);
+
+            for (File f : zoomImages) {
+                f.delete();
+            }
+        }
+        catch (SecurityException e) {
+            Log.v(TAG, "Security manager access violation: " + e.toString());
+        }
+    }
+
+    // Test case for stressing the camera zoom in/out feature
+    @LargeTest
+    public void testStressCameraZoom() throws Exception {
+        SurfaceHolder mSurfaceHolder;
+        mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+        File stressOutFile = new File(CAMERA_STRESS_OUTPUT);
+        Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
+        output.write("Camera zoom stress:\n");
+        output.write("Total number of loops: " +  NUMBER_OF_ZOOM_LOOPS + "\n");
+
+        try {
+            Log.v(TAG, "Start preview");
+            output.write("No of loop: ");
+
+            mCamera = Camera.open();
+            Camera.Parameters params = mCamera.getParameters();
+            mCamera.release();
+
+            if (!params.isSmoothZoomSupported() && !params.isZoomSupported()) {
+                Log.v(TAG, "Device camera does not support zoom");
+                assertTrue("Camera zoom stress test", false);
+            }
+            else {
+                Log.v(TAG, "Device camera does support zoom");
+
+                int nextZoomLevel = 0;
+
+                for (int i = 0; i < NUMBER_OF_ZOOM_LOOPS; i++) {
+                    runOnLooper(new Runnable() {
+                        @Override
+                        public void run() {
+                            mCamera = Camera.open();
+                        }
+                    });
+
+                    mCamera.setErrorCallback(mCameraErrorCallback);
+                    mCamera.setPreviewDisplay(mSurfaceHolder);
+                    mCamera.startPreview();
+                    Thread.sleep(WAIT_GENERIC);
+
+                    params = mCamera.getParameters();
+                    int currentZoomLevel = params.getZoom();
+
+                    if (nextZoomLevel >= params.getMaxZoom()) {
+                        nextZoomLevel = 0;
+                    }
+                    ++nextZoomLevel;
+
+                    if (params.isSmoothZoomSupported()) {
+                        mCamera.startSmoothZoom(nextZoomLevel);
+                    }
+                    else {
+                        params.setZoom(nextZoomLevel);
+                        mCamera.setParameters(params);
+                    }
+                    Log.v(TAG, "Zooming from " + currentZoomLevel + " to " + nextZoomLevel);
+
+                    // sleep allows for zoom animation to finish
+                    Thread.sleep(WAIT_ZOOM_ANIMATION);
+
+                    // take picture
+                    mCamera.takePicture(shutterCallback, rawCallback, jpegCallback);
+                    Thread.sleep(WAIT_GENERIC);
+                    mCamera.stopPreview();
+                    mCamera.release();
+                    output.write(" ," + i);
+                }
+            }
+
+            cleanupZoomImages();
+        }
+        catch (Exception e) {
+            assertTrue("Camera zoom stress test Exception", false);
+            Log.v(TAG, e.toString());
+        }
+        output.write("\n\n");
+        output.close();
+    }
+}
diff --git a/packages/InputDevices/Android.mk b/packages/InputDevices/Android.mk
new file mode 100644
index 0000000..446b47e
--- /dev/null
+++ b/packages/InputDevices/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_JAVA_LIBRARIES := 
+
+LOCAL_PACKAGE_NAME := InputDevices
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
+
+########################
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/InputDevices/AndroidManifest.xml b/packages/InputDevices/AndroidManifest.xml
new file mode 100644
index 0000000..6831a74
--- /dev/null
+++ b/packages/InputDevices/AndroidManifest.xml
@@ -0,0 +1,19 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.inputdevices"
+        coreApp="true"
+        android:sharedUserId="android.uid.system">
+
+    <application
+            android:allowClearUserData="false"
+            android:label="@string/app_label"
+            android:process="system">
+
+        <receiver android:name=".InputDeviceReceiver">
+            <intent-filter>
+                <action android:name="android.hardware.input.action.QUERY_KEYBOARD_LAYOUTS" />
+            </intent-filter>
+            <meta-data android:name="android.hardware.input.metadata.KEYBOARD_LAYOUTS"
+                    android:resource="@xml/keyboard_layouts" />
+        </receiver>
+    </application>
+</manifest>
diff --git a/packages/InputDevices/MODULE_LICENSE_APACHE2 b/packages/InputDevices/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/packages/InputDevices/MODULE_LICENSE_APACHE2
diff --git a/packages/InputDevices/NOTICE b/packages/InputDevices/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/packages/InputDevices/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-2008, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/packages/InputDevices/res/raw/keyboard_layout_english_us.kcm b/packages/InputDevices/res/raw/keyboard_layout_english_us.kcm
new file mode 100644
index 0000000..a7823fd
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_english_us.kcm
@@ -0,0 +1,15 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# PLACEHOLDER CONTENT #
diff --git a/packages/InputDevices/res/raw/keyboard_layout_english_us_dvorak.kcm b/packages/InputDevices/res/raw/keyboard_layout_english_us_dvorak.kcm
new file mode 100644
index 0000000..a7823fd
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_english_us_dvorak.kcm
@@ -0,0 +1,15 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# PLACEHOLDER CONTENT #
diff --git a/packages/InputDevices/res/raw/keyboard_layout_german.kcm b/packages/InputDevices/res/raw/keyboard_layout_german.kcm
new file mode 100644
index 0000000..a7823fd
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_german.kcm
@@ -0,0 +1,15 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# PLACEHOLDER CONTENT #
diff --git a/packages/InputDevices/res/values/strings.xml b/packages/InputDevices/res/values/strings.xml
new file mode 100644
index 0000000..6d5ee98
--- /dev/null
+++ b/packages/InputDevices/res/values/strings.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <!-- Name of the application. [CHAR LIMIT=35] -->
+    <string name="app_label">Input Devices</string>
+
+    <!-- US English keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_english_us_label">English (US)</string>
+
+    <!-- US English (Dvorak style) keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_english_us_dvorak_label">English (US), Dvorak</string>
+
+    <!-- German keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_german_label">German</string>
+</resources>
diff --git a/packages/InputDevices/res/xml/keyboard_layouts.xml b/packages/InputDevices/res/xml/keyboard_layouts.xml
new file mode 100644
index 0000000..459a0e4
--- /dev/null
+++ b/packages/InputDevices/res/xml/keyboard_layouts.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<keyboard-layouts xmlns:android="http://schemas.android.com/apk/res/android">
+    <keyboard-layout android:name="keyboard_layout_english_us"
+            android:label="@string/keyboard_layout_english_us_label"
+            android:kcm="@raw/keyboard_layout_english_us" />
+
+    <keyboard-layout android:name="keyboard_layout_english_us_dvorak"
+            android:label="@string/keyboard_layout_english_us_dvorak_label"
+            android:kcm="@raw/keyboard_layout_english_us_dvorak" />
+
+    <keyboard-layout android:name="keyboard_layout_german"
+            android:label="@string/keyboard_layout_german_label"
+            android:kcm="@raw/keyboard_layout_german" />
+</keyboard-layouts>
diff --git a/packages/InputDevices/src/com/android/inputdevices/InputDeviceReceiver.java b/packages/InputDevices/src/com/android/inputdevices/InputDeviceReceiver.java
new file mode 100644
index 0000000..50a7c2f
--- /dev/null
+++ b/packages/InputDevices/src/com/android/inputdevices/InputDeviceReceiver.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputdevices;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class InputDeviceReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        // Nothing to do at this time.
+    }
+}
diff --git a/packages/SystemUI/res/anim/status_bar_in.xml b/packages/SystemUI/res/anim/status_bar_in.xml
deleted file mode 100644
index 79fe5f1..0000000
--- a/packages/SystemUI/res/anim/status_bar_in.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-    >
-    <translate android:fromYDelta="100%p" android:toYDelta="0"
-        android:duration="@android:integer/config_longAnimTime" 
-        android:interpolator="@anim/hydraulic_brake_interpolator"
-        />
-    <alpha android:fromAlpha="0.5" android:toAlpha="1.0"
-        android:duration="@android:integer/config_longAnimTime" 
-        />
-</set>
diff --git a/packages/SystemUI/res/anim/status_bar_out.xml b/packages/SystemUI/res/anim/status_bar_out.xml
deleted file mode 100644
index 80863cf..0000000
--- a/packages/SystemUI/res/anim/status_bar_out.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-    >
-    <translate android:toYDelta="100%p" android:fromYDelta="0"
-        android:duration="@android:integer/config_longAnimTime" 
-        android:interpolator="@anim/hydraulic_brake_interpolator"
-        />
-    <alpha android:toAlpha="0.5" android:fromAlpha="1.0"
-        android:duration="@android:integer/config_longAnimTime" 
-        />
-</set>
diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
index aa27861..715ccba 100644
--- a/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_recent_item.xml
@@ -66,7 +66,7 @@
             android:layout_height="wrap_content"
             android:textSize="@dimen/status_bar_recents_app_label_text_size"
             android:fadingEdge="horizontal"
-            android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length"
+            android:fadingEdgeLength="@dimen/status_bar_recents_text_fading_edge_length"
             android:scrollHorizontally="true"
             android:layout_alignLeft="@id/app_thumbnail"
             android:layout_below="@id/app_thumbnail"
@@ -82,7 +82,7 @@
             android:layout_height="wrap_content"
             android:textSize="@dimen/status_bar_recents_app_description_text_size"
             android:fadingEdge="horizontal"
-            android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length"
+            android:fadingEdgeLength="@dimen/status_bar_recents_text_fading_edge_length"
             android:scrollHorizontally="true"
             android:layout_alignLeft="@id/app_thumbnail"
             android:layout_below="@id/app_label"
diff --git a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
index 180f022..dba1dd9 100644
--- a/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_recent_panel.xml
@@ -41,7 +41,7 @@
             android:stackFromBottom="true"
             android:fadingEdge="horizontal"
             android:scrollbars="none"
-            android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length"
+            android:fadingEdgeLength="@dimen/status_bar_recents_scroll_fading_edge_length"
             android:layout_gravity="bottom|left"
             android:orientation="horizontal"
             android:clipToPadding="false"
diff --git a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml b/packages/SystemUI/res/layout-port/status_bar_recent_item.xml
index bc389f9..ca72530 100644
--- a/packages/SystemUI/res/layout-port/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-port/status_bar_recent_item.xml
@@ -35,7 +35,7 @@
             android:layout_height="wrap_content"
             android:textSize="@dimen/status_bar_recents_app_label_text_size"
             android:fadingEdge="horizontal"
-            android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length"
+            android:fadingEdgeLength="@dimen/status_bar_recents_text_fading_edge_length"
             android:scrollHorizontally="true"
             android:layout_alignParentLeft="true"
             android:layout_alignTop="@id/app_icon"
@@ -89,7 +89,7 @@
             android:layout_height="wrap_content"
             android:textSize="@dimen/status_bar_recents_app_description_text_size"
             android:fadingEdge="horizontal"
-            android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length"
+            android:fadingEdgeLength="@dimen/status_bar_recents_text_fading_edge_length"
             android:scrollHorizontally="true"
             android:layout_alignParentLeft="true"
             android:layout_marginLeft="@dimen/status_bar_recents_app_label_left_margin"
diff --git a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
index e6a077a..73c3da5 100644
--- a/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
+++ b/packages/SystemUI/res/layout-port/status_bar_recent_panel.xml
@@ -40,7 +40,7 @@
             android:stackFromBottom="true"
             android:fadingEdge="vertical"
             android:scrollbars="none"
-            android:fadingEdgeLength="@*android:dimen/status_bar_height"
+            android:fadingEdgeLength="@dimen/status_bar_recents_scroll_fading_edge_length"
             android:layout_gravity="bottom|left"
             android:clipToPadding="false"
             android:clipChildren="false">
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml
index 333fcda..7d639ec 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_recent_item.xml
@@ -28,7 +28,7 @@
         android:layout_height="wrap_content"
         android:textSize="@dimen/status_bar_recents_app_label_text_size"
         android:fadingEdge="horizontal"
-        android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length"
+        android:fadingEdgeLength="@dimen/status_bar_recents_text_fading_edge_length"
         android:scrollHorizontally="true"
         android:layout_alignParentLeft="true"
         android:layout_alignParentTop="true"
@@ -86,7 +86,7 @@
         android:layout_height="wrap_content"
         android:textSize="@dimen/status_bar_recents_app_description_text_size"
         android:fadingEdge="horizontal"
-        android:fadingEdgeLength="@dimen/status_bar_recents_fading_edge_length"
+        android:fadingEdgeLength="@dimen/status_bar_recents_text_fading_edge_length"
         android:scrollHorizontally="true"
         android:layout_alignParentLeft="true"
         android:layout_below="@id/recents_callout_line"
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index ba1cdfa..8c1ac55 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -53,8 +53,10 @@
     <dimen name="status_bar_recents_app_label_width">97dip</dimen>
     <!-- Left margin for application label -->
     <dimen name="status_bar_recents_app_label_left_margin">16dip</dimen>
-    <!-- Size of fading edge for scroll effect -->
-    <dimen name="status_bar_recents_fading_edge_length">20dip</dimen>
+    <!-- Size of fading edge for text -->
+    <dimen name="status_bar_recents_text_fading_edge_length">20dip</dimen>
+    <!-- Size of fading edge for scrolling -->
+    <dimen name="status_bar_recents_scroll_fading_edge_length">10dip</dimen>
     <!-- Margin between recents container and glow on the right -->
     <dimen name="status_bar_recents_right_glow_margin">100dip</dimen>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 2c22e3c..4441ca6 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -33,8 +33,10 @@
     <dimen name="status_bar_recents_app_label_text_size">14dip</dimen>
     <!-- Size of application description text -->
     <dimen name="status_bar_recents_app_description_text_size">14dip</dimen>
-    <!-- Size of fading edge for scroll effect -->
-    <dimen name="status_bar_recents_fading_edge_length">20dip</dimen>
+    <!-- Size of fading edge for text -->
+    <dimen name="status_bar_recents_text_fading_edge_length">20dip</dimen>
+    <!-- Size of fading edge for scrolling -->
+    <dimen name="status_bar_recents_scroll_fading_edge_length">10dip</dimen>
     <!-- Margin between recents container and glow on the right -->
     <dimen name="status_bar_recents_right_glow_margin">100dip</dimen>
     <!-- Amount to offset bottom of notification peek window from top of status bar. -->
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index dc5c540..02411d4 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -67,8 +67,6 @@
 
     <!-- Standard animations for hiding and showing the status bar. -->
     <style name="Animation.StatusBar">
-        <item name="android:windowEnterAnimation">@anim/status_bar_enter</item>
-        <item name="android:windowExitAnimation">@anim/status_bar_exit</item>
     </style>
 
     <style name="Animation.StatusBar.IntruderAlert">
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index d7a5056..1ae15be 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -69,9 +69,9 @@
         IWindowManager wm = IWindowManager.Stub.asInterface(
                 ServiceManager.getService(Context.WINDOW_SERVICE));
         try {
-            SERVICES[0] = wm.canStatusBarHide()
-                    ? R.string.config_statusBarComponent
-                    : R.string.config_systemBarComponent;
+            SERVICES[0] = wm.hasSystemNavBar()
+                    ? R.string.config_systemBarComponent
+                    : R.string.config_statusBarComponent;
         } catch (RemoteException e) {
             Slog.w(TAG, "Failing checking whether status bar can hide", e);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index ebed522..5d6e315 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -68,6 +68,7 @@
     static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG || false;
     private Context mContext;
     private BaseStatusBar mBar;
+    private PopupMenu mPopup;
     private View mRecentsScrim;
     private View mRecentsNoApps;
     private ViewGroup mRecentsContainer;
@@ -313,6 +314,10 @@
             setFocusable(true);
             setFocusableInTouchMode(true);
             requestFocus();
+        } else {
+            if (mPopup != null) {
+                mPopup.dismiss();
+            }
         }
     }
 
@@ -325,6 +330,7 @@
             setVisibility(View.GONE);
         }
         if (mBar != null) {
+            // This will indirectly cause show(false, ...) to get called
             mBar.animateCollapse();
         }
     }
@@ -729,10 +735,20 @@
         getContext().startActivity(intent);
     }
 
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        if (mPopup != null) {
+            return true;
+        } else {
+            return super.onInterceptTouchEvent(ev);
+        }
+    }
+
     public void handleLongPress(
             final View selectedView, final View anchorView, final View thumbnailView) {
         thumbnailView.setSelected(true);
-        PopupMenu popup = new PopupMenu(mContext, anchorView == null ? selectedView : anchorView);
+        final PopupMenu popup =
+            new PopupMenu(mContext, anchorView == null ? selectedView : anchorView);
+        mPopup = popup;
         popup.getMenuInflater().inflate(R.menu.recent_popup_menu, popup.getMenu());
         popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
             public boolean onMenuItemClick(MenuItem item) {
@@ -756,6 +772,7 @@
         popup.setOnDismissListener(new PopupMenu.OnDismissListener() {
             public void onDismiss(PopupMenu menu) {
                 thumbnailView.setSelected(false);
+                mPopup = null;
             }
         });
         popup.show();
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsScrollViewPerformanceHelper.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsScrollViewPerformanceHelper.java
index 5529d0c..6bd1826 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsScrollViewPerformanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsScrollViewPerformanceHelper.java
@@ -37,15 +37,11 @@
     public static final boolean OPTIMIZE_SW_RENDERED_RECENTS = true;
     public static final boolean USE_DARK_FADE_IN_HW_ACCELERATED_MODE = true;
     private View mScrollView;
-    private LinearLayout mLinearLayout;
     private RecentsCallback mCallback;
 
-    private boolean mShowBackground = false;
     private int mFadingEdgeLength;
-    private Drawable.ConstantState mBackgroundDrawable;
     private Context mContext;
     private boolean mIsVertical;
-    private boolean mFirstTime = true;
     private boolean mSoftwareRendered = false;
     private boolean mAttachedToWindow = false;
 
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 12c05ed..5ba72c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1766,11 +1766,6 @@
                 // HWComposer is unable to handle SW-rendered RGBX_8888 layers.
                 PixelFormat.RGB_565);
 
-        // the status bar should be in an overlay if possible
-        final Display defaultDisplay
-            = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
-                .getDefaultDisplay();
-
         // We explicitly leave FLAG_HARDWARE_ACCELERATED out of the flags.  The status bar occupies
         // very little screen real-estate and is updated fairly frequently.  By using CPU rendering
         // for the status bar, we prevent the GPU from having to wake up just to do these small
@@ -1779,9 +1774,7 @@
         lp.gravity = getStatusBarGravity();
         lp.setTitle("StatusBar");
         lp.packageName = mContext.getPackageName();
-        lp.windowAnimations = R.style.Animation_StatusBar;
         WindowManagerImpl.getDefault().addView(makeStatusBarView(), lp);
-
     }
     
     void addExpandedWindow() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/HeightReceiver.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/HeightReceiver.java
deleted file mode 100644
index 3e9a9d8..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/HeightReceiver.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.tablet;
-
-import java.util.ArrayList;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.res.Resources;
-import android.util.DisplayMetrics;
-import android.util.Slog;
-import android.view.Display;
-import android.view.WindowManager;
-import android.view.WindowManagerImpl;
-import android.view.WindowManagerPolicy;
-
-public class HeightReceiver extends BroadcastReceiver {
-    private static final String TAG = "StatusBar.HeightReceiver";
-
-    public interface OnBarHeightChangedListener {
-        public void onBarHeightChanged(int height);
-    }
-
-    Context mContext;
-    ArrayList<OnBarHeightChangedListener> mListeners = new ArrayList<OnBarHeightChangedListener>();
-    WindowManager mWindowManager;
-    int mHeight;
-    boolean mPlugged;
-
-    public HeightReceiver(Context context) {
-        mContext = context;
-        mWindowManager = WindowManagerImpl.getDefault();
-    }
-
-    public void addOnBarHeightChangedListener(OnBarHeightChangedListener l) {
-        mListeners.add(l);
-        l.onBarHeightChanged(mHeight);
-    }
-
-    public void removeOnBarHeightChangedListener(OnBarHeightChangedListener l) {
-        mListeners.remove(l);
-    }
-
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        final boolean plugged
-                = intent.getBooleanExtra(WindowManagerPolicy.EXTRA_HDMI_PLUGGED_STATE, false);
-        setPlugged(plugged);
-    }
-
-    public void registerReceiver() {
-        final IntentFilter filter = new IntentFilter();
-        filter.addAction(WindowManagerPolicy.ACTION_HDMI_PLUGGED);
-        final Intent val = mContext.registerReceiver(this, filter);
-        onReceive(mContext, val);
-    }
-
-    private void setPlugged(boolean plugged) {
-        mPlugged = plugged;
-        updateHeight();
-    }
-
-    public void updateHeight() {
-        final Resources res = mContext.getResources();
-
-        int height = -1;
-        if (mPlugged) {
-            final DisplayMetrics metrics = new DisplayMetrics();
-            Display display = mWindowManager.getDefaultDisplay();
-            display.getRealMetrics(metrics);
-
-            //Slog.i(TAG, "updateHeight: display metrics=" + metrics);
-            final int shortSide = Math.min(metrics.widthPixels, metrics.heightPixels);
-            final int externalShortSide = Math.min(display.getRawExternalWidth(),
-                    display.getRawExternalHeight());
-            height = shortSide - externalShortSide;
-        }
-
-        final int minHeight
-                = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
-        if (height < minHeight) {
-            height = minHeight;
-        }
-        Slog.i(TAG, "Resizing status bar plugged=" + mPlugged + " height="
-                + height + " old=" + mHeight);
-        mHeight = height;
-
-        final int N = mListeners.size();
-        for (int i=0; i<N; i++) {
-            mListeners.get(i).onBarHeightChanged(height);
-        }
-    }
-
-    public int getHeight() {
-        return mHeight;
-    }
-}
-
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 7325a37..49b1a14 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -87,7 +87,6 @@
 import com.android.systemui.statusbar.policy.Prefs;
 
 public class TabletStatusBar extends BaseStatusBar implements
-        HeightReceiver.OnBarHeightChangedListener,
         InputMethodsPanel.OnHardKeyboardEnabledChangeListener,
         RecentsPanelView.OnRecentsPanelVisibilityChangedListener {
     public static final boolean DEBUG = false;
@@ -162,7 +161,6 @@
 
     ViewGroup mPile;
 
-    HeightReceiver mHeightReceiver;
     BatteryController mBatteryController;
     BluetoothController mBluetoothController;
     LocationController mLocationController;
@@ -204,12 +202,11 @@
     
     private void addStatusBarWindow() {
         final View sb = makeStatusBarView();
-        final int height = getStatusBarHeight();
 
         final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT,
-                height,
-                WindowManager.LayoutParams.TYPE_STATUS_BAR,
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                     | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                     | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
@@ -218,20 +215,14 @@
                 // HWComposer is unable to handle SW-rendered RGBX_8888 layers.
                 PixelFormat.RGB_565);
 
-        // the status bar should be in an overlay if possible
-        final Display defaultDisplay
-            = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
-                .getDefaultDisplay();
-
         // We explicitly leave FLAG_HARDWARE_ACCELERATED out of the flags.  The status bar occupies
         // very little screen real-estate and is updated fairly frequently.  By using CPU rendering
         // for the status bar, we prevent the GPU from having to wake up just to do these small
         // updates, which should help keep power consumption down.
 
         lp.gravity = getStatusBarGravity();
-        lp.setTitle("StatusBar");
+        lp.setTitle("SystemBar");
         lp.packageName = mContext.getPackageName();
-        lp.windowAnimations = R.style.Animation_StatusBar;
         WindowManagerImpl.getDefault().addView(sb, lp);
     }
 
@@ -414,7 +405,6 @@
 
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
-        mHeightReceiver.updateHeight(); // display size may have changed
         loadDimens();
         mNotificationPanelParams.height = getNotificationPanelHeight();
         WindowManagerImpl.getDefault().updateViewLayout(mNotificationPanel,
@@ -426,7 +416,7 @@
         final Resources res = mContext.getResources();
 
         mNaturalBarHeight = res.getDimensionPixelSize(
-                com.android.internal.R.dimen.system_bar_height);
+                com.android.internal.R.dimen.navigation_bar_height);
 
         int newIconSize = res.getDimensionPixelSize(
             com.android.internal.R.dimen.system_bar_icon_size);
@@ -478,10 +468,6 @@
         mWindowManager = IWindowManager.Stub.asInterface(
                 ServiceManager.getService(Context.WINDOW_SERVICE));
 
-        // This guy will listen for HDMI plugged broadcasts so we can resize the
-        // status bar as appropriate.
-        mHeightReceiver = new HeightReceiver(mContext);
-        mHeightReceiver.registerReceiver();
         loadDimens();
 
         final TabletStatusBarView sb = (TabletStatusBarView)View.inflate(
@@ -637,8 +623,6 @@
         // set the initial view visibility
         setAreThereNotifications();
 
-        mHeightReceiver.addOnBarHeightChangedListener(this);
-
         // receive broadcasts
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
@@ -674,7 +658,9 @@
     }
 
     public int getStatusBarHeight() {
-        return mHeightReceiver.getHeight();
+        return mStatusBarView != null ? mStatusBarView.getHeight()
+                : mContext.getResources().getDimensionPixelSize(
+                        com.android.internal.R.dimen.navigation_bar_height);
     }
 
     protected int getStatusBarGravity() {
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
index 804cd9e..a472375 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
@@ -105,6 +105,7 @@
     private static final int MSG_CLOCK_VISIBILITY_CHANGED = 307;
     private static final int MSG_DEVICE_PROVISIONED = 308;
     protected static final int MSG_DPM_STATE_CHANGED = 309;
+    protected static final int MSG_USER_CHANGED = 310;
 
     /**
      * When we receive a
@@ -209,6 +210,9 @@
                     case MSG_DPM_STATE_CHANGED:
                         handleDevicePolicyManagerStateChanged();
                         break;
+                    case MSG_USER_CHANGED:
+                        handleUserChanged(msg.arg1);
+                        break;
                 }
             }
         };
@@ -268,6 +272,8 @@
         filter.addAction(SPN_STRINGS_UPDATED_ACTION);
         filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
         filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
+        filter.addAction(Intent.ACTION_USER_SWITCHED);
+        filter.addAction(Intent.ACTION_USER_REMOVED);
         context.registerReceiver(new BroadcastReceiver() {
 
             public void onReceive(Context context, Intent intent) {
@@ -302,6 +308,9 @@
                 } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
                         .equals(action)) {
                     mHandler.sendMessage(mHandler.obtainMessage(MSG_DPM_STATE_CHANGED));
+                } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+                    mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_CHANGED,
+                            intent.getIntExtra(Intent.EXTRA_USERID, 0), 0));
                 }
             }
         }, filter);
@@ -313,6 +322,12 @@
         }
     }
 
+    protected void handleUserChanged(int userId) {
+        for (int i = 0; i < mInfoCallbacks.size(); i++) {
+            mInfoCallbacks.get(i).onUserChanged(userId);
+        }
+    }
+
     protected void handleDeviceProvisioned() {
         for (int i = 0; i < mInfoCallbacks.size(); i++) {
             mInfoCallbacks.get(i).onDeviceProvisioned();
@@ -542,6 +557,11 @@
          * See {@link DevicePolicyManager#ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED}
          */
         void onDevicePolicyManagerStateChanged();
+
+        /**
+         * Called when the user changes.
+         */
+        void onUserChanged(int userId);
     }
 
     // Simple class that allows methods to easily be overwritten
@@ -570,6 +590,9 @@
 
         public void onDevicePolicyManagerStateChanged() {
         }
+
+        public void onUserChanged(int userId) {
+        }
     }
 
     /**
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index 377ea66..52fb875 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -85,7 +85,7 @@
  * This class is created by the initialization routine of the {@link WindowManagerPolicy},
  * and runs on its thread.  The keyguard UI is created from that thread in the
  * constructor of this class.  The apis may be called from other threads, including the
- * {@link com.android.server.wm.InputManager}'s and {@link android.view.WindowManager}'s.
+ * {@link com.android.server.input.InputManagerService}'s and {@link android.view.WindowManager}'s.
  * Therefore, methods on this class are synchronized, and any action that is pointed
  * directly to the keyguard UI is posted to a {@link Handler} to ensure it is taken on the UI
  * thread of the keyguard.
@@ -342,6 +342,10 @@
         if (soundPath == null || mUnlockSoundId == 0) {
             if (DEBUG) Log.d(TAG, "failed to load sound from " + soundPath);
         }
+        IntentFilter userFilter = new IntentFilter();
+        userFilter.addAction(Intent.ACTION_USER_SWITCHED);
+        userFilter.addAction(Intent.ACTION_USER_REMOVED);
+        mContext.registerReceiver(mUserChangeReceiver, userFilter);
     }
 
     /**
@@ -801,6 +805,29 @@
         return mKeyguardViewProperties.isSecure();
     }
 
+    private void onUserSwitched(int userId) {
+        mLockPatternUtils.setCurrentUser(userId);
+        synchronized (KeyguardViewMediator.this) {
+            resetStateLocked();
+        }
+    }
+
+    private void onUserRemoved(int userId) {
+        mLockPatternUtils.removeUser(userId);
+    }
+
+    private BroadcastReceiver mUserChangeReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+                onUserSwitched(intent.getIntExtra(Intent.EXTRA_USERID, 0));
+            } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
+                onUserRemoved(intent.getIntExtra(Intent.EXTRA_USERID, 0));
+            }
+        }
+    };
+
     private BroadcastReceiver mBroadCastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 2e7769b..404dc6f 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -757,6 +757,12 @@
                 hideFaceLockArea();
             }
         }
+
+        @Override
+        public void onUserChanged(int userId) {
+            mLockPatternUtils.setCurrentUser(userId);
+            updateScreen(getInitialMode(), true);
+        }
     };
 
     @Override
diff --git a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
index 9a6d2cc..17e671d 100644
--- a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
@@ -41,7 +41,7 @@
 class PatternUnlockScreen extends LinearLayoutWithDefaultTouchRecepient
         implements KeyguardScreen {
 
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = true; /* TODO: revert before JB release */
     private static final String TAG = "UnlockScreen";
 
     // how long before we clear the wrong pattern
@@ -321,6 +321,7 @@
             implements LockPatternView.OnPatternListener {
 
         public void onPatternStart() {
+            if (DEBUG) Log.d(TAG, "Got pattern start");
             mLockPatternView.removeCallbacks(mCancelPatternRunnable);
         }
 
@@ -336,6 +337,7 @@
                 // Give just a little extra time if they hit one of the first few dots
                 mCallback.pokeWakelock(UNLOCK_PATTERN_WAKE_INTERVAL_FIRST_DOTS_MS);
             }
+            if (DEBUG) Log.d(TAG, "Got pattern cell");
         }
 
         public void onPatternDetected(List<LockPatternView.Cell> pattern) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index fb1e106..c3cac6e 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -1,5 +1,4 @@
 /*
- * Copyright (C) 2006 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -72,6 +71,7 @@
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.view.Display;
 import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
 import android.view.IApplicationToken;
@@ -299,11 +299,13 @@
     boolean mHeadless;
     boolean mSafeMode;
     WindowState mStatusBar = null;
-    boolean mStatusBarCanHide;
+    boolean mHasSystemNavBar;
     int mStatusBarHeight;
     final ArrayList<WindowState> mStatusBarPanels = new ArrayList<WindowState>();
     WindowState mNavigationBar = null;
     boolean mHasNavigationBar = false;
+    boolean mCanHideNavigationBar = false;
+    boolean mNavigationBarOnBottom = true;
     int mNavigationBarWidth = 0, mNavigationBarHeight = 0;
 
     WindowState mKeyguard = null;
@@ -329,6 +331,8 @@
     boolean mSystemReady;
     boolean mSystemBooted;
     boolean mHdmiPlugged;
+    int mExternalDisplayWidth;
+    int mExternalDisplayHeight;
     int mUiMode;
     int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
     int mLidOpenRotation;
@@ -464,6 +468,8 @@
     // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
     int mIncallPowerBehavior;
 
+    Display mDisplay;
+
     int mLandscapeRotation = 0;  // default landscape rotation
     int mSeascapeRotation = 0;   // "other" landscape rotation, 180 degrees from mLandscapeRotation
     int mPortraitRotation = 0;   // default portrait rotation
@@ -927,10 +933,13 @@
         }
     }
 
-    public void setInitialDisplaySize(int width, int height) {
-        int shortSize;
+    public void setInitialDisplaySize(Display display, int width, int height) {
+        mDisplay = display;
+
+        int shortSize, longSize;
         if (width > height) {
             shortSize = height;
+            longSize = width;
             mLandscapeRotation = Surface.ROTATION_0;
             mSeascapeRotation = Surface.ROTATION_180;
             if (mContext.getResources().getBoolean(
@@ -943,6 +952,7 @@
             }
         } else {
             shortSize = width;
+            longSize = height;
             mPortraitRotation = Surface.ROTATION_0;
             mUpsideDownRotation = Surface.ROTATION_180;
             if (mContext.getResources().getBoolean(
@@ -955,36 +965,61 @@
             }
         }
 
+        mExternalDisplayWidth = mDisplay.getRawExternalWidth();
+        mExternalDisplayHeight = mDisplay.getRawExternalHeight();
+
+        mStatusBarHeight = mContext.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.status_bar_height);
+        mNavigationBarHeight = mContext.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.navigation_bar_height);
+        mNavigationBarWidth = mContext.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.navigation_bar_width);
+
         // Determine whether the status bar can hide based on the size
         // of the screen.  We assume sizes > 600dp are tablets where we
         // will use the system bar.
         int shortSizeDp = shortSize
                 * DisplayMetrics.DENSITY_DEFAULT
                 / DisplayMetrics.DENSITY_DEVICE;
-        mStatusBarCanHide = shortSizeDp < 600;
-        mStatusBarHeight = mContext.getResources().getDimensionPixelSize(
-                mStatusBarCanHide
-                ? com.android.internal.R.dimen.status_bar_height
-                : com.android.internal.R.dimen.system_bar_height);
+        mHasSystemNavBar = shortSizeDp > 600;
 
-        mHasNavigationBar = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_showNavigationBar);
-        // Allow a system property to override this. Used by the emulator.
-        // See also hasNavigationBar().
-        String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
-        if (! "".equals(navBarOverride)) {
-            if      (navBarOverride.equals("1")) mHasNavigationBar = false;
-            else if (navBarOverride.equals("0")) mHasNavigationBar = true;
+        if (!mHasSystemNavBar) {
+            mHasNavigationBar = mContext.getResources().getBoolean(
+                    com.android.internal.R.bool.config_showNavigationBar);
+            // Allow a system property to override this. Used by the emulator.
+            // See also hasNavigationBar().
+            String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
+            if (! "".equals(navBarOverride)) {
+                if      (navBarOverride.equals("1")) mHasNavigationBar = false;
+                else if (navBarOverride.equals("0")) mHasNavigationBar = true;
+            }
+        } else {
+            mHasNavigationBar = false;
         }
 
-        mNavigationBarHeight = mHasNavigationBar
-                ? mContext.getResources().getDimensionPixelSize(
-                    com.android.internal.R.dimen.navigation_bar_height)
-                : 0;
-        mNavigationBarWidth = mHasNavigationBar
-                ? mContext.getResources().getDimensionPixelSize(
-                    com.android.internal.R.dimen.navigation_bar_width)
-                : 0;
+        if (mHasSystemNavBar) {
+            // The system bar is always at the bottom.  If you are watching
+            // a video in landscape, we don't need to hide it if we can still
+            // show a 16:9 aspect ratio with it.
+            int longSizeDp = longSize
+                    * DisplayMetrics.DENSITY_DEFAULT
+                    / DisplayMetrics.DENSITY_DEVICE;
+            int barHeightDp = mNavigationBarHeight
+                    * DisplayMetrics.DENSITY_DEFAULT
+                    / DisplayMetrics.DENSITY_DEVICE;
+            int aspect = ((shortSizeDp-barHeightDp) * 16) / longSizeDp;
+            // We have computed the aspect ratio with the bar height taken
+            // out to be 16:aspect.  If this is less than 9, then hiding
+            // the navigation bar will provide more useful space for wide
+            // screen movies.
+            mCanHideNavigationBar = aspect < 9;
+        } else if (mHasNavigationBar) {
+            // The navigation bar is at the right in landscape; it seems always
+            // useful to hide it for showing a video.
+            mCanHideNavigationBar = true;
+        } else {
+            mCanHideNavigationBar = false;
+        }
 
         if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
             mHdmiRotation = mPortraitRotation;
@@ -1318,13 +1353,13 @@
         return STATUS_BAR_LAYER;
     }
 
-    public boolean canStatusBarHide() {
-        return mStatusBarCanHide;
+    public boolean hasSystemNavBar() {
+        return mHasSystemNavBar;
     }
 
     public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation) {
         // Assumes that the navigation bar appears on the side of the display in landscape.
-        if (fullWidth > fullHeight) {
+        if (mHasNavigationBar && fullWidth > fullHeight) {
             return fullWidth - mNavigationBarWidth;
         }
         return fullWidth;
@@ -1333,8 +1368,8 @@
     public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation) {
         // Assumes the navigation bar appears on the bottom of the display in portrait.
         return fullHeight
-            - (mStatusBarCanHide ? 0 : mStatusBarHeight)
-            - ((fullWidth > fullHeight) ? 0 : mNavigationBarHeight);
+            - (mHasSystemNavBar ? mNavigationBarHeight : 0)
+            - ((mHasNavigationBar && fullWidth > fullHeight) ? 0 : mNavigationBarHeight);
     }
 
     public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation) {
@@ -1348,7 +1383,7 @@
         // exclude it since applications can't generally use that part of the
         // screen.
         return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation)
-                - (mStatusBarCanHide ? mStatusBarHeight : 0);
+                - (mHasSystemNavBar ? 0 : mStatusBarHeight);
     }
 
     public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) {
@@ -1357,6 +1392,7 @@
     
     public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) {
         return attrs.type != WindowManager.LayoutParams.TYPE_STATUS_BAR
+                && attrs.type != WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
                 && attrs.type != WindowManager.LayoutParams.TYPE_WALLPAPER;
     }
     
@@ -1495,10 +1531,10 @@
                 mContext.enforceCallingOrSelfPermission(
                         android.Manifest.permission.STATUS_BAR_SERVICE,
                         "PhoneWindowManager");
-                // TODO: Need to handle the race condition of the status bar proc
-                // dying and coming back before the removeWindowLw cleanup has happened.
                 if (mStatusBar != null) {
-                    return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
+                    if (mStatusBar.isAlive()) {
+                        return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
+                    }
                 }
                 mStatusBar = win;
                 break;
@@ -1506,6 +1542,11 @@
                 mContext.enforceCallingOrSelfPermission(
                         android.Manifest.permission.STATUS_BAR_SERVICE,
                         "PhoneWindowManager");
+                if (mNavigationBar != null) {
+                    if (mNavigationBar.isAlive()) {
+                        return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
+                    }
+                }
                 mNavigationBar = win;
                 if (DEBUG_LAYOUT) Log.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
                 break;
@@ -1550,7 +1591,28 @@
     public int selectAnimationLw(WindowState win, int transit) {
         if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
               + ": transit=" + transit);
-        if (transit == TRANSIT_PREVIEW_DONE) {
+        if (win == mStatusBar) {
+            if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) {
+                return R.anim.dock_top_exit;
+            } else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
+                return R.anim.dock_top_enter;
+            }
+        } else if (win == mNavigationBar) {
+            // This can be on either the bottom or the right.
+            if (mNavigationBarOnBottom) {
+                if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) {
+                    return R.anim.dock_bottom_exit;
+                } else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
+                    return R.anim.dock_bottom_enter;
+                }
+            } else {
+                if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) {
+                    return R.anim.dock_right_exit;
+                } else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
+                    return R.anim.dock_right_enter;
+                }
+            }
+        } if (transit == TRANSIT_PREVIEW_DONE) {
             if (win.hasAppShownWindows()) {
                 if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
                 return com.android.internal.R.anim.app_starting_exit;
@@ -2036,7 +2098,8 @@
         if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
                 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
             int availRight, availBottom;
-            if ((attrs.systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
+            if (mCanHideNavigationBar &&
+                    (attrs.systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
                 availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
                 availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
             } else {
@@ -2082,8 +2145,9 @@
         pf.right = df.right = vf.right = mDockRight;
         pf.bottom = df.bottom = vf.bottom = mDockBottom;
 
-        final boolean navVisible = (mNavigationBar == null || mNavigationBar.isVisibleLw()) &&
-                (mLastSystemUiFlags&View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
+        // For purposes of putting out fake window up to steal focus, we will
+        // drive nav being hidden only by whether it is requested.
+        boolean navVisible = (mLastSystemUiFlags&View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
 
         // When the navigation bar isn't visible, we put up a fake
         // input window to catch all touch events.  This way we can
@@ -2101,57 +2165,71 @@
                     0, false, false, true);
         }
 
-        // decide where the status bar goes ahead of time
-        if (mStatusBar != null) {
-            if (mNavigationBar != null) {
-                // Force the navigation bar to its appropriate place and
-                // size.  We need to do this directly, instead of relying on
-                // it to bubble up from the nav bar, because this needs to
-                // change atomically with screen rotations.
-                if (displayWidth < displayHeight) {
-                    // Portrait screen; nav bar goes on bottom.
-                    mTmpNavigationFrame.set(0, displayHeight-mNavigationBarHeight,
-                            displayWidth, displayHeight);
-                    mStableBottom = mTmpNavigationFrame.top;
-                    if (navVisible) {
-                        mDockBottom = mTmpNavigationFrame.top;
-                        mRestrictedScreenHeight = mDockBottom - mDockTop;
-                    } else {
-                        // We currently want to hide the navigation UI.  Do this by just
-                        // moving it off the screen, so it can still receive input events
-                        // to know when to be re-shown.
-                        mTmpNavigationFrame.offset(0, mNavigationBarHeight);
-                    }
-                } else {
-                    // Landscape screen; nav bar goes to the right.
-                    mTmpNavigationFrame.set(displayWidth-mNavigationBarWidth, 0,
-                            displayWidth, displayHeight);
-                    mStableRight = mTmpNavigationFrame.left;
-                    if (navVisible) {
-                        mDockRight = mTmpNavigationFrame.left;
-                        mRestrictedScreenWidth = mDockRight - mDockLeft;
-                    } else {
-                        // We currently want to hide the navigation UI.  Do this by just
-                        // moving it off the screen, so it can still receive input events
-                        // to know when to be re-shown.
-                        mTmpNavigationFrame.offset(mNavigationBarWidth, 0);
+        // For purposes of positioning and showing the nav bar, if we have
+        // decided that it can't be hidden (because of the screen aspect ratio),
+        // then take that into account.
+        navVisible |= !mCanHideNavigationBar;
+
+        if (mNavigationBar != null) {
+            // Force the navigation bar to its appropriate place and
+            // size.  We need to do this directly, instead of relying on
+            // it to bubble up from the nav bar, because this needs to
+            // change atomically with screen rotations.
+            mNavigationBarOnBottom = !mHasNavigationBar || displayWidth < displayHeight;
+            if (mNavigationBarOnBottom) {
+                // It's a system nav bar or a portrait screen; nav bar goes on bottom.
+                int top = displayHeight - mNavigationBarHeight;
+                if (mHdmiPlugged) {
+                    if (top > mExternalDisplayHeight) {
+                        top = mExternalDisplayHeight;
                     }
                 }
-                // Make sure the content and current rectangles are updated to
-                // account for the restrictions from the navigation bar.
-                mContentTop = mCurTop = mDockTop;
-                mContentBottom = mCurBottom = mDockBottom;
-                mContentLeft = mCurLeft = mDockLeft;
-                mContentRight = mCurRight = mDockRight;
-                // And compute the final frame.
-                mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
-                        mTmpNavigationFrame, mTmpNavigationFrame);
-                if (DEBUG_LAYOUT) Log.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
+                mTmpNavigationFrame.set(0, top, displayWidth, displayHeight);
+                mStableBottom = mTmpNavigationFrame.top;
+                if (navVisible) {
+                    mNavigationBar.showLw(true);
+                    mDockBottom = mTmpNavigationFrame.top;
+                    mRestrictedScreenHeight = mDockBottom - mDockTop;
+                } else {
+                    // We currently want to hide the navigation UI.
+                    mNavigationBar.hideLw(true);
+                }
+            } else {
+                // Landscape screen; nav bar goes to the right.
+                int left = displayWidth - mNavigationBarWidth;
+                if (mHdmiPlugged) {
+                    if (left > mExternalDisplayWidth) {
+                        left = mExternalDisplayWidth;
+                    }
+                }
+                mTmpNavigationFrame.set(left, 0, displayWidth, displayHeight);
+                mStableRight = mTmpNavigationFrame.left;
+                if (navVisible) {
+                    mNavigationBar.showLw(true);
+                    mDockRight = mTmpNavigationFrame.left;
+                    mRestrictedScreenWidth = mDockRight - mDockLeft;
+                } else {
+                    // We currently want to hide the navigation UI.
+                    mNavigationBar.hideLw(true);
+                }
             }
-            if (DEBUG_LAYOUT) Log.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
-                    mDockLeft, mDockTop, mDockRight, mDockBottom));
+            // Make sure the content and current rectangles are updated to
+            // account for the restrictions from the navigation bar.
+            mContentTop = mCurTop = mDockTop;
+            mContentBottom = mCurBottom = mDockBottom;
+            mContentLeft = mCurLeft = mDockLeft;
+            mContentRight = mCurRight = mDockRight;
+            // And compute the final frame.
+            mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
+                    mTmpNavigationFrame, mTmpNavigationFrame);
+            if (DEBUG_LAYOUT) Log.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
+        }
+        if (DEBUG_LAYOUT) Log.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
+                mDockLeft, mDockTop, mDockRight, mDockBottom));
 
-            // apply navigation bar insets
+        // decide where the status bar goes ahead of time
+        if (mStatusBar != null) {
+            // apply any navigation bar insets
             pf.left = df.left = vf.left = mDockLeft;
             pf.top = df.top = vf.top = mDockTop;
             pf.right = df.right = vf.right = mDockRight;
@@ -2161,57 +2239,29 @@
             final Rect r = mStatusBar.getFrameLw();
 
             // Compute the stable dimensions whether or not the status bar is hidden.
-            if (mStatusBarCanHide) {
-                if (mDockTop == r.top) mStableTop = r.bottom;
-                else if (mDockBottom == r.bottom) mStableBottom = r.top;
-            } else {
-                if (mStableTop == r.top) {
-                    mStableTop = r.bottom;
-                } else if (mStableBottom == r.bottom) {
-                    mStableBottom = r.top;
-                }
-            }
+            if (mDockTop == r.top) mStableTop = r.bottom;
+            else if (mDockBottom == r.bottom) mStableBottom = r.top;
 
+            // If the status bar is hidden, we don't want to cause
+            // windows behind it to scroll.
             if (mStatusBar.isVisibleLw()) {
-                // If the status bar is hidden, we don't want to cause
-                // windows behind it to scroll.
-                if (mStatusBarCanHide) {
-                    // Status bar may go away, so the screen area it occupies
-                    // is available to apps but just covering them when the
-                    // status bar is visible.
-                    if (mDockTop == r.top) mDockTop = r.bottom;
-                    else if (mDockBottom == r.bottom) mDockBottom = r.top;
-                    
-                    mContentTop = mCurTop = mDockTop;
-                    mContentBottom = mCurBottom = mDockBottom;
-                    mContentLeft = mCurLeft = mDockLeft;
-                    mContentRight = mCurRight = mDockRight;
+                // Status bar may go away, so the screen area it occupies
+                // is available to apps but just covering them when the
+                // status bar is visible.
+                if (mDockTop == r.top) mDockTop = r.bottom;
+                else if (mDockBottom == r.bottom) mDockBottom = r.top;
+                
+                mContentTop = mCurTop = mDockTop;
+                mContentBottom = mCurBottom = mDockBottom;
+                mContentLeft = mCurLeft = mDockLeft;
+                mContentRight = mCurRight = mDockRight;
 
-                    if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: " +
-                        String.format(
-                            "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
-                            mDockLeft, mDockTop, mDockRight, mDockBottom,
-                            mContentLeft, mContentTop, mContentRight, mContentBottom,
-                            mCurLeft, mCurTop, mCurRight, mCurBottom));
-                } else {
-                    // Status bar can't go away; the part of the screen it
-                    // covers does not exist for anything behind it.
-                    if (mRestrictedScreenTop == r.top) {
-                        mRestrictedScreenTop = r.bottom;
-                        mRestrictedScreenHeight -= (r.bottom-r.top);
-                    } else if ((mRestrictedScreenHeight-mRestrictedScreenTop) == r.bottom) {
-                        mRestrictedScreenHeight -= (r.bottom-r.top);
-                    }
-
-                    mContentTop = mCurTop = mDockTop = mRestrictedScreenTop;
-                    mContentBottom = mCurBottom = mDockBottom
-                            = mRestrictedScreenTop + mRestrictedScreenHeight;
-                    if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: restricted screen area: ("
-                            + mRestrictedScreenLeft + ","
-                            + mRestrictedScreenTop + ","
-                            + (mRestrictedScreenLeft + mRestrictedScreenWidth) + ","
-                            + (mRestrictedScreenTop + mRestrictedScreenHeight) + ")");
-                }
+                if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: " +
+                    String.format(
+                        "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
+                        mDockLeft, mDockTop, mDockRight, mDockBottom,
+                        mContentLeft, mContentTop, mContentRight, mContentBottom,
+                        mCurLeft, mCurTop, mCurRight, mCurBottom));
             }
         }
     }
@@ -2333,7 +2383,8 @@
                                         "Laying out status bar window: (%d,%d - %d,%d)",
                                         pf.left, pf.top, pf.right, pf.bottom));
                         }
-                    } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
+                    } else if (mCanHideNavigationBar
+                            && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
                             && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
                             && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
                         // Asking for layout as if the nav bar is hidden, lets the
@@ -2426,7 +2477,8 @@
                     pf.right = df.right = cf.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
                     pf.bottom = df.bottom = cf.bottom
                             = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
-                } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
+                } else if (mCanHideNavigationBar
+                        && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
                         && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
                         && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
                     // Asking for layout as if the nav bar is hidden, lets the
@@ -2623,19 +2675,17 @@
                 // has the FLAG_FULLSCREEN set.  Not sure if there is another way that to be the
                 // case though.
                 if (topIsFullscreen) {
-                    if (mStatusBarCanHide) {
-                        if (DEBUG_LAYOUT) Log.v(TAG, "** HIDING status bar");
-                        if (mStatusBar.hideLw(true)) {
-                            changes |= FINISH_LAYOUT_REDO_LAYOUT;
+                    if (DEBUG_LAYOUT) Log.v(TAG, "** HIDING status bar");
+                    if (mStatusBar.hideLw(true)) {
+                        changes |= FINISH_LAYOUT_REDO_LAYOUT;
 
-                            mHandler.post(new Runnable() { public void run() {
-                                if (mStatusBarService != null) {
-                                    try {
-                                        mStatusBarService.collapse();
-                                    } catch (RemoteException ex) {}
-                                }
-                            }});
-                        }
+                        mHandler.post(new Runnable() { public void run() {
+                            if (mStatusBarService != null) {
+                                try {
+                                    mStatusBarService.collapse();
+                                } catch (RemoteException ex) {}
+                            }
+                        }});
                     } else if (DEBUG_LAYOUT) {
                         Log.v(TAG, "Preventing status bar from hiding by policy");
                     }
@@ -2699,29 +2749,23 @@
             // behind it.
             return false;
         }
-        if (false) {
-            // Don't do this on the tablet, since the system bar never completely
-            // covers the screen, and with all its transparency this will
-            // incorrectly think it does cover it when it doesn't.  We'll revisit
-            // this later when we re-do the phone status bar.
-            if (mStatusBar != null && mStatusBar.isVisibleLw()) {
-                RectF rect = new RectF(mStatusBar.getShownFrameLw());
-                for (int i=mStatusBarPanels.size()-1; i>=0; i--) {
-                    WindowState w = mStatusBarPanels.get(i);
-                    if (w.isVisibleLw()) {
-                        rect.union(w.getShownFrameLw());
-                    }
+        if (mStatusBar != null && mStatusBar.isVisibleLw()) {
+            RectF rect = new RectF(mStatusBar.getShownFrameLw());
+            for (int i=mStatusBarPanels.size()-1; i>=0; i--) {
+                WindowState w = mStatusBarPanels.get(i);
+                if (w.isVisibleLw()) {
+                    rect.union(w.getShownFrameLw());
                 }
-                final int insetw = mRestrictedScreenWidth/10;
-                final int inseth = mRestrictedScreenHeight/10;
-                if (rect.contains(insetw, inseth, mRestrictedScreenWidth-insetw,
-                            mRestrictedScreenHeight-inseth)) {
-                    // All of the status bar windows put together cover the
-                    // screen, so the app can't be seen.  (Note this test doesn't
-                    // work if the rects of these windows are at off offsets or
-                    // sizes, causing gaps in the rect union we have computed.)
-                    return false;
-                }
+            }
+            final int insetw = mRestrictedScreenWidth/10;
+            final int inseth = mRestrictedScreenHeight/10;
+            if (rect.contains(insetw, inseth, mRestrictedScreenWidth-insetw,
+                        mRestrictedScreenHeight-inseth)) {
+                // All of the status bar windows put together cover the
+                // screen, so the app can't be seen.  (Note this test doesn't
+                // work if the rects of these windows are at odd offsets or
+                // sizes, causing gaps in the rect union we have computed.)
+                return false;
             }
         }
         return true;
@@ -2776,7 +2820,11 @@
     void setHdmiPlugged(boolean plugged) {
         if (mHdmiPlugged != plugged) {
             mHdmiPlugged = plugged;
-            updateRotation(true);
+            if (plugged && mDisplay != null) {
+                mExternalDisplayWidth = mDisplay.getRawExternalWidth();
+                mExternalDisplayHeight = mDisplay.getRawExternalHeight();
+            }
+            updateRotation(true, true);
             Intent intent = new Intent(ACTION_HDMI_PLUGGED);
             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
             intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
@@ -3871,7 +3919,16 @@
     void updateRotation(boolean alwaysSendConfiguration) {
         try {
             //set orientation on WindowManager
-            mWindowManager.updateRotation(alwaysSendConfiguration);
+            mWindowManager.updateRotation(alwaysSendConfiguration, false);
+        } catch (RemoteException e) {
+            // Ignore
+        }
+    }
+
+    void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
+        try {
+            //set orientation on WindowManager
+            mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
         } catch (RemoteException e) {
             // Ignore
         }
diff --git a/services/java/com/android/server/NsdService.java b/services/java/com/android/server/NsdService.java
new file mode 100644
index 0000000..768be7d
--- /dev/null
+++ b/services/java/com/android/server/NsdService.java
@@ -0,0 +1,269 @@
+/*
+ * 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.server;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.net.nsd.DnsSdServiceInfo;
+import android.net.nsd.DnsSdTxtRecord;
+import android.net.nsd.INsdManager;
+import android.net.nsd.NsdManager;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.IBinder;
+import android.util.Slog;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.List;
+
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.util.AsyncChannel;
+import com.android.server.am.BatteryStatsService;
+import com.android.server.NativeDaemonConnector.Command;
+import com.android.internal.R;
+
+/**
+ * Network Service Discovery Service handles remote service discovery operation requests by
+ * implementing the INsdManager interface.
+ *
+ * @hide
+ */
+public class NsdService extends INsdManager.Stub {
+    private static final String TAG = "NsdService";
+    private static final String MDNS_TAG = "mDnsConnector";
+
+    private static final boolean DBG = true;
+
+    private Context mContext;
+
+    /**
+     * Clients receiving asynchronous messages
+     */
+    private List<AsyncChannel> mClients = new ArrayList<AsyncChannel>();
+
+    private AsyncChannel mReplyChannel = new AsyncChannel();
+
+    /**
+     * Handles client(app) connections
+     */
+    private class AsyncServiceHandler extends Handler {
+
+        AsyncServiceHandler(android.os.Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
+                    if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
+                        AsyncChannel c = (AsyncChannel) msg.obj;
+                        if (DBG) Slog.d(TAG, "New client listening to asynchronous messages");
+                        c.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED);
+                        mClients.add(c);
+                    } else {
+                        Slog.e(TAG, "Client connection failure, error=" + msg.arg1);
+                    }
+                    break;
+                case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
+                    if (msg.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) {
+                        Slog.e(TAG, "Send failed, client connection lost");
+                    } else {
+                        if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1);
+                    }
+                    mClients.remove((AsyncChannel) msg.obj);
+                    break;
+                case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
+                    AsyncChannel ac = new AsyncChannel();
+                    ac.connect(mContext, this, msg.replyTo);
+                    break;
+                case NsdManager.DISCOVER_SERVICES:
+                    if (DBG) Slog.d(TAG, "Discover services");
+                    DnsSdServiceInfo s = (DnsSdServiceInfo) msg.obj;
+                    discoverServices(1, s.getServiceType());
+                    mReplyChannel.replyToMessage(msg, NsdManager.DISCOVER_SERVICES_STARTED);
+                    break;
+                case NsdManager.STOP_DISCOVERY:
+                    if (DBG) Slog.d(TAG, "Stop service discovery");
+                    mReplyChannel.replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED);
+                    break;
+                case NsdManager.REGISTER_SERVICE:
+                    if (DBG) Slog.d(TAG, "Register service");
+                    mReplyChannel.replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED);
+                    break;
+                case NsdManager.UPDATE_SERVICE:
+                    if (DBG) Slog.d(TAG, "Update service");
+                    mReplyChannel.replyToMessage(msg, NsdManager.UPDATE_SERVICE_FAILED);
+                    break;
+                default:
+                    Slog.d(TAG, "NsdServicehandler.handleMessage ignoring msg=" + msg);
+                    break;
+            }
+        }
+    }
+    private AsyncServiceHandler mAsyncServiceHandler;
+
+    private NativeDaemonConnector mNativeConnector;
+    private final CountDownLatch mNativeDaemonConnected = new CountDownLatch(1);
+
+    private NsdService(Context context) {
+        mContext = context;
+
+        HandlerThread nsdThread = new HandlerThread("NsdService");
+        nsdThread.start();
+        mAsyncServiceHandler = new AsyncServiceHandler(nsdThread.getLooper());
+
+        /*
+        mNativeConnector = new NativeDaemonConnector(new NativeCallbackReceiver(), "mdns", 10,
+                MDNS_TAG, 25);
+        Thread th = new Thread(mNativeConnector, MDNS_TAG);
+        th.start();
+        */
+    }
+
+    public static NsdService create(Context context) throws InterruptedException {
+        NsdService service = new NsdService(context);
+        /* service.mNativeDaemonConnected.await(); */
+        return service;
+    }
+
+    public Messenger getMessenger() {
+        return new Messenger(mAsyncServiceHandler);
+    }
+
+    /* These should be in sync with system/netd/mDnsResponseCode.h */
+    class NativeResponseCode {
+        public static final int SERVICE_FOUND               =   101;
+        public static final int SERVICE_LOST                =   102;
+        public static final int SERVICE_DISCOVERY_FAILED    =   103;
+
+        public static final int SERVICE_REGISTERED          =   104;
+        public static final int SERVICE_REGISTRATION_FAILED =   105;
+
+        public static final int SERVICE_UPDATED             =   106;
+        public static final int SERVICE_UPDATE_FAILED       =   107;
+
+        public static final int SERVICE_RESOLVED            =   108;
+        public static final int SERVICE_RESOLUTION_FAILED   =   109;
+    }
+
+
+    class NativeCallbackReceiver implements INativeDaemonConnectorCallbacks {
+        public void onDaemonConnected() {
+            mNativeDaemonConnected.countDown();
+        }
+
+        public boolean onEvent(int code, String raw, String[] cooked) {
+            switch (code) {
+                case NativeResponseCode.SERVICE_FOUND:
+                    /* NNN uniqueId serviceName regType */
+                    break;
+                case NativeResponseCode.SERVICE_LOST:
+                    /* NNN uniqueId serviceName regType */
+                    break;
+                case NativeResponseCode.SERVICE_DISCOVERY_FAILED:
+                    /* NNN uniqueId errorCode */
+                    break;
+                case NativeResponseCode.SERVICE_REGISTERED:
+                    /* NNN regId serviceName regType */
+                    break;
+                case NativeResponseCode.SERVICE_REGISTRATION_FAILED:
+                    /* NNN regId errorCode */
+                    break;
+                case NativeResponseCode.SERVICE_UPDATED:
+                    /* NNN regId */
+                    break;
+                case NativeResponseCode.SERVICE_UPDATE_FAILED:
+                    /* NNN regId errorCode */
+                    break;
+                case NativeResponseCode.SERVICE_RESOLVED:
+                    /* NNN resolveId fullName hostName port txtlen txtdata */
+                    break;
+                case NativeResponseCode.SERVICE_RESOLUTION_FAILED:
+                    /* NNN resovleId errorCode */
+                    break;
+                default:
+                    break;
+            }
+            return false;
+        }
+    }
+
+    private void registerService(int regId, DnsSdServiceInfo service) {
+        try {
+            //Add txtlen and txtdata
+            mNativeConnector.execute("mdnssd", "register", regId, service.getServiceName(),
+                    service.getServiceType(), service.getPort());
+        } catch(NativeDaemonConnectorException e) {
+            Slog.e(TAG, "Failed to execute registerService");
+        }
+    }
+
+    private void updateService(int regId, DnsSdTxtRecord t) {
+        try {
+            if (t == null) return;
+            mNativeConnector.execute("mdnssd", "update", regId, t.size(), t.getRawData());
+        } catch(NativeDaemonConnectorException e) {
+            Slog.e(TAG, "Failed to updateServices");
+        }
+    }
+
+    private void discoverServices(int discoveryId, String serviceType) {
+        try {
+            mNativeConnector.execute("mdnssd", "discover", discoveryId, serviceType);
+        } catch(NativeDaemonConnectorException e) {
+            Slog.e(TAG, "Failed to discoverServices");
+        }
+    }
+
+    private void stopServiceDiscovery(int discoveryId) {
+        try {
+            mNativeConnector.execute("mdnssd", "stopdiscover", discoveryId);
+        } catch(NativeDaemonConnectorException e) {
+            Slog.e(TAG, "Failed to stopServiceDiscovery");
+        }
+    }
+
+    private void resolveService(DnsSdServiceInfo service) {
+        try {
+        mNativeConnector.execute("mdnssd", "resolve", service.getServiceName(),
+                service.getServiceType());
+        } catch(NativeDaemonConnectorException e) {
+            Slog.e(TAG, "Failed to resolveService");
+        }
+    }
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+                != PackageManager.PERMISSION_GRANTED) {
+            pw.println("Permission Denial: can't dump ServiceDiscoverService from from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid());
+            return;
+        }
+
+        pw.println("Internal state:");
+    }
+}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 423dad6..7dd736d 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -47,6 +47,7 @@
 import com.android.internal.app.ShutdownThread;
 import com.android.internal.os.BinderInternal;
 import com.android.internal.os.SamplingProfilerIntegration;
+import com.android.internal.widget.LockSettingsService;
 import com.android.server.accessibility.AccessibilityManagerService;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.net.NetworkPolicyManagerService;
@@ -120,6 +121,7 @@
         ConnectivityService connectivity = null;
         WifiP2pService wifiP2p = null;
         WifiService wifi = null;
+        NsdService serviceDiscovery= null;
         IPackageManager pm = null;
         Context context = null;
         WindowManagerService wm = null;
@@ -219,6 +221,7 @@
                     factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,
                     !firstBoot);
             ServiceManager.addService(Context.WINDOW_SERVICE, wm);
+            ServiceManager.addService(Context.INPUT_SERVICE, wm.getInputManagerService());
 
             ActivityManagerService.self().setWindowManager(wm);
 
@@ -265,6 +268,7 @@
         LocationManagerService location = null;
         CountryDetectorService countryDetector = null;
         TextServicesManagerService tsms = null;
+        LockSettingsService lockSettings = null;
 
         // Bring up services needed for UI.
         if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
@@ -307,6 +311,14 @@
 
         if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
             try {
+                Slog.i(TAG,  "LockSettingsService");
+                lockSettings = new LockSettingsService(context);
+                ServiceManager.addService("lock_settings", lockSettings);
+            } catch (Throwable e) {
+                reportWtf("starting LockSettingsService service", e);
+            }
+
+            try {
                 Slog.i(TAG, "Device Policy");
                 devicePolicy = new DevicePolicyManagerService(context);
                 ServiceManager.addService(Context.DEVICE_POLICY_SERVICE, devicePolicy);
@@ -394,6 +406,15 @@
             }
 
             try {
+                Slog.i(TAG, "Network Service Discovery Service");
+                serviceDiscovery = NsdService.create(context);
+                ServiceManager.addService(
+                        Context.NSD_SERVICE, serviceDiscovery);
+            } catch (Throwable e) {
+                reportWtf("starting Service Discovery Service", e);
+            }
+
+            try {
                 Slog.i(TAG, "Throttle Service");
                 throttle = new ThrottleService(context);
                 ServiceManager.addService(
@@ -651,6 +672,11 @@
         } catch (Throwable e) {
             reportWtf("making Package Manager Service ready", e);
         }
+        try {
+            lockSettings.systemReady();
+        } catch (Throwable e) {
+            reportWtf("making Lock Settings Service ready", e);
+        }
 
         // These are needed to propagate to the runnable below.
         final Context contextF = context;
diff --git a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
index 769cb6a..31aa21e 100644
--- a/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -16,7 +16,7 @@
 
 package com.android.server.accessibility;
 
-import com.android.server.wm.InputFilter;
+import com.android.server.input.InputFilter;
 
 import android.content.Context;
 import android.util.Slog;
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index 41cf9a6..d07aa7a 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -29,7 +29,7 @@
 import android.view.accessibility.AccessibilityManager;
 
 import com.android.server.accessibility.AccessibilityInputFilter.Explorer;
-import com.android.server.wm.InputFilter;
+import com.android.server.input.InputFilter;
 
 import java.util.Arrays;
 
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index a6fbdd7..2da827e 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -62,10 +62,10 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.IIntentReceiver;
 import android.content.IIntentSender;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.IntentSender;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
@@ -75,12 +75,12 @@
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PathPermission;
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.UserInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
@@ -113,10 +113,10 @@
 import android.provider.Settings;
 import android.text.format.Time;
 import android.util.EventLog;
-import android.util.Pair;
-import android.util.Slog;
 import android.util.Log;
+import android.util.Pair;
 import android.util.PrintWriterPrinter;
+import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.util.TimeUtils;
@@ -140,7 +140,6 @@
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
 import java.io.StringWriter;
-import java.lang.IllegalStateException;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -10263,6 +10262,29 @@
             }
             pw.println();
             pw.print("Total PSS: "); pw.print(totalPss); pw.println(" kB");
+            final int[] SINGLE_LONG_FORMAT = new int[] {
+                Process.PROC_SPACE_TERM|Process.PROC_OUT_LONG
+            };
+            long[] longOut = new long[1];
+            Process.readProcFile("/sys/kernel/mm/ksm/pages_shared",
+                    SINGLE_LONG_FORMAT, null, longOut, null);
+            long shared = longOut[0] * ProcessList.PAGE_SIZE / 1024;
+            longOut[0] = 0;
+            Process.readProcFile("/sys/kernel/mm/ksm/pages_sharing",
+                    SINGLE_LONG_FORMAT, null, longOut, null);
+            long sharing = longOut[0] * ProcessList.PAGE_SIZE / 1024;
+            longOut[0] = 0;
+            Process.readProcFile("/sys/kernel/mm/ksm/pages_unshared",
+                    SINGLE_LONG_FORMAT, null, longOut, null);
+            long unshared = longOut[0] * ProcessList.PAGE_SIZE / 1024;
+            longOut[0] = 0;
+            Process.readProcFile("/sys/kernel/mm/ksm/pages_volatile",
+                    SINGLE_LONG_FORMAT, null, longOut, null);
+            long voltile = longOut[0] * ProcessList.PAGE_SIZE / 1024;
+            pw.print("      KSM: "); pw.print(sharing); pw.print(" kB saved from shared ");
+                    pw.print(shared); pw.println(" kB");
+            pw.print("           "); pw.print(unshared); pw.print(" kB unshared; ");
+                    pw.print(voltile); pw.println(" kB volatile");
         }
     }
 
@@ -13281,6 +13303,102 @@
         }
     }
 
+    @Override
+    public boolean targetTaskAffinityMatchesActivity(IBinder token, String destAffinity) {
+        ActivityRecord srec = ActivityRecord.forToken(token);
+        return srec.task.affinity != null && srec.task.affinity.equals(destAffinity);
+    }
+
+    public boolean navigateUpTo(IBinder token, Intent destIntent, int resultCode,
+            Intent resultData) {
+        ComponentName dest = destIntent.getComponent();
+
+        synchronized (this) {
+            ActivityRecord srec = ActivityRecord.forToken(token);
+            ArrayList<ActivityRecord> history = srec.stack.mHistory;
+            final int start = history.indexOf(srec);
+            if (start < 0) {
+                // Current activity is not in history stack; do nothing.
+                return false;
+            }
+            int finishTo = start - 1;
+            ActivityRecord parent = null;
+            boolean foundParentInTask = false;
+            if (dest != null) {
+                TaskRecord tr = srec.task;
+                for (int i = start - 1; i >= 0; i--) {
+                    ActivityRecord r = history.get(i);
+                    if (tr != r.task) {
+                        // Couldn't find parent in the same task; stop at the one above this.
+                        // (Root of current task; in-app "home" behavior)
+                        // Always at least finish the current activity.
+                        finishTo = Math.min(start - 1, i + 1);
+                        parent = history.get(finishTo);
+                        break;
+                    } else if (r.info.packageName.equals(dest.getPackageName()) &&
+                            r.info.name.equals(dest.getClassName())) {
+                        finishTo = i;
+                        parent = r;
+                        foundParentInTask = true;
+                        break;
+                    }
+                }
+            }
+
+            if (mController != null) {
+                ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
+                if (next != null) {
+                    // ask watcher if this is allowed
+                    boolean resumeOK = true;
+                    try {
+                        resumeOK = mController.activityResuming(next.packageName);
+                    } catch (RemoteException e) {
+                        mController = null;
+                    }
+
+                    if (!resumeOK) {
+                        return false;
+                    }
+                }
+            }
+            final long origId = Binder.clearCallingIdentity();
+            for (int i = start; i > finishTo; i--) {
+                ActivityRecord r = history.get(i);
+                mMainStack.requestFinishActivityLocked(r.appToken, resultCode, resultData,
+                        "navigate-up");
+                // Only return the supplied result for the first activity finished
+                resultCode = Activity.RESULT_CANCELED;
+                resultData = null;
+            }
+
+            if (parent != null && foundParentInTask) {
+                final int parentLaunchMode = parent.info.launchMode;
+                final int destIntentFlags = destIntent.getFlags();
+                if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE ||
+                        parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK ||
+                        parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP ||
+                        (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
+                    parent.deliverNewIntentLocked(srec.app.uid, destIntent);
+                } else {
+                    try {
+                        ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
+                                destIntent.getComponent(), 0, UserId.getCallingUserId());
+                        int res = mMainStack.startActivityLocked(srec.app.thread, destIntent,
+                                null, aInfo, parent.appToken, null,
+                                0, -1, parent.launchedFromUid, 0, null, true, null);
+                        foundParentInTask = res == ActivityManager.START_SUCCESS;
+                    } catch (RemoteException e) {
+                        foundParentInTask = false;
+                    }
+                    mMainStack.requestFinishActivityLocked(parent.appToken, resultCode,
+                            resultData, "navigate-up");
+                }
+            }
+            Binder.restoreCallingIdentity(origId);
+            return foundParentInTask;
+        }
+    }
+
     // =========================================================
     // LIFETIME MANAGEMENT
     // =========================================================
diff --git a/services/java/com/android/server/wm/InputApplicationHandle.java b/services/java/com/android/server/input/InputApplicationHandle.java
similarity index 90%
rename from services/java/com/android/server/wm/InputApplicationHandle.java
rename to services/java/com/android/server/input/InputApplicationHandle.java
index 1812f11..42c1052 100644
--- a/services/java/com/android/server/wm/InputApplicationHandle.java
+++ b/services/java/com/android/server/input/InputApplicationHandle.java
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.wm;
-
+package com.android.server.input;
 
 /**
  * Functions as a handle for an application that can receive input.
@@ -30,7 +29,7 @@
     private int ptr;
 
     // The window manager's application window token.
-    public final AppWindowToken appWindowToken;
+    public final Object appWindowToken;
 
     // Application name.
     public String name;
@@ -40,7 +39,7 @@
 
     private native void nativeDispose();
 
-    public InputApplicationHandle(AppWindowToken appWindowToken) {
+    public InputApplicationHandle(Object appWindowToken) {
         this.appWindowToken = appWindowToken;
     }
 
diff --git a/services/java/com/android/server/wm/InputFilter.java b/services/java/com/android/server/input/InputFilter.java
similarity index 96%
rename from services/java/com/android/server/wm/InputFilter.java
rename to services/java/com/android/server/input/InputFilter.java
index 8f0001a..2ce0a02 100644
--- a/services/java/com/android/server/wm/InputFilter.java
+++ b/services/java/com/android/server/input/InputFilter.java
@@ -14,7 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.server.wm;
+package com.android.server.input;
+
+import com.android.server.wm.WindowManagerService;
 
 import android.os.Handler;
 import android.os.Looper;
@@ -33,7 +35,7 @@
  * system's behavior changes as follows:
  * <ul>
  * <li>Input events are first delivered to the {@link WindowManagerPolicy}
- * interception methods before queueing as usual.  This critical step takes care of managing
+ * interception methods before queuing as usual.  This critical step takes care of managing
  * the power state of the device and handling wake keys.</li>
  * <li>Input events are then asynchronously delivered to the input filter's
  * {@link #onInputEvent(InputEvent)} method instead of being enqueued for dispatch to
@@ -79,7 +81,7 @@
  * {@link WindowManagerPolicy#FLAG_PASS_TO_USER} policy flag.  The input filter may
  * sometimes receive events that do not have this flag set.  It should take note of
  * the fact that the policy intends to drop the event, clean up its state, and
- * then send appropriate cancelation events to the dispatcher if needed.
+ * then send appropriate cancellation events to the dispatcher if needed.
  * </p><p>
  * For example, suppose the input filter is processing a gesture and one of the touch events
  * it receives does not have the {@link WindowManagerPolicy#FLAG_PASS_TO_USER} flag set.
@@ -89,8 +91,8 @@
  * Corollary: Events that set sent to the dispatcher should usually include the
  * {@link WindowManagerPolicy#FLAG_PASS_TO_USER} flag.  Otherwise, they will be dropped!
  * </p><p>
- * It may be prudent to disable automatic key repeating for synthetically generated
- * keys by setting the {@link WindowManagerPolicy#FLAG_DISABLE_KEY_REPEAT} policy flag.
+ * It may be prudent to disable automatic key repeating for synthetic key events
+ * by setting the {@link WindowManagerPolicy#FLAG_DISABLE_KEY_REPEAT} policy flag.
  * </p>
  */
 public abstract class InputFilter {
diff --git a/services/java/com/android/server/wm/InputManager.java b/services/java/com/android/server/input/InputManagerService.java
similarity index 60%
rename from services/java/com/android/server/wm/InputManager.java
rename to services/java/com/android/server/input/InputManagerService.java
index 56c3519..6a566ae 100644
--- a/services/java/com/android/server/wm/InputManager.java
+++ b/services/java/com/android/server/input/InputManagerService.java
@@ -14,10 +14,12 @@
  * limitations under the License.
  */
 
-package com.android.server.wm;
+package com.android.server.input;
 
 import com.android.internal.util.XmlUtils;
 import com.android.server.Watchdog;
+import com.android.server.input.InputFilter.Host;
+import com.android.server.wm.WindowManagerService;
 
 import org.xmlpull.v1.XmlPullParser;
 
@@ -25,7 +27,10 @@
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.database.ContentObserver;
+import android.hardware.input.IInputManager;
+import android.os.Binder;
 import android.os.Environment;
+import android.os.Handler;
 import android.os.Looper;
 import android.os.MessageQueue;
 import android.os.SystemProperties;
@@ -44,6 +49,7 @@
 import android.view.WindowManagerPolicy;
 
 import java.io.File;
+import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
@@ -53,61 +59,66 @@
 /*
  * Wraps the C++ InputManager and provides its callbacks.
  */
-public class InputManager implements Watchdog.Monitor {
+public class InputManagerService extends IInputManager.Stub implements Watchdog.Monitor {
     static final String TAG = "InputManager";
-    
-    private static final boolean DEBUG = false;
+    static final boolean DEBUG = false;
 
-    private final Callbacks mCallbacks;
+    private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
+
+    // Pointer to native input manager service object.
+    private final int mPtr;
+
     private final Context mContext;
-    private final WindowManagerService mWindowManagerService;
+    private final Callbacks mCallbacks;
+    private final Handler mHandler;
 
-    private static native void nativeInit(Context context,
-            Callbacks callbacks, MessageQueue messageQueue);
-    private static native void nativeStart();
-    private static native void nativeSetDisplaySize(int displayId, int width, int height,
-            int externalWidth, int externalHeight);
-    private static native void nativeSetDisplayOrientation(int displayId, int rotation);
+    private static native int nativeInit(InputManagerService service,
+            Context context, MessageQueue messageQueue);
+    private static native void nativeStart(int ptr);
+    private static native void nativeSetDisplaySize(int ptr, int displayId,
+            int width, int height, int externalWidth, int externalHeight);
+    private static native void nativeSetDisplayOrientation(int ptr, int displayId, int rotation);
     
-    private static native int nativeGetScanCodeState(int deviceId, int sourceMask,
-            int scanCode);
-    private static native int nativeGetKeyCodeState(int deviceId, int sourceMask,
-            int keyCode);
-    private static native int nativeGetSwitchState(int deviceId, int sourceMask,
-            int sw);
-    private static native boolean nativeHasKeys(int deviceId, int sourceMask,
-            int[] keyCodes, boolean[] keyExists);
-    private static native void nativeRegisterInputChannel(InputChannel inputChannel,
+    private static native int nativeGetScanCodeState(int ptr,
+            int deviceId, int sourceMask, int scanCode);
+    private static native int nativeGetKeyCodeState(int ptr,
+            int deviceId, int sourceMask, int keyCode);
+    private static native int nativeGetSwitchState(int ptr,
+            int deviceId, int sourceMask, int sw);
+    private static native boolean nativeHasKeys(int ptr,
+            int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists);
+    private static native void nativeRegisterInputChannel(int ptr, InputChannel inputChannel,
             InputWindowHandle inputWindowHandle, boolean monitor);
-    private static native void nativeUnregisterInputChannel(InputChannel inputChannel);
-    private static native void nativeSetInputFilterEnabled(boolean enable);
-    private static native int nativeInjectInputEvent(InputEvent event,
+    private static native void nativeUnregisterInputChannel(int ptr, InputChannel inputChannel);
+    private static native void nativeSetInputFilterEnabled(int ptr, boolean enable);
+    private static native int nativeInjectInputEvent(int ptr, InputEvent event,
             int injectorPid, int injectorUid, int syncMode, int timeoutMillis,
             int policyFlags);
-    private static native void nativeSetInputWindows(InputWindowHandle[] windowHandles);
-    private static native void nativeSetInputDispatchMode(boolean enabled, boolean frozen);
-    private static native void nativeSetSystemUiVisibility(int visibility);
-    private static native void nativeSetFocusedApplication(InputApplicationHandle application);
-    private static native InputDevice nativeGetInputDevice(int deviceId);
-    private static native void nativeGetInputConfiguration(Configuration configuration);
-    private static native int[] nativeGetInputDeviceIds();
-    private static native boolean nativeTransferTouchFocus(InputChannel fromChannel,
-            InputChannel toChannel);
-    private static native void nativeSetPointerSpeed(int speed);
-    private static native void nativeSetShowTouches(boolean enabled);
-    private static native String nativeDump();
-    private static native void nativeMonitor();
+    private static native void nativeSetInputWindows(int ptr, InputWindowHandle[] windowHandles);
+    private static native void nativeSetInputDispatchMode(int ptr, boolean enabled, boolean frozen);
+    private static native void nativeSetSystemUiVisibility(int ptr, int visibility);
+    private static native void nativeSetFocusedApplication(int ptr,
+            InputApplicationHandle application);
+    private static native InputDevice nativeGetInputDevice(int ptr, int deviceId);
+    private static native void nativeGetInputConfiguration(int ptr, Configuration configuration);
+    private static native int[] nativeGetInputDeviceIds(int ptr);
+    private static native boolean nativeTransferTouchFocus(int ptr,
+            InputChannel fromChannel, InputChannel toChannel);
+    private static native void nativeSetPointerSpeed(int ptr, int speed);
+    private static native void nativeSetShowTouches(int ptr, boolean enabled);
+    private static native String nativeDump(int ptr);
+    private static native void nativeMonitor(int ptr);
     
     // Input event injection constants defined in InputDispatcher.h.
-    static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
-    static final int INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1;
-    static final int INPUT_EVENT_INJECTION_FAILED = 2;
-    static final int INPUT_EVENT_INJECTION_TIMED_OUT = 3;
-    
+    public static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
+    public static final int INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1;
+    public static final int INPUT_EVENT_INJECTION_FAILED = 2;
+    public static final int INPUT_EVENT_INJECTION_TIMED_OUT = 3;
+
     // Input event injection synchronization modes defined in InputDispatcher.h
-    static final int INPUT_EVENT_INJECTION_SYNC_NONE = 0;
-    static final int INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT = 1;
-    static final int INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH = 2;
+    public static final int INPUT_EVENT_INJECTION_SYNC_NONE = 0;
+    public static final int INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT = 1;
+    public static final int INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH = 2;
     
     // Key states (may be returned by queries about the current state of a
     // particular key code, scan code or switch).
@@ -129,23 +140,21 @@
     InputFilter mInputFilter;
     InputFilterHost mInputFilterHost;
 
-    public InputManager(Context context, WindowManagerService windowManagerService) {
+    public InputManagerService(Context context, Callbacks callbacks) {
         this.mContext = context;
-        this.mWindowManagerService = windowManagerService;
-        this.mCallbacks = new Callbacks();
-
-        Looper looper = windowManagerService.mH.getLooper();
+        this.mCallbacks = callbacks;
+        this.mHandler = new Handler();
 
         Slog.i(TAG, "Initializing input manager");
-        nativeInit(mContext, mCallbacks, looper.getQueue());
-
-        // Add ourself to the Watchdog monitors.
-        Watchdog.getInstance().addMonitor(this);
+        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
     }
 
     public void start() {
         Slog.i(TAG, "Starting input manager");
-        nativeStart();
+        nativeStart(mPtr);
+
+        // Add ourself to the Watchdog monitors.
+        Watchdog.getInstance().addMonitor(this);
 
         registerPointerSpeedSettingObserver();
         registerShowTouchesSettingObserver();
@@ -164,7 +173,7 @@
             Slog.d(TAG, "Setting display #" + displayId + " size to " + width + "x" + height
                     + " external size " + externalWidth + "x" + externalHeight);
         }
-        nativeSetDisplaySize(displayId, width, height, externalWidth, externalHeight);
+        nativeSetDisplaySize(mPtr, displayId, width, height, externalWidth, externalHeight);
     }
     
     public void setDisplayOrientation(int displayId, int rotation) {
@@ -175,7 +184,7 @@
         if (DEBUG) {
             Slog.d(TAG, "Setting display #" + displayId + " orientation to " + rotation);
         }
-        nativeSetDisplayOrientation(displayId, rotation);
+        nativeSetDisplayOrientation(mPtr, displayId, rotation);
     }
     
     public void getInputConfiguration(Configuration config) {
@@ -183,7 +192,7 @@
             throw new IllegalArgumentException("config must not be null.");
         }
         
-        nativeGetInputConfiguration(config);
+        nativeGetInputConfiguration(mPtr, config);
     }
     
     /**
@@ -196,7 +205,7 @@
      * @return The key state.
      */
     public int getKeyCodeState(int deviceId, int sourceMask, int keyCode) {
-        return nativeGetKeyCodeState(deviceId, sourceMask, keyCode);
+        return nativeGetKeyCodeState(mPtr, deviceId, sourceMask, keyCode);
     }
     
     /**
@@ -209,7 +218,7 @@
      * @return The key state.
      */
     public int getScanCodeState(int deviceId, int sourceMask, int scanCode) {
-        return nativeGetScanCodeState(deviceId, sourceMask, scanCode);
+        return nativeGetScanCodeState(mPtr, deviceId, sourceMask, scanCode);
     }
     
     /**
@@ -222,7 +231,7 @@
      * @return The switch state.
      */
     public int getSwitchState(int deviceId, int sourceMask, int switchCode) {
-        return nativeGetSwitchState(deviceId, sourceMask, switchCode);
+        return nativeGetSwitchState(mPtr, deviceId, sourceMask, switchCode);
     }
 
     /**
@@ -246,7 +255,7 @@
                     + "least as large as keyCodes.");
         }
         
-        return nativeHasKeys(deviceId, sourceMask, keyCodes, keyExists);
+        return nativeHasKeys(mPtr, deviceId, sourceMask, keyCodes, keyExists);
     }
     
     /**
@@ -260,7 +269,7 @@
         }
         
         InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
-        nativeRegisterInputChannel(inputChannels[0], null, true);
+        nativeRegisterInputChannel(mPtr, inputChannels[0], null, true);
         inputChannels[0].dispose(); // don't need to retain the Java object reference
         return inputChannels[1];
     }
@@ -277,7 +286,7 @@
             throw new IllegalArgumentException("inputChannel must not be null.");
         }
         
-        nativeRegisterInputChannel(inputChannel, inputWindowHandle, false);
+        nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false);
     }
     
     /**
@@ -289,7 +298,7 @@
             throw new IllegalArgumentException("inputChannel must not be null.");
         }
         
-        nativeUnregisterInputChannel(inputChannel);
+        nativeUnregisterInputChannel(mPtr, inputChannel);
     }
 
     /**
@@ -323,7 +332,7 @@
                 filter.install(mInputFilterHost);
             }
 
-            nativeSetInputFilterEnabled(filter != null);
+            nativeSetInputFilterEnabled(mPtr, filter != null);
         }
     }
 
@@ -362,8 +371,8 @@
             throw new IllegalArgumentException("timeoutMillis must be positive");
         }
 
-        return nativeInjectInputEvent(event, injectorPid, injectorUid, syncMode, timeoutMillis,
-                WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);
+        return nativeInjectInputEvent(mPtr, event, injectorPid, injectorUid, syncMode,
+                timeoutMillis, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);
     }
 
     /**
@@ -372,7 +381,7 @@
      * @return The input device or null if not found.
      */
     public InputDevice getInputDevice(int deviceId) {
-        return nativeGetInputDevice(deviceId);
+        return nativeGetInputDevice(mPtr, deviceId);
     }
     
     /**
@@ -380,23 +389,23 @@
      * @return The input device ids.
      */
     public int[] getInputDeviceIds() {
-        return nativeGetInputDeviceIds();
+        return nativeGetInputDeviceIds(mPtr);
     }
     
     public void setInputWindows(InputWindowHandle[] windowHandles) {
-        nativeSetInputWindows(windowHandles);
+        nativeSetInputWindows(mPtr, windowHandles);
     }
     
     public void setFocusedApplication(InputApplicationHandle application) {
-        nativeSetFocusedApplication(application);
+        nativeSetFocusedApplication(mPtr, application);
     }
     
     public void setInputDispatchMode(boolean enabled, boolean frozen) {
-        nativeSetInputDispatchMode(enabled, frozen);
+        nativeSetInputDispatchMode(mPtr, enabled, frozen);
     }
 
     public void setSystemUiVisibility(int visibility) {
-        nativeSetSystemUiVisibility(visibility);
+        nativeSetSystemUiVisibility(mPtr, visibility);
     }
 
     /**
@@ -419,7 +428,7 @@
         if (toChannel == null) {
             throw new IllegalArgumentException("toChannel must not be null.");
         }
-        return nativeTransferTouchFocus(fromChannel, toChannel);
+        return nativeTransferTouchFocus(mPtr, fromChannel, toChannel);
     }
 
     /**
@@ -429,7 +438,7 @@
      */
     public void setPointerSpeed(int speed) {
         speed = Math.min(Math.max(speed, -7), 7);
-        nativeSetPointerSpeed(speed);
+        nativeSetPointerSpeed(mPtr, speed);
     }
 
     public void updatePointerSpeedFromSettings() {
@@ -440,7 +449,7 @@
     private void registerPointerSpeedSettingObserver() {
         mContext.getContentResolver().registerContentObserver(
                 Settings.System.getUriFor(Settings.System.POINTER_SPEED), true,
-                new ContentObserver(mWindowManagerService.mH) {
+                new ContentObserver(mHandler) {
                     @Override
                     public void onChange(boolean selfChange) {
                         updatePointerSpeedFromSettings();
@@ -460,13 +469,13 @@
 
     public void updateShowTouchesFromSettings() {
         int setting = getShowTouchesSetting(0);
-        nativeSetShowTouches(setting != 0);
+        nativeSetShowTouches(mPtr, setting != 0);
     }
 
     private void registerShowTouchesSettingObserver() {
         mContext.getContentResolver().registerContentObserver(
                 Settings.System.getUriFor(Settings.System.SHOW_TOUCHES), true,
-                new ContentObserver(mWindowManagerService.mH) {
+                new ContentObserver(mHandler) {
                     @Override
                     public void onChange(boolean selfChange) {
                         updateShowTouchesFromSettings();
@@ -484,19 +493,202 @@
         return result;
     }
 
-    public void dump(PrintWriter pw) {
-        String dumpStr = nativeDump();
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
+                != PackageManager.PERMISSION_GRANTED) {
+            pw.println("Permission Denial: can't dump InputManager from from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid());
+            return;
+        }
+
+        pw.println("INPUT MANAGER (dumpsys input)\n");
+        String dumpStr = nativeDump(mPtr);
         if (dumpStr != null) {
             pw.println(dumpStr);
         }
     }
 
-    // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
+    // Called by the heartbeat to ensure locks are not held indefinitely (for deadlock detection).
     public void monitor() {
         synchronized (mInputFilterLock) { }
-        nativeMonitor();
+        nativeMonitor(mPtr);
     }
 
+    // Native callback.
+    private void notifyConfigurationChanged(long whenNanos) {
+        mCallbacks.notifyConfigurationChanged();
+    }
+
+    // Native callback.
+    private void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
+        mCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
+    }
+
+    // Native callback.
+    private void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
+        mCallbacks.notifyInputChannelBroken(inputWindowHandle);
+    }
+
+    // Native callback.
+    private long notifyANR(InputApplicationHandle inputApplicationHandle,
+            InputWindowHandle inputWindowHandle) {
+        return mCallbacks.notifyANR(inputApplicationHandle, inputWindowHandle);
+    }
+
+    // Native callback.
+    final boolean filterInputEvent(InputEvent event, int policyFlags) {
+        synchronized (mInputFilterLock) {
+            if (mInputFilter != null) {
+                mInputFilter.filterInputEvent(event, policyFlags);
+                return false;
+            }
+        }
+        event.recycle();
+        return true;
+    }
+
+    // Native callback.
+    private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
+        return mCallbacks.interceptKeyBeforeQueueing(
+                event, policyFlags, isScreenOn);
+    }
+
+    // Native callback.
+    private int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
+        return mCallbacks.interceptMotionBeforeQueueingWhenScreenOff(policyFlags);
+    }
+
+    // Native callback.
+    private long interceptKeyBeforeDispatching(InputWindowHandle focus,
+            KeyEvent event, int policyFlags) {
+        return mCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags);
+    }
+
+    // Native callback.
+    private KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
+            KeyEvent event, int policyFlags) {
+        return mCallbacks.dispatchUnhandledKey(focus, event, policyFlags);
+    }
+
+    // Native callback.
+    private boolean checkInjectEventsPermission(int injectorPid, int injectorUid) {
+        return mContext.checkPermission(android.Manifest.permission.INJECT_EVENTS,
+                injectorPid, injectorUid) == PackageManager.PERMISSION_GRANTED;
+    }
+
+    // Native callback.
+    private int getVirtualKeyQuietTimeMillis() {
+        return mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_virtualKeyQuietTimeMillis);
+    }
+
+    // Native callback.
+    private String[] getExcludedDeviceNames() {
+        ArrayList<String> names = new ArrayList<String>();
+
+        // Read partner-provided list of excluded input devices
+        XmlPullParser parser = null;
+        // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
+        File confFile = new File(Environment.getRootDirectory(), EXCLUDED_DEVICES_PATH);
+        FileReader confreader = null;
+        try {
+            confreader = new FileReader(confFile);
+            parser = Xml.newPullParser();
+            parser.setInput(confreader);
+            XmlUtils.beginDocument(parser, "devices");
+
+            while (true) {
+                XmlUtils.nextElement(parser);
+                if (!"device".equals(parser.getName())) {
+                    break;
+                }
+                String name = parser.getAttributeValue(null, "name");
+                if (name != null) {
+                    names.add(name);
+                }
+            }
+        } catch (FileNotFoundException e) {
+            // It's ok if the file does not exist.
+        } catch (Exception e) {
+            Slog.e(TAG, "Exception while parsing '" + confFile.getAbsolutePath() + "'", e);
+        } finally {
+            try { if (confreader != null) confreader.close(); } catch (IOException e) { }
+        }
+
+        return names.toArray(new String[names.size()]);
+    }
+
+    // Native callback.
+    private int getKeyRepeatTimeout() {
+        return ViewConfiguration.getKeyRepeatTimeout();
+    }
+
+    // Native callback.
+    private int getKeyRepeatDelay() {
+        return ViewConfiguration.getKeyRepeatDelay();
+    }
+
+    // Native callback.
+    private int getHoverTapTimeout() {
+        return ViewConfiguration.getHoverTapTimeout();
+    }
+
+    // Native callback.
+    private int getHoverTapSlop() {
+        return ViewConfiguration.getHoverTapSlop();
+    }
+
+    // Native callback.
+    private int getDoubleTapTimeout() {
+        return ViewConfiguration.getDoubleTapTimeout();
+    }
+
+    // Native callback.
+    private int getLongPressTimeout() {
+        return ViewConfiguration.getLongPressTimeout();
+    }
+
+    // Native callback.
+    private int getPointerLayer() {
+        return mCallbacks.getPointerLayer();
+    }
+
+    // Native callback.
+    private PointerIcon getPointerIcon() {
+        return PointerIcon.getDefaultIcon(mContext);
+    }
+
+    /**
+     * Callback interface implemented by the Window Manager.
+     */
+    public interface Callbacks {
+        public void notifyConfigurationChanged();
+
+        public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen);
+
+        public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle);
+
+        public long notifyANR(InputApplicationHandle inputApplicationHandle,
+                InputWindowHandle inputWindowHandle);
+
+        public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn);
+
+        public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags);
+
+        public long interceptKeyBeforeDispatching(InputWindowHandle focus,
+                KeyEvent event, int policyFlags);
+
+        public KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
+                KeyEvent event, int policyFlags);
+
+        public int getPointerLayer();
+    }
+
+    /**
+     * Hosting interface for input filters to call back into the input manager.
+     */
     private final class InputFilterHost implements InputFilter.Host {
         private boolean mDisconnected;
 
@@ -511,173 +703,10 @@
 
             synchronized (mInputFilterLock) {
                 if (!mDisconnected) {
-                    nativeInjectInputEvent(event, 0, 0, INPUT_EVENT_INJECTION_SYNC_NONE, 0,
+                    nativeInjectInputEvent(mPtr, event, 0, 0, INPUT_EVENT_INJECTION_SYNC_NONE, 0,
                             policyFlags | WindowManagerPolicy.FLAG_FILTERED);
                 }
             }
         }
     }
-
-    /*
-     * Callbacks from native.
-     */
-    private final class Callbacks {
-        static final String TAG = "InputManager-Callbacks";
-        
-        private static final boolean DEBUG_VIRTUAL_KEYS = false;
-        private static final String EXCLUDED_DEVICES_PATH = "etc/excluded-input-devices.xml";
-        private static final String CALIBRATION_DIR_PATH = "usr/idc/";
-        
-        @SuppressWarnings("unused")
-        public void notifyConfigurationChanged(long whenNanos) {
-            mWindowManagerService.mInputMonitor.notifyConfigurationChanged();
-        }
-        
-        @SuppressWarnings("unused")
-        public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
-            mWindowManagerService.mInputMonitor.notifyLidSwitchChanged(whenNanos, lidOpen);
-        }
-        
-        @SuppressWarnings("unused")
-        public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle) {
-            mWindowManagerService.mInputMonitor.notifyInputChannelBroken(inputWindowHandle);
-        }
-        
-        @SuppressWarnings("unused")
-        public long notifyANR(InputApplicationHandle inputApplicationHandle,
-                InputWindowHandle inputWindowHandle) {
-            return mWindowManagerService.mInputMonitor.notifyANR(
-                    inputApplicationHandle, inputWindowHandle);
-        }
-
-        @SuppressWarnings("unused")
-        final boolean filterInputEvent(InputEvent event, int policyFlags) {
-            synchronized (mInputFilterLock) {
-                if (mInputFilter != null) {
-                    mInputFilter.filterInputEvent(event, policyFlags);
-                    return false;
-                }
-            }
-            event.recycle();
-            return true;
-        }
-
-        @SuppressWarnings("unused")
-        public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
-            return mWindowManagerService.mInputMonitor.interceptKeyBeforeQueueing(
-                    event, policyFlags, isScreenOn);
-        }
-
-        @SuppressWarnings("unused")
-        public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
-            return mWindowManagerService.mInputMonitor.interceptMotionBeforeQueueingWhenScreenOff(
-                    policyFlags);
-        }
-
-        @SuppressWarnings("unused")
-        public long interceptKeyBeforeDispatching(InputWindowHandle focus,
-                KeyEvent event, int policyFlags) {
-            return mWindowManagerService.mInputMonitor.interceptKeyBeforeDispatching(
-                    focus, event, policyFlags);
-        }
-        
-        @SuppressWarnings("unused")
-        public KeyEvent dispatchUnhandledKey(InputWindowHandle focus,
-                KeyEvent event, int policyFlags) {
-            return mWindowManagerService.mInputMonitor.dispatchUnhandledKey(
-                    focus, event, policyFlags);
-        }
-        
-        @SuppressWarnings("unused")
-        public boolean checkInjectEventsPermission(int injectorPid, int injectorUid) {
-            return mContext.checkPermission(
-                    android.Manifest.permission.INJECT_EVENTS, injectorPid, injectorUid)
-                    == PackageManager.PERMISSION_GRANTED;
-        }
-
-        @SuppressWarnings("unused")
-        public int getVirtualKeyQuietTimeMillis() {
-            return mContext.getResources().getInteger(
-                    com.android.internal.R.integer.config_virtualKeyQuietTimeMillis);
-        }
-
-        @SuppressWarnings("unused")
-        public String[] getExcludedDeviceNames() {
-            ArrayList<String> names = new ArrayList<String>();
-            
-            // Read partner-provided list of excluded input devices
-            XmlPullParser parser = null;
-            // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
-            File confFile = new File(Environment.getRootDirectory(), EXCLUDED_DEVICES_PATH);
-            FileReader confreader = null;
-            try {
-                confreader = new FileReader(confFile);
-                parser = Xml.newPullParser();
-                parser.setInput(confreader);
-                XmlUtils.beginDocument(parser, "devices");
-
-                while (true) {
-                    XmlUtils.nextElement(parser);
-                    if (!"device".equals(parser.getName())) {
-                        break;
-                    }
-                    String name = parser.getAttributeValue(null, "name");
-                    if (name != null) {
-                        names.add(name);
-                    }
-                }
-            } catch (FileNotFoundException e) {
-                // It's ok if the file does not exist.
-            } catch (Exception e) {
-                Slog.e(TAG, "Exception while parsing '" + confFile.getAbsolutePath() + "'", e);
-            } finally {
-                try { if (confreader != null) confreader.close(); } catch (IOException e) { }
-            }
-            
-            return names.toArray(new String[names.size()]);
-        }
-
-        @SuppressWarnings("unused")
-        public int getKeyRepeatTimeout() {
-            return ViewConfiguration.getKeyRepeatTimeout();
-        }
-
-        @SuppressWarnings("unused")
-        public int getKeyRepeatDelay() {
-            return ViewConfiguration.getKeyRepeatDelay();
-        }
-
-        @SuppressWarnings("unused")
-        public int getHoverTapTimeout() {
-            return ViewConfiguration.getHoverTapTimeout();
-        }
-
-        @SuppressWarnings("unused")
-        public int getHoverTapSlop() {
-            return ViewConfiguration.getHoverTapSlop();
-        }
-
-        @SuppressWarnings("unused")
-        public int getDoubleTapTimeout() {
-            return ViewConfiguration.getDoubleTapTimeout();
-        }
-
-        @SuppressWarnings("unused")
-        public int getLongPressTimeout() {
-            return ViewConfiguration.getLongPressTimeout();
-        }
-
-        @SuppressWarnings("unused")
-        public int getPointerLayer() {
-            return mWindowManagerService.mPolicy.windowTypeToLayerLw(
-                    WindowManager.LayoutParams.TYPE_POINTER)
-                    * WindowManagerService.TYPE_LAYER_MULTIPLIER
-                    + WindowManagerService.TYPE_LAYER_OFFSET;
-        }
-
-        @SuppressWarnings("unused")
-        public PointerIcon getPointerIcon() {
-            return PointerIcon.getDefaultIcon(mContext);
-        }
-    }
 }
diff --git a/services/java/com/android/server/wm/InputWindowHandle.java b/services/java/com/android/server/input/InputWindowHandle.java
similarity index 93%
rename from services/java/com/android/server/wm/InputWindowHandle.java
rename to services/java/com/android/server/input/InputWindowHandle.java
index 264877c..03d66af 100644
--- a/services/java/com/android/server/wm/InputWindowHandle.java
+++ b/services/java/com/android/server/input/InputWindowHandle.java
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.server.wm;
+package com.android.server.input;
 
 import android.graphics.Region;
 import android.view.InputChannel;
-import android.view.WindowManagerPolicy;
 
 /**
  * Functions as a handle for a window that can receive input.
@@ -35,7 +34,7 @@
     public final InputApplicationHandle inputApplicationHandle;
 
     // The window manager's window state.
-    public final WindowManagerPolicy.WindowState windowState;
+    public final Object windowState;
 
     // The input channel associated with the window.
     public InputChannel inputChannel;
@@ -91,7 +90,7 @@
     private native void nativeDispose();
 
     public InputWindowHandle(InputApplicationHandle inputApplicationHandle,
-            WindowManagerPolicy.WindowState windowState) {
+            Object windowState) {
         this.inputApplicationHandle = inputApplicationHandle;
         this.windowState = windowState;
     }
diff --git a/services/java/com/android/server/net/NetworkIdentitySet.java b/services/java/com/android/server/net/NetworkIdentitySet.java
index af03fb3..397f9f4 100644
--- a/services/java/com/android/server/net/NetworkIdentitySet.java
+++ b/services/java/com/android/server/net/NetworkIdentitySet.java
@@ -21,7 +21,6 @@
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
-import java.net.ProtocolException;
 import java.util.HashSet;
 
 /**
@@ -33,48 +32,46 @@
 public class NetworkIdentitySet extends HashSet<NetworkIdentity> {
     private static final int VERSION_INIT = 1;
     private static final int VERSION_ADD_ROAMING = 2;
+    private static final int VERSION_ADD_NETWORK_ID = 3;
 
     public NetworkIdentitySet() {
     }
 
     public NetworkIdentitySet(DataInputStream in) throws IOException {
         final int version = in.readInt();
-        switch (version) {
-            case VERSION_INIT: {
-                final int size = in.readInt();
-                for (int i = 0; i < size; i++) {
-                    final int ignoredVersion = in.readInt();
-                    final int type = in.readInt();
-                    final int subType = in.readInt();
-                    final String subscriberId = readOptionalString(in);
-                    add(new NetworkIdentity(type, subType, subscriberId, false));
-                }
-                break;
+        final int size = in.readInt();
+        for (int i = 0; i < size; i++) {
+            if (version <= VERSION_INIT) {
+                final int ignored = in.readInt();
             }
-            case VERSION_ADD_ROAMING: {
-                final int size = in.readInt();
-                for (int i = 0; i < size; i++) {
-                    final int type = in.readInt();
-                    final int subType = in.readInt();
-                    final String subscriberId = readOptionalString(in);
-                    final boolean roaming = in.readBoolean();
-                    add(new NetworkIdentity(type, subType, subscriberId, roaming));
-                }
-                break;
+            final int type = in.readInt();
+            final int subType = in.readInt();
+            final String subscriberId = readOptionalString(in);
+            final String networkId;
+            if (version >= VERSION_ADD_NETWORK_ID) {
+                networkId = readOptionalString(in);
+            } else {
+                networkId = null;
             }
-            default: {
-                throw new ProtocolException("unexpected version: " + version);
+            final boolean roaming;
+            if (version >= VERSION_ADD_ROAMING) {
+                roaming = in.readBoolean();
+            } else {
+                roaming = false;
             }
+
+            add(new NetworkIdentity(type, subType, subscriberId, networkId, false));
         }
     }
 
     public void writeToStream(DataOutputStream out) throws IOException {
-        out.writeInt(VERSION_ADD_ROAMING);
+        out.writeInt(VERSION_ADD_NETWORK_ID);
         out.writeInt(size());
         for (NetworkIdentity ident : this) {
             out.writeInt(ident.getType());
             out.writeInt(ident.getSubType());
             writeOptionalString(out, ident.getSubscriberId());
+            writeOptionalString(out, ident.getNetworkId());
             out.writeBoolean(ident.getRoaming());
         }
     }
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 1f1e720..b0657a6 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -48,6 +48,7 @@
 import static android.net.NetworkTemplate.MATCH_WIFI;
 import static android.net.NetworkTemplate.buildTemplateMobileAll;
 import static android.net.TrafficStats.MB_IN_BYTES;
+import static android.telephony.TelephonyManager.SIM_STATE_READY;
 import static android.text.format.DateUtils.DAY_IN_MILLIS;
 import static com.android.internal.util.Preconditions.checkNotNull;
 import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
@@ -113,6 +114,7 @@
 import com.android.internal.R;
 import com.android.internal.os.AtomicFile;
 import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Objects;
 import com.google.android.collect.Lists;
 import com.google.android.collect.Maps;
@@ -160,6 +162,8 @@
     private static final int VERSION_ADDED_TIMEZONE = 6;
     private static final int VERSION_ADDED_INFERRED = 7;
     private static final int VERSION_SWITCH_APP_ID = 8;
+    private static final int VERSION_ADDED_NETWORK_ID = 9;
+    private static final int VERSION_LATEST = VERSION_ADDED_NETWORK_ID;
 
     // @VisibleForTesting
     public static final int TYPE_WARNING = 0x1;
@@ -175,6 +179,7 @@
     private static final String ATTR_RESTRICT_BACKGROUND = "restrictBackground";
     private static final String ATTR_NETWORK_TEMPLATE = "networkTemplate";
     private static final String ATTR_SUBSCRIBER_ID = "subscriberId";
+    private static final String ATTR_NETWORK_ID = "networkId";
     private static final String ATTR_CYCLE_DAY = "cycleDay";
     private static final String ATTR_CYCLE_TIMEZONE = "cycleTimezone";
     private static final String ATTR_WARNING_BYTES = "warningBytes";
@@ -491,6 +496,7 @@
         for (NetworkPolicy policy : mNetworkPolicy.values()) {
             // ignore policies that aren't relevant to user
             if (!isTemplateRelevant(policy.template)) continue;
+            if (!policy.hasCycle()) continue;
 
             final long start = computeLastCycleBoundary(currentTime, policy);
             final long end = currentTime;
@@ -528,21 +534,24 @@
 
     /**
      * Test if given {@link NetworkTemplate} is relevant to user based on
-     * current device state, such as when {@link #getActiveSubscriberId()}
-     * matches. This is regardless of data connection status.
+     * current device state, such as when
+     * {@link TelephonyManager#getSubscriberId()} matches. This is regardless of
+     * data connection status.
      */
     private boolean isTemplateRelevant(NetworkTemplate template) {
+        final TelephonyManager tele = TelephonyManager.from(mContext);
+
         switch (template.getMatchRule()) {
             case MATCH_MOBILE_3G_LOWER:
             case MATCH_MOBILE_4G:
             case MATCH_MOBILE_ALL:
-                // mobile templates aren't relevant in airplane mode
-                if (isAirplaneModeOn(mContext)) {
+                // mobile templates are relevant when SIM is ready and
+                // subscriberId matches.
+                if (tele.getSimState() == SIM_STATE_READY) {
+                    return Objects.equal(tele.getSubscriberId(), template.getSubscriberId());
+                } else {
                     return false;
                 }
-
-                // mobile templates are relevant when subscriberid is active
-                return Objects.equal(getActiveSubscriberId(), template.getSubscriberId());
         }
         return true;
     }
@@ -761,7 +770,7 @@
         final long currentTime = currentTimeMillis();
         for (NetworkPolicy policy : mNetworkPolicy.values()) {
             // shortcut when policy has no limit
-            if (policy.limitBytes == LIMIT_DISABLED) {
+            if (policy.limitBytes == LIMIT_DISABLED || !policy.hasCycle()) {
                 setNetworkTemplateEnabled(policy.template, true);
                 continue;
             }
@@ -784,13 +793,16 @@
      * for the given {@link NetworkTemplate}.
      */
     private void setNetworkTemplateEnabled(NetworkTemplate template, boolean enabled) {
+        final TelephonyManager tele = TelephonyManager.from(mContext);
+
         switch (template.getMatchRule()) {
             case MATCH_MOBILE_3G_LOWER:
             case MATCH_MOBILE_4G:
             case MATCH_MOBILE_ALL:
                 // TODO: offer more granular control over radio states once
                 // 4965893 is available.
-                if (Objects.equal(getActiveSubscriberId(), template.getSubscriberId())) {
+                if (tele.getSimState() == SIM_STATE_READY
+                        && Objects.equal(tele.getSubscriberId(), template.getSubscriberId())) {
                     setPolicyDataEnable(TYPE_MOBILE, enabled);
                     setPolicyDataEnable(TYPE_WIMAX, enabled);
                 }
@@ -863,9 +875,15 @@
         for (NetworkPolicy policy : mNetworkRules.keySet()) {
             final String[] ifaces = mNetworkRules.get(policy);
 
-            final long start = computeLastCycleBoundary(currentTime, policy);
-            final long end = currentTime;
-            final long totalBytes = getTotalBytes(policy.template, start, end);
+            final long start;
+            final long totalBytes;
+            if (policy.hasCycle()) {
+                start = computeLastCycleBoundary(currentTime, policy);
+                totalBytes = getTotalBytes(policy.template, start, currentTime);
+            } else {
+                start = Long.MAX_VALUE;
+                totalBytes = 0;
+            }
 
             if (LOGD) {
                 Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces "
@@ -923,9 +941,14 @@
         if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()");
         if (mSuppressDefaultPolicy) return;
 
-        final String subscriberId = getActiveSubscriberId();
+        final TelephonyManager tele = TelephonyManager.from(mContext);
+
+        // avoid creating policy when SIM isn't ready
+        if (tele.getSimState() != SIM_STATE_READY) return;
+
+        final String subscriberId = tele.getSubscriberId();
         final NetworkIdentity probeIdent = new NetworkIdentity(
-                TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, false);
+                TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false);
 
         // examine to see if any policy is defined for active mobile
         boolean mobileDefined = false;
@@ -986,6 +1009,12 @@
                     } else if (TAG_NETWORK_POLICY.equals(tag)) {
                         final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE);
                         final String subscriberId = in.getAttributeValue(null, ATTR_SUBSCRIBER_ID);
+                        final String networkId;
+                        if (version >= VERSION_ADDED_NETWORK_ID) {
+                            networkId = in.getAttributeValue(null, ATTR_NETWORK_ID);
+                        } else {
+                            networkId = null;
+                        }
                         final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY);
                         final String cycleTimezone;
                         if (version >= VERSION_ADDED_TIMEZONE) {
@@ -1031,12 +1060,12 @@
                         }
 
                         final NetworkTemplate template = new NetworkTemplate(
-                                networkTemplate, subscriberId);
+                                networkTemplate, subscriberId, networkId);
                         mNetworkPolicy.put(template, new NetworkPolicy(template, cycleDay,
                                 cycleTimezone, warningBytes, limitBytes, lastWarningSnooze,
                                 lastLimitSnooze, metered, inferred));
 
-                    } else if (TAG_UID_POLICY.equals(tag)) {
+                    } else if (TAG_UID_POLICY.equals(tag) && version < VERSION_SWITCH_APP_ID) {
                         final int uid = readIntAttribute(in, ATTR_UID);
                         final int policy = readIntAttribute(in, ATTR_POLICY);
 
@@ -1046,7 +1075,7 @@
                         } else {
                             Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
                         }
-                    } else if (TAG_APP_POLICY.equals(tag)) {
+                    } else if (TAG_APP_POLICY.equals(tag) && version >= VERSION_SWITCH_APP_ID) {
                         final int appId = readIntAttribute(in, ATTR_APP_ID);
                         final int policy = readIntAttribute(in, ATTR_POLICY);
 
@@ -1099,7 +1128,7 @@
             out.startDocument(null, true);
 
             out.startTag(null, TAG_POLICY_LIST);
-            writeIntAttribute(out, ATTR_VERSION, VERSION_SWITCH_APP_ID);
+            writeIntAttribute(out, ATTR_VERSION, VERSION_LATEST);
             writeBooleanAttribute(out, ATTR_RESTRICT_BACKGROUND, mRestrictBackground);
 
             // write all known network policies
@@ -1112,6 +1141,10 @@
                 if (subscriberId != null) {
                     out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId);
                 }
+                final String networkId = template.getNetworkId();
+                if (networkId != null) {
+                    out.attribute(null, ATTR_NETWORK_ID, networkId);
+                }
                 writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay);
                 out.attribute(null, ATTR_CYCLE_TIMEZONE, policy.cycleTimezone);
                 writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes);
@@ -1318,7 +1351,7 @@
             policy = findPolicyForNetworkLocked(ident);
         }
 
-        if (policy == null) {
+        if (policy == null || !policy.hasCycle()) {
             // missing policy means we can't derive useful quota info
             return null;
         }
@@ -1340,9 +1373,11 @@
     }
 
     @Override
-    protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
+    protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         mContext.enforceCallingOrSelfPermission(DUMP, TAG);
 
+        final IndentingPrintWriter fout = new IndentingPrintWriter(writer, "  ");
+
         final HashSet<String> argSet = new HashSet<String>();
         for (String arg : args) {
             argSet.add(arg);
@@ -1365,31 +1400,36 @@
 
             fout.print("Restrict background: "); fout.println(mRestrictBackground);
             fout.println("Network policies:");
+            fout.increaseIndent();
             for (NetworkPolicy policy : mNetworkPolicy.values()) {
-                fout.print("  "); fout.println(policy.toString());
+                fout.println(policy.toString());
             }
+            fout.decreaseIndent();
 
             fout.println("Policy for apps:");
+            fout.increaseIndent();
             int size = mAppPolicy.size();
             for (int i = 0; i < size; i++) {
                 final int appId = mAppPolicy.keyAt(i);
                 final int policy = mAppPolicy.valueAt(i);
-                fout.print("  appId=");
+                fout.print("appId=");
                 fout.print(appId);
                 fout.print(" policy=");
                 dumpPolicy(fout, policy);
                 fout.println();
             }
+            fout.decreaseIndent();
 
             final SparseBooleanArray knownUids = new SparseBooleanArray();
             collectKeys(mUidForeground, knownUids);
             collectKeys(mUidRules, knownUids);
 
             fout.println("Status for known UIDs:");
+            fout.increaseIndent();
             size = knownUids.size();
             for (int i = 0; i < size; i++) {
                 final int uid = knownUids.keyAt(i);
-                fout.print("  UID=");
+                fout.print("UID=");
                 fout.print(uid);
 
                 fout.print(" foreground=");
@@ -1410,6 +1450,7 @@
 
                 fout.println();
             }
+            fout.decreaseIndent();
         }
     }
 
@@ -1697,12 +1738,6 @@
         }
     }
 
-    private String getActiveSubscriberId() {
-        final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService(
-                Context.TELEPHONY_SERVICE);
-        return telephony.getSubscriberId();
-    }
-
     private long getTotalBytes(NetworkTemplate template, long start, long end) {
         try {
             return mNetworkStats.getSummaryForNetwork(template, start, end).getTotalBytes();
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index 8796afc..b847673 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -34,7 +34,7 @@
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
 import static android.net.NetworkTemplate.buildTemplateMobileAll;
-import static android.net.NetworkTemplate.buildTemplateWifi;
+import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
 import static android.net.TrafficStats.MB_IN_BYTES;
 import static android.provider.Settings.Secure.NETSTATS_DEV_BUCKET_DURATION;
 import static android.provider.Settings.Secure.NETSTATS_DEV_DELETE_AGE;
@@ -836,7 +836,7 @@
                 trustedTime);
 
         // collect wifi sample
-        template = buildTemplateWifi();
+        template = buildTemplateWifiWildcard();
         devTotal = mDevRecorder.getTotalSinceBootLocked(template);
         xtTotal = new NetworkStats.Entry();
         uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
diff --git a/services/java/com/android/server/wm/AppWindowAnimator.java b/services/java/com/android/server/wm/AppWindowAnimator.java
new file mode 100644
index 0000000..6ba4c35
--- /dev/null
+++ b/services/java/com/android/server/wm/AppWindowAnimator.java
@@ -0,0 +1,288 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+
+package com.android.server.wm;
+
+import android.graphics.Matrix;
+import android.util.Slog;
+import android.view.Surface;
+import android.view.WindowManagerPolicy;
+import android.view.animation.Animation;
+import android.view.animation.Transformation;
+
+import java.io.PrintWriter;
+
+/**
+ *
+ */
+public class AppWindowAnimator {
+
+    final AppWindowToken mAppToken;
+    final WindowManagerService mService;
+    final WindowAnimator mAnimator;
+
+    boolean animating;
+    Animation animation;
+    boolean animInitialized;
+    boolean hasTransformation;
+    final Transformation transformation = new Transformation();
+
+    // Have we been asked to have this token keep the screen frozen?
+    // Protect with mAnimator.
+    boolean freezingScreen;
+
+    // Offset to the window of all layers in the token, for use by
+    // AppWindowToken animations.
+    int animLayerAdjustment;
+
+    // Special surface for thumbnail animation.
+    Surface thumbnail;
+    int thumbnailTransactionSeq;
+    int thumbnailX;
+    int thumbnailY;
+    int thumbnailLayer;
+    Animation thumbnailAnimation;
+    final Transformation thumbnailTransformation = new Transformation();
+
+    public AppWindowAnimator(final WindowManagerService service, final AppWindowToken atoken) {
+        mService = service;
+        mAppToken = atoken;
+        mAnimator = service.mAnimator;
+    }
+
+    public void setAnimation(Animation anim, boolean initialized) {
+        if (WindowManagerService.localLOGV) Slog.v(
+            WindowManagerService.TAG, "Setting animation in " + this + ": " + anim);
+        animation = anim;
+        animating = false;
+        animInitialized = initialized;
+        anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
+        anim.scaleCurrentDuration(mService.mTransitionAnimationScale);
+        int zorder = anim.getZAdjustment();
+        int adj = 0;
+        if (zorder == Animation.ZORDER_TOP) {
+            adj = WindowManagerService.TYPE_LAYER_OFFSET;
+        } else if (zorder == Animation.ZORDER_BOTTOM) {
+            adj = -WindowManagerService.TYPE_LAYER_OFFSET;
+        }
+
+        if (animLayerAdjustment != adj) {
+            animLayerAdjustment = adj;
+            updateLayers();
+        }
+        // Start out animation gone if window is gone, or visible if window is visible.
+        transformation.clear();
+        transformation.setAlpha(mAppToken.reportedVisible ? 1 : 0);
+        hasTransformation = true;
+    }
+
+    public void setDummyAnimation() {
+        if (animation == null) {
+            if (WindowManagerService.localLOGV) Slog.v(
+                WindowManagerService.TAG, "Setting dummy animation in " + this);
+            animation = WindowManagerService.sDummyAnimation;
+            animInitialized = false;
+        }
+    }
+
+    public void clearAnimation() {
+        if (animation != null) {
+            animation = null;
+            animating = true;
+            animInitialized = false;
+        }
+        clearThumbnail();
+    }
+
+    public void clearThumbnail() {
+        if (thumbnail != null) {
+            thumbnail.destroy();
+            thumbnail = null;
+        }
+    }
+
+    void updateLayers() {
+        final int N = mAppToken.allAppWindows.size();
+        final int adj = animLayerAdjustment;
+        thumbnailLayer = -1;
+        for (int i=0; i<N; i++) {
+            final WindowState w = mAppToken.allAppWindows.get(i);
+            final WindowStateAnimator winAnimator = w.mWinAnimator;
+            winAnimator.mAnimLayer = w.mLayer + adj;
+            if (winAnimator.mAnimLayer > thumbnailLayer) {
+                thumbnailLayer = winAnimator.mAnimLayer;
+            }
+            if (WindowManagerService.DEBUG_LAYERS) Slog.v(WindowManagerService.TAG, "Updating layer " + w + ": "
+                    + winAnimator.mAnimLayer);
+            if (w == mService.mInputMethodTarget && !mService.mInputMethodTargetWaitingAnim) {
+                mService.setInputMethodAnimLayerAdjustment(adj);
+            }
+            if (w == mService.mWallpaperTarget && mService.mLowerWallpaperTarget == null) {
+                mService.setWallpaperAnimLayerAdjustmentLocked(adj);
+            }
+        }
+    }
+
+    private void stepThumbnailAnimation(long currentTime) {
+        thumbnailTransformation.clear();
+        thumbnailAnimation.getTransformation(currentTime, thumbnailTransformation);
+        thumbnailTransformation.getMatrix().preTranslate(thumbnailX, thumbnailY);
+        final boolean screenAnimation = mAnimator.mScreenRotationAnimation != null
+                && mAnimator.mScreenRotationAnimation.isAnimating();
+        if (screenAnimation) {
+            thumbnailTransformation.postCompose(
+                    mAnimator.mScreenRotationAnimation.getEnterTransformation());
+        }
+        // cache often used attributes locally
+        final float tmpFloats[] = mService.mTmpFloats;
+        thumbnailTransformation.getMatrix().getValues(tmpFloats);
+        if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail,
+                "thumbnail", "POS " + tmpFloats[Matrix.MTRANS_X]
+                + ", " + tmpFloats[Matrix.MTRANS_Y], null);
+        thumbnail.setPosition(tmpFloats[Matrix.MTRANS_X], tmpFloats[Matrix.MTRANS_Y]);
+        if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail,
+                "thumbnail", "alpha=" + thumbnailTransformation.getAlpha()
+                + " layer=" + thumbnailLayer
+                + " matrix=[" + tmpFloats[Matrix.MSCALE_X]
+                + "," + tmpFloats[Matrix.MSKEW_Y]
+                + "][" + tmpFloats[Matrix.MSKEW_X]
+                + "," + tmpFloats[Matrix.MSCALE_Y] + "]", null);
+        thumbnail.setAlpha(thumbnailTransformation.getAlpha());
+        // The thumbnail is layered below the window immediately above this
+        // token's anim layer.
+        thumbnail.setLayer(thumbnailLayer + WindowManagerService.WINDOW_LAYER_MULTIPLIER
+                - WindowManagerService.LAYER_OFFSET_THUMBNAIL);
+        thumbnail.setMatrix(tmpFloats[Matrix.MSCALE_X], tmpFloats[Matrix.MSKEW_Y],
+                tmpFloats[Matrix.MSKEW_X], tmpFloats[Matrix.MSCALE_Y]);
+    }
+
+    private boolean stepAnimation(long currentTime) {
+        if (animation == null) {
+            return false;
+        }
+        transformation.clear();
+        final boolean more = animation.getTransformation(currentTime, transformation);
+        if (WindowManagerService.DEBUG_ANIM) Slog.v(
+            WindowManagerService.TAG, "Stepped animation in " + this +
+            ": more=" + more + ", xform=" + transformation);
+        if (!more) {
+            animation = null;
+            clearThumbnail();
+            if (WindowManagerService.DEBUG_ANIM) Slog.v(
+                WindowManagerService.TAG, "Finished animation in " + this +
+                " @ " + currentTime);
+        }
+        hasTransformation = more;
+        return more;
+    }
+
+    // This must be called while inside a transaction.
+    boolean stepAnimationLocked(long currentTime, int dw, int dh) {
+        if (mService.okToDisplay()) {
+            // We will run animations as long as the display isn't frozen.
+
+            if (animation == WindowManagerService.sDummyAnimation) {
+                // This guy is going to animate, but not yet.  For now count
+                // it as not animating for purposes of scheduling transactions;
+                // when it is really time to animate, this will be set to
+                // a real animation and the next call will execute normally.
+                return false;
+            }
+
+            if ((mAppToken.allDrawn || animating || mAppToken.startingDisplayed)
+                    && animation != null) {
+                if (!animating) {
+                    if (WindowManagerService.DEBUG_ANIM) Slog.v(
+                        WindowManagerService.TAG, "Starting animation in " + this +
+                        " @ " + currentTime + ": dw=" + dw + " dh=" + dh
+                        + " scale=" + mService.mTransitionAnimationScale
+                        + " allDrawn=" + mAppToken.allDrawn + " animating=" + animating);
+                    if (!animInitialized) {
+                        animation.initialize(dw, dh, dw, dh);
+                    }
+                    animation.setStartTime(currentTime);
+                    animating = true;
+                    if (thumbnail != null) {
+                        thumbnail.show();
+                        thumbnailAnimation.setStartTime(currentTime);
+                    }
+                }
+                if (stepAnimation(currentTime)) {
+                    // animation isn't over, step any thumbnail and that's
+                    // it for now.
+                    if (thumbnail != null) {
+                        stepThumbnailAnimation(currentTime);
+                    }
+                    return true;
+                }
+            }
+        } else if (animation != null) {
+            // If the display is frozen, and there is a pending animation,
+            // clear it and make sure we run the cleanup code.
+            animating = true;
+            animation = null;
+        }
+
+        hasTransformation = false;
+
+        if (!animating) {
+            return false;
+        }
+
+        mAnimator.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
+        if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
+            mService.debugLayoutRepeats("AppWindowToken", mAnimator.mPendingLayoutChanges);
+        }
+
+        clearAnimation();
+        animating = false;
+        if (animLayerAdjustment != 0) {
+            animLayerAdjustment = 0;
+            updateLayers();
+        }
+        if (mService.mInputMethodTarget != null
+                && mService.mInputMethodTarget.mAppToken == mAppToken) {
+            mService.moveInputMethodWindowsIfNeededLocked(true);
+        }
+
+        if (WindowManagerService.DEBUG_ANIM) Slog.v(
+                WindowManagerService.TAG, "Animation done in " + this
+                + ": reportedVisible=" + mAppToken.reportedVisible);
+
+        transformation.clear();
+
+        final int N = mAppToken.windows.size();
+        for (int i=0; i<N; i++) {
+            mAppToken.windows.get(i).mWinAnimator.finishExit();
+        }
+        mAppToken.updateReportedVisibilityLocked();
+
+        return false;
+    }
+
+    void dump(PrintWriter pw, String prefix) {
+        if (freezingScreen) {
+            pw.print(prefix); pw.print(" freezingScreen="); pw.println(freezingScreen);
+        }
+        if (animating || animation != null) {
+            pw.print(prefix); pw.print("animating="); pw.print(animating);
+                    pw.print(" animation="); pw.println(animation);
+        }
+        if (hasTransformation) {
+            pw.print(prefix); pw.print("XForm: ");
+                    transformation.printShortString(pw);
+                    pw.println();
+        }
+        if (animLayerAdjustment != 0) {
+            pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
+        }
+        if (thumbnail != null) {
+            pw.print(prefix); pw.print("thumbnail="); pw.print(thumbnail);
+                    pw.print(" x="); pw.print(thumbnailX);
+                    pw.print(" y="); pw.print(thumbnailY);
+                    pw.print(" layer="); pw.println(thumbnailLayer);
+            pw.print(prefix); pw.print("thumbnailAnimation="); pw.println(thumbnailAnimation);
+            pw.print(prefix); pw.print("thumbnailTransformation=");
+                    pw.println(thumbnailTransformation.toShortString());
+        }
+    }
+}
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index 3069b74..1f8348d 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -18,20 +18,16 @@
 
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 
+import com.android.server.input.InputApplicationHandle;
 import com.android.server.wm.WindowManagerService.H;
 
 import android.content.pm.ActivityInfo;
-import android.graphics.Matrix;
 import android.os.Message;
 import android.os.RemoteException;
 import android.util.Slog;
 import android.view.IApplicationToken;
-import android.view.Surface;
 import android.view.View;
 import android.view.WindowManager;
-import android.view.WindowManagerPolicy;
-import android.view.animation.Animation;
-import android.view.animation.Transformation;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -47,6 +43,9 @@
     // All of the windows and child windows that are included in this
     // application token.  Note this list is NOT sorted!
     final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>();
+    final AppWindowAnimator mAppAnimator;
+
+    final WindowAnimator mAnimator;
 
     int groupId = -1;
     boolean appFullscreen;
@@ -87,19 +86,6 @@
     // Set to true when the token has been removed from the window mgr.
     boolean removed;
 
-    // Have we been asked to have this token keep the screen frozen?
-    boolean freezingScreen;
-
-    boolean animating;
-    Animation animation;
-    boolean animInitialized;
-    boolean hasTransformation;
-    final Transformation transformation = new Transformation();
-
-    // Offset to the window of all layers in the token, for use by
-    // AppWindowToken animations.
-    int animLayerAdjustment;
-
     // Information about an application starting window if displayed.
     StartingData startingData;
     WindowState startingWindow;
@@ -108,15 +94,6 @@
     boolean startingMoved;
     boolean firstWindowDrawn;
 
-    // Special surface for thumbnail animation.
-    Surface thumbnail;
-    int thumbnailTransactionSeq;
-    int thumbnailX;
-    int thumbnailY;
-    int thumbnailLayer;
-    Animation thumbnailAnimation;
-    final Transformation thumbnailTransformation = new Transformation();
-
     // Input application handle used by the input dispatcher.
     final InputApplicationHandle mInputApplicationHandle;
 
@@ -126,79 +103,8 @@
         appWindowToken = this;
         appToken = _token;
         mInputApplicationHandle = new InputApplicationHandle(this);
-    }
-
-    public void setAnimation(Animation anim, boolean initialized) {
-        if (WindowManagerService.localLOGV) Slog.v(
-            WindowManagerService.TAG, "Setting animation in " + this + ": " + anim);
-        animation = anim;
-        animating = false;
-        animInitialized = initialized;
-        anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
-        anim.scaleCurrentDuration(service.mTransitionAnimationScale);
-        int zorder = anim.getZAdjustment();
-        int adj = 0;
-        if (zorder == Animation.ZORDER_TOP) {
-            adj = WindowManagerService.TYPE_LAYER_OFFSET;
-        } else if (zorder == Animation.ZORDER_BOTTOM) {
-            adj = -WindowManagerService.TYPE_LAYER_OFFSET;
-        }
-
-        if (animLayerAdjustment != adj) {
-            animLayerAdjustment = adj;
-            updateLayers();
-        }
-        // Start out animation gone if window is gone, or visible if window is visible.
-        transformation.clear();
-        transformation.setAlpha(reportedVisible ? 1 : 0);
-        hasTransformation = true;
-    }
-
-    public void setDummyAnimation() {
-        if (animation == null) {
-            if (WindowManagerService.localLOGV) Slog.v(
-                WindowManagerService.TAG, "Setting dummy animation in " + this);
-            animation = WindowManagerService.sDummyAnimation;
-            animInitialized = false;
-        }
-    }
-
-    public void clearAnimation() {
-        if (animation != null) {
-            animation = null;
-            animating = true;
-            animInitialized = false;
-        }
-        clearThumbnail();
-    }
-
-    public void clearThumbnail() {
-        if (thumbnail != null) {
-            thumbnail.destroy();
-            thumbnail = null;
-        }
-    }
-
-    void updateLayers() {
-        final int N = allAppWindows.size();
-        final int adj = animLayerAdjustment;
-        thumbnailLayer = -1;
-        for (int i=0; i<N; i++) {
-            final WindowState w = allAppWindows.get(i);
-            final WindowStateAnimator winAnimator = w.mWinAnimator;
-            winAnimator.mAnimLayer = w.mLayer + adj;
-            if (winAnimator.mAnimLayer > thumbnailLayer) {
-                thumbnailLayer = winAnimator.mAnimLayer;
-            }
-            if (WindowManagerService.DEBUG_LAYERS) Slog.v(WindowManagerService.TAG, "Updating layer " + w + ": "
-                    + winAnimator.mAnimLayer);
-            if (w == service.mInputMethodTarget && !service.mInputMethodTargetWaitingAnim) {
-                service.setInputMethodAnimLayerAdjustment(adj);
-            }
-            if (w == service.mWallpaperTarget && service.mLowerWallpaperTarget == null) {
-                service.setWallpaperAnimLayerAdjustmentLocked(adj);
-            }
-        }
+        mAnimator = service.mAnimator;
+        mAppAnimator = new AppWindowAnimator(_service, this);
     }
 
     void sendAppVisibilityToClients() {
@@ -231,141 +137,6 @@
         return isAnimating;
     }
 
-    private void stepThumbnailAnimation(long currentTime) {
-        thumbnailTransformation.clear();
-        thumbnailAnimation.getTransformation(currentTime, thumbnailTransformation);
-        thumbnailTransformation.getMatrix().preTranslate(thumbnailX, thumbnailY);
-        final boolean screenAnimation = service.mAnimator.mScreenRotationAnimation != null
-                && service.mAnimator.mScreenRotationAnimation.isAnimating();
-        if (screenAnimation) {
-            thumbnailTransformation.postCompose(
-                    service.mAnimator.mScreenRotationAnimation.getEnterTransformation());
-        }
-        // cache often used attributes locally
-        final float tmpFloats[] = service.mTmpFloats;
-        thumbnailTransformation.getMatrix().getValues(tmpFloats);
-        if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail,
-                "thumbnail", "POS " + tmpFloats[Matrix.MTRANS_X]
-                + ", " + tmpFloats[Matrix.MTRANS_Y], null);
-        thumbnail.setPosition(tmpFloats[Matrix.MTRANS_X], tmpFloats[Matrix.MTRANS_Y]);
-        if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(thumbnail,
-                "thumbnail", "alpha=" + thumbnailTransformation.getAlpha()
-                + " layer=" + thumbnailLayer
-                + " matrix=[" + tmpFloats[Matrix.MSCALE_X]
-                + "," + tmpFloats[Matrix.MSKEW_Y]
-                + "][" + tmpFloats[Matrix.MSKEW_X]
-                + "," + tmpFloats[Matrix.MSCALE_Y] + "]", null);
-        thumbnail.setAlpha(thumbnailTransformation.getAlpha());
-        // The thumbnail is layered below the window immediately above this
-        // token's anim layer.
-        thumbnail.setLayer(thumbnailLayer + WindowManagerService.WINDOW_LAYER_MULTIPLIER
-                - WindowManagerService.LAYER_OFFSET_THUMBNAIL);
-        thumbnail.setMatrix(tmpFloats[Matrix.MSCALE_X], tmpFloats[Matrix.MSKEW_Y],
-                tmpFloats[Matrix.MSKEW_X], tmpFloats[Matrix.MSCALE_Y]);
-    }
-
-    private boolean stepAnimation(long currentTime) {
-        if (animation == null) {
-            return false;
-        }
-        transformation.clear();
-        final boolean more = animation.getTransformation(currentTime, transformation);
-        if (WindowManagerService.DEBUG_ANIM) Slog.v(
-            WindowManagerService.TAG, "Stepped animation in " + this +
-            ": more=" + more + ", xform=" + transformation);
-        if (!more) {
-            animation = null;
-            clearThumbnail();
-            if (WindowManagerService.DEBUG_ANIM) Slog.v(
-                WindowManagerService.TAG, "Finished animation in " + this +
-                " @ " + currentTime);
-        }
-        hasTransformation = more;
-        return more;
-    }
-
-    // This must be called while inside a transaction.
-    boolean stepAnimationLocked(long currentTime, int dw, int dh) {
-        if (service.okToDisplay()) {
-            // We will run animations as long as the display isn't frozen.
-
-            if (animation == WindowManagerService.sDummyAnimation) {
-                // This guy is going to animate, but not yet.  For now count
-                // it as not animating for purposes of scheduling transactions;
-                // when it is really time to animate, this will be set to
-                // a real animation and the next call will execute normally.
-                return false;
-            }
-
-            if ((allDrawn || animating || startingDisplayed) && animation != null) {
-                if (!animating) {
-                    if (WindowManagerService.DEBUG_ANIM) Slog.v(
-                        WindowManagerService.TAG, "Starting animation in " + this +
-                        " @ " + currentTime + ": dw=" + dw + " dh=" + dh
-                        + " scale=" + service.mTransitionAnimationScale
-                        + " allDrawn=" + allDrawn + " animating=" + animating);
-                    if (!animInitialized) {
-                        animation.initialize(dw, dh, dw, dh);
-                    }
-                    animation.setStartTime(currentTime);
-                    animating = true;
-                    if (thumbnail != null) {
-                        thumbnail.show();
-                        thumbnailAnimation.setStartTime(currentTime);
-                    }
-                }
-                if (stepAnimation(currentTime)) {
-                    // animation isn't over, step any thumbnail and that's
-                    // it for now.
-                    if (thumbnail != null) {
-                        stepThumbnailAnimation(currentTime);
-                    }
-                    return true;
-                }
-            }
-        } else if (animation != null) {
-            // If the display is frozen, and there is a pending animation,
-            // clear it and make sure we run the cleanup code.
-            animating = true;
-            animation = null;
-        }
-
-        hasTransformation = false;
-
-        if (!animating) {
-            return false;
-        }
-
-        service.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
-        if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
-            service.debugLayoutRepeats("AppWindowToken");
-        }
-
-        clearAnimation();
-        animating = false;
-        if (animLayerAdjustment != 0) {
-            animLayerAdjustment = 0;
-            updateLayers();
-        }
-        if (service.mInputMethodTarget != null && service.mInputMethodTarget.mAppToken == this) {
-            service.moveInputMethodWindowsIfNeededLocked(true);
-        }
-
-        if (WindowManagerService.DEBUG_ANIM) Slog.v(
-                WindowManagerService.TAG, "Animation done in " + this
-                + ": reportedVisible=" + reportedVisible);
-
-        transformation.clear();
-
-        final int N = windows.size();
-        for (int i=0; i<N; i++) {
-            windows.get(i).mWinAnimator.finishExit();
-        }
-        updateReportedVisibilityLocked();
-
-        return false;
-    }
-
     void updateReportedVisibilityLocked() {
         if (appToken == null) {
             return;
@@ -479,9 +250,8 @@
                 pw.print(" willBeHidden="); pw.print(willBeHidden);
                 pw.print(" reportedDrawn="); pw.print(reportedDrawn);
                 pw.print(" reportedVisible="); pw.println(reportedVisible);
-        if (paused || freezingScreen) {
-            pw.print(prefix); pw.print("paused="); pw.print(paused);
-                    pw.print(" freezingScreen="); pw.println(freezingScreen);
+        if (paused) {
+            pw.print(prefix); pw.print("paused="); pw.println(paused);
         }
         if (numInterestingWindows != 0 || numDrawnWindows != 0
                 || inPendingTransaction || allDrawn) {
@@ -491,18 +261,6 @@
                     pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
                     pw.print(" allDrawn="); pw.println(allDrawn);
         }
-        if (animating || animation != null) {
-            pw.print(prefix); pw.print("animating="); pw.print(animating);
-                    pw.print(" animation="); pw.println(animation);
-        }
-        if (hasTransformation) {
-            pw.print(prefix); pw.print("XForm: ");
-                    transformation.printShortString(pw);
-                    pw.println();
-        }
-        if (animLayerAdjustment != 0) {
-            pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
-        }
         if (startingData != null || removed || firstWindowDrawn) {
             pw.print(prefix); pw.print("startingData="); pw.print(startingData);
                     pw.print(" removed="); pw.print(removed);
@@ -515,15 +273,6 @@
                     pw.print(" startingDisplayed="); pw.print(startingDisplayed);
                     pw.print(" startingMoved"); pw.println(startingMoved);
         }
-        if (thumbnail != null) {
-            pw.print(prefix); pw.print("thumbnail="); pw.print(thumbnail);
-                    pw.print(" x="); pw.print(thumbnailX);
-                    pw.print(" y="); pw.print(thumbnailY);
-                    pw.print(" layer="); pw.println(thumbnailLayer);
-            pw.print(prefix); pw.print("thumbnailAnimation="); pw.println(thumbnailAnimation);
-            pw.print(prefix); pw.print("thumbnailTransformation=");
-                    pw.println(thumbnailTransformation.toShortString());
-        }
     }
 
     @Override
@@ -537,4 +286,4 @@
         }
         return stringName;
     }
-}
\ No newline at end of file
+}
diff --git a/services/java/com/android/server/wm/DimAnimator.java b/services/java/com/android/server/wm/DimAnimator.java
index 0051d98..405dd04 100644
--- a/services/java/com/android/server/wm/DimAnimator.java
+++ b/services/java/com/android/server/wm/DimAnimator.java
@@ -57,12 +57,17 @@
     }
 
     /**
-     * Show the dim surface.
+     * Set's the dim surface's layer and update dim parameters that will be used in
+     * {@link #updateSurface} after all windows are examined.
      */
-    void show(int dw, int dh) {
+    void updateParameters(final Resources res, final Parameters params, final long currentTime) {
+        final int dw = params.mDimWidth;
+        final int dh = params.mDimHeight;
+        final WindowStateAnimator winAnimator = params.mDimWinAnimator;
+        final float target = params.mDimTarget;
         if (!mDimShown) {
-            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DIM " + mDimSurface + ": SHOW pos=(0,0) (" +
-                    dw + "x" + dh + ")");
+            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
+                "  DIM " + mDimSurface + ": SHOW pos=(0,0) (" + dw + "x" + dh + ")");
             mDimShown = true;
             try {
                 mLastDimWidth = dw;
@@ -78,17 +83,9 @@
             mLastDimHeight = dh;
             mDimSurface.setSize(dw, dh);
         }
-    }
 
-    /**
-     * Set's the dim surface's layer and update dim parameters that will be used in
-     * {@link #updateSurface} after all windows are examined.
-     */
-    void updateParameters(Resources res, WindowState w, long currentTime) {
-        final WindowStateAnimator winAnimator = w.mWinAnimator;
         mDimSurface.setLayer(winAnimator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM);
 
-        final float target = w.mExiting ? 0 : w.mAttrs.dimAmount;
         if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DIM "
                 + mDimSurface + ": layer=" + (winAnimator.mAnimLayer-1) + " target=" + target);
         if (mDimTargetAlpha != target) {
@@ -189,4 +186,18 @@
         pw.print(" delta="); pw.print(mDimDeltaPerMs);
         pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime);
     }
+
+    static class Parameters {
+        final WindowStateAnimator mDimWinAnimator;
+        final int mDimWidth;
+        final int mDimHeight;
+        final float mDimTarget;
+        Parameters(final WindowStateAnimator dimWinAnimator, final int dimWidth,
+                final int dimHeight, final float dimTarget) {
+            mDimWinAnimator = dimWinAnimator;
+            mDimWidth = dimWidth;
+            mDimHeight = dimHeight;
+            mDimTarget = dimTarget;
+        }
+    }
 }
\ No newline at end of file
diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java
index a19035a..b2cf3e0c 100644
--- a/services/java/com/android/server/wm/DragState.java
+++ b/services/java/com/android/server/wm/DragState.java
@@ -16,6 +16,8 @@
 
 package com.android.server.wm;
 
+import com.android.server.input.InputApplicationHandle;
+import com.android.server.input.InputWindowHandle;
 import com.android.server.wm.WindowManagerService.DragInputEventReceiver;
 import com.android.server.wm.WindowManagerService.H;
 
diff --git a/services/java/com/android/server/wm/FakeWindowImpl.java b/services/java/com/android/server/wm/FakeWindowImpl.java
index 121ce18..2527f46 100644
--- a/services/java/com/android/server/wm/FakeWindowImpl.java
+++ b/services/java/com/android/server/wm/FakeWindowImpl.java
@@ -16,6 +16,9 @@
 
 package com.android.server.wm;
 
+import com.android.server.input.InputApplicationHandle;
+import com.android.server.input.InputWindowHandle;
+
 import android.os.Looper;
 import android.os.Process;
 import android.util.Slog;
diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java
index fb74d27..c28cfa2 100644
--- a/services/java/com/android/server/wm/InputMonitor.java
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -16,6 +16,10 @@
 
 package com.android.server.wm;
 
+import com.android.server.input.InputManagerService;
+import com.android.server.input.InputApplicationHandle;
+import com.android.server.input.InputWindowHandle;
+
 import android.graphics.Rect;
 import android.os.RemoteException;
 import android.util.Log;
@@ -27,7 +31,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 
-final class InputMonitor {
+final class InputMonitor implements InputManagerService.Callbacks {
     private final WindowManagerService mService;
     
     // Current window with input focus for keys and other non-touch events.  May be null.
@@ -93,7 +97,7 @@
         }
         
         if (appWindowToken == null && inputApplicationHandle != null) {
-            appWindowToken = inputApplicationHandle.appWindowToken;
+            appWindowToken = (AppWindowToken)inputApplicationHandle.appWindowToken;
             if (appWindowToken != null) {
                 Slog.i(WindowManagerService.TAG,
                         "Input event dispatching timed out sending to application "
@@ -301,7 +305,14 @@
         WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
         return mService.mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
     }
-    
+
+    /* Callback to get pointer layer. */
+    public int getPointerLayer() {
+        return mService.mPolicy.windowTypeToLayerLw(WindowManager.LayoutParams.TYPE_POINTER)
+                * WindowManagerService.TYPE_LAYER_MULTIPLIER
+                + WindowManagerService.TYPE_LAYER_OFFSET;
+    }
+
     /* Called when the current input focus changes.
      * Layer assignment is assumed to be complete by the time this is called.
      */
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
index 5a104b2..9b196cc 100644
--- a/services/java/com/android/server/wm/WindowAnimator.java
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -6,6 +6,9 @@
 
 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_UPDATE_ROTATION;
 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_MAY_CHANGE;
+import static com.android.server.wm.WindowManagerService.LayoutFields.SET_FORCE_HIDING_CHANGED;
+
+import static com.android.server.wm.WindowManagerService.H.SET_DIM_PARAMETERS;
 
 import android.content.Context;
 import android.os.SystemClock;
@@ -21,7 +24,6 @@
 import java.io.PrintWriter;
 
 /**
- * @author cmautner@google.com (Craig Mautner)
  * Singleton class that carries out the animations and Surface operations in a separate task
  * on behalf of WindowManagerService.
  */
@@ -67,6 +69,9 @@
 
     int mBulkUpdateParams = 0;
 
+    DimAnimator mDimAnimator = null;
+    DimAnimator.Parameters mDimParams = null;
+
     WindowAnimator(final WindowManagerService service, final Context context,
             final WindowManagerPolicy policy) {
         mService = service;
@@ -91,7 +96,8 @@
             if (mService.mWallpaperTarget == target
                     || mService.mLowerWallpaperTarget == target
                     || mService.mUpperWallpaperTarget == target) {
-                for (int i=0; i<mService.mWindows.size(); i++) {
+                final int N = mService.mWindows.size();
+                for (int i = 0; i < N; i++) {
                     WindowState w = mService.mWindows.get(i);
                     if (w.mIsWallpaper) {
                         target = w;
@@ -116,32 +122,34 @@
         int i;
         final int NAT = mService.mAppTokens.size();
         for (i=0; i<NAT; i++) {
-            final AppWindowToken appToken = mService.mAppTokens.get(i);
-            final boolean wasAnimating = appToken.animation != null
-                    && appToken.animation != WindowManagerService.sDummyAnimation;
-            if (appToken.stepAnimationLocked(mCurrentTime, mInnerDw, mInnerDh)) {
+            final AppWindowAnimator appAnimator = mService.mAppTokens.get(i).mAppAnimator;
+            final boolean wasAnimating = appAnimator.animation != null
+                    && appAnimator.animation != WindowManagerService.sDummyAnimation;
+            if (appAnimator.stepAnimationLocked(mCurrentTime, mInnerDw, mInnerDh)) {
                 mAnimating = true;
             } else if (wasAnimating) {
                 // stopped animating, do one more pass through the layout
                 mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
                 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
-                    mService.debugLayoutRepeats("appToken " + appToken + " done");
+                    mService.debugLayoutRepeats("appToken " + appAnimator.mAppToken + " done",
+                        mPendingLayoutChanges);
                 }
             }
         }
 
         final int NEAT = mService.mExitingAppTokens.size();
         for (i=0; i<NEAT; i++) {
-            final AppWindowToken appToken = mService.mExitingAppTokens.get(i);
-            final boolean wasAnimating = appToken.animation != null
-                    && appToken.animation != WindowManagerService.sDummyAnimation;
-            if (appToken.stepAnimationLocked(mCurrentTime, mInnerDw, mInnerDh)) {
+            final AppWindowAnimator appAnimator = mService.mExitingAppTokens.get(i).mAppAnimator;
+            final boolean wasAnimating = appAnimator.animation != null
+                    && appAnimator.animation != WindowManagerService.sDummyAnimation;
+            if (appAnimator.stepAnimationLocked(mCurrentTime, mInnerDw, mInnerDh)) {
                 mAnimating = true;
             } else if (wasAnimating) {
                 // stopped animating, do one more pass through the layout
                 mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
                 if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
-                    mService.debugLayoutRepeats("exiting appToken " + appToken + " done");
+                    mService.debugLayoutRepeats("exiting appToken " + appAnimator.mAppToken 
+                        + " done", mPendingLayoutChanges);
                 }
             }
         }
@@ -185,13 +193,13 @@
                                 && winAnimator.mAnimation.getDetachWallpaper()) {
                             mDetachedWallpaper = w;
                         }
-                        if (winAnimator.mAnimation.getBackgroundColor() != 0) {
+                        final int backgroundColor = winAnimator.mAnimation.getBackgroundColor();
+                        if (backgroundColor != 0) {
                             if (mWindowAnimationBackground == null
                                     || (winAnimator.mAnimLayer <
                                             mWindowAnimationBackground.mWinAnimator.mAnimLayer)) {
                                 mWindowAnimationBackground = w;
-                                mWindowAnimationBackgroundColor =
-                                        winAnimator.mAnimation.getBackgroundColor();
+                                mWindowAnimationBackgroundColor = backgroundColor;
                             }
                         }
                     }
@@ -201,19 +209,21 @@
                 // If this window's app token is running a detached wallpaper
                 // animation, make a note so we can ensure the wallpaper is
                 // displayed behind it.
-                if (w.mAppToken != null && w.mAppToken.animation != null
-                        && w.mAppToken.animating) {
+                final AppWindowAnimator appAnimator =
+                        w.mAppToken == null ? null : w.mAppToken.mAppAnimator;
+                if (appAnimator != null && appAnimator.animation != null
+                        && appAnimator.animating) {
                     if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0
-                            && w.mAppToken.animation.getDetachWallpaper()) {
+                            && appAnimator.animation.getDetachWallpaper()) {
                         mDetachedWallpaper = w;
                     }
-                    if (w.mAppToken.animation.getBackgroundColor() != 0) {
+                    final int backgroundColor = appAnimator.animation.getBackgroundColor();
+                    if (backgroundColor != 0) {
                         if (mWindowAnimationBackground == null
                                 || (winAnimator.mAnimLayer <
                                         mWindowAnimationBackground.mWinAnimator.mAnimLayer)) {
                             mWindowAnimationBackground = w;
-                            mWindowAnimationBackgroundColor =
-                                    w.mAppToken.animation.getBackgroundColor();
+                            mWindowAnimationBackgroundColor = backgroundColor;
                         }
                     }
                 }
@@ -222,7 +232,8 @@
                     mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
                     mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
                     if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
-                        mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 2");
+                        mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 2",
+                            mPendingLayoutChanges);
                     }
                 }
 
@@ -231,17 +242,18 @@
                         if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
                                 "Animation started that could impact force hide: "
                                 + w);
-                        mService.mInnerFields.mWallpaperForceHidingChanged = true;
+                        mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED;
                         mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
                         if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
-                            mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 3");
+                            mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 3",
+                                mPendingLayoutChanges);
                         }
                         mService.mFocusMayChange = true;
                     } else if (w.isReadyForDisplay() && winAnimator.mAnimation == null) {
                         mForceHiding = true;
                     }
                 } else if (mPolicy.canBeForceHidden(w, attrs)) {
-                    boolean changed;
+                    final boolean changed;
                     if (mForceHiding) {
                         changed = w.hideLw(false, false);
                         if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
@@ -251,7 +263,7 @@
                         if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
                                 "Now policy shown: " + w);
                         if (changed) {
-                            if (mService.mInnerFields.mWallpaperForceHidingChanged
+                            if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
                                     && w.isVisibleNow() /*w.isReadyForDisplay()*/) {
                                 // Assume we will need to animate.  If
                                 // we don't (because the wallpaper will
@@ -275,14 +287,15 @@
                         mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
                         mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
                         if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
-                            mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 4");
+                            mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 4",
+                                mPendingLayoutChanges);
                         }
                     }
                 }
             }
 
             final AppWindowToken atoken = w.mAppToken;
-            if (atoken != null && (!atoken.allDrawn || atoken.freezingScreen)) {
+            if (atoken != null && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
                 if (atoken.lastTransactionSequence != mTransactionSequence) {
                     atoken.lastTransactionSequence = mTransactionSequence;
                     atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
@@ -306,14 +319,14 @@
                         }
                     }
                     if (w != atoken.startingWindow) {
-                        if (!atoken.freezingScreen || !w.mAppFreezing) {
+                        if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
                             atoken.numInterestingWindows++;
                             if (w.isDrawnLw()) {
                                 atoken.numDrawnWindows++;
                                 if (WindowManagerService.DEBUG_VISIBILITY ||
                                         WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG,
                                         "tokenMayBeDrawn: " + atoken
-                                        + " freezingScreen=" + atoken.freezingScreen
+                                        + " freezingScreen=" + atoken.mAppAnimator.freezingScreen
                                         + " mAppFreezing=" + w.mAppFreezing);
                                 mTokenMayBeDrawn = true;
                             }
@@ -326,17 +339,20 @@
                 if (winAnimator.performShowLocked()) {
                     mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
                     if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
-                        mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 5");
+                        mService.debugLayoutRepeats("updateWindowsAndWallpaperLocked 5",
+                            mPendingLayoutChanges);
                     }
                 }
             }
-            if (atoken != null && atoken.thumbnail != null) {
-                if (atoken.thumbnailTransactionSeq != mTransactionSequence) {
-                    atoken.thumbnailTransactionSeq = mTransactionSequence;
-                    atoken.thumbnailLayer = 0;
+            final AppWindowAnimator appAnimator =
+                    atoken == null ? null : atoken.mAppAnimator;
+            if (appAnimator != null && appAnimator.thumbnail != null) {
+                if (appAnimator.thumbnailTransactionSeq != mTransactionSequence) {
+                    appAnimator.thumbnailTransactionSeq = mTransactionSequence;
+                    appAnimator.thumbnailLayer = 0;
                 }
-                if (atoken.thumbnailLayer < winAnimator.mAnimLayer) {
-                    atoken.thumbnailLayer = winAnimator.mAnimLayer;
+                if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
+                    appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
                 }
             }
         } // end forall windows
@@ -348,7 +364,7 @@
         final int NT = mService.mAppTokens.size();
         for (int i=0; i<NT; i++) {
             AppWindowToken wtoken = mService.mAppTokens.get(i);
-            if (wtoken.freezingScreen) {
+            if (wtoken.mAppAnimator.freezingScreen) {
                 int numInteresting = wtoken.numInterestingWindows;
                 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
                     if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
@@ -361,7 +377,6 @@
                             "Setting mOrientationChangeComplete=true because wtoken "
                             + wtoken + " numInteresting=" + numInteresting
                             + " numDrawn=" + wtoken.numDrawnWindows);
-                    mService.mInnerFields.mOrientationChangeComplete = true;
                 }
             } else if (!wtoken.allDrawn) {
                 int numInteresting = wtoken.numInterestingWindows;
@@ -373,7 +388,8 @@
                     wtoken.allDrawn = true;
                     mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
                     if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
-                        mService.debugLayoutRepeats("testTokenMayBeDrawnLocked");
+                        mService.debugLayoutRepeats("testTokenMayBeDrawnLocked",
+                            mPendingLayoutChanges);
                     }
 
                     // We can now show all of the drawn windows!
@@ -419,14 +435,13 @@
                 mScreenRotationAnimation.updateSurfaces();
             }
 
-            final int N = mService.mWindows.size();
-            for (int i=N-1; i>=0; i--) {
+            for (int i = mService.mWindows.size() - 1; i >= 0; i--) {
                 WindowState w = mService.mWindows.get(i);
                 w.mWinAnimator.prepareSurfaceLocked(true);
             }
 
-            if (mService.mDimAnimator != null && mService.mDimAnimator.mDimShown) {
-                mAnimating |= mService.mDimAnimator.updateSurface(mService.mInnerFields.mDimming,
+            if (mDimAnimator != null && mDimAnimator.mDimShown) {
+                mAnimating |= mDimAnimator.updateSurface(mService.mInnerFields.mDimming,
                             mCurrentTime, !mService.okToDisplay());
             }
 
@@ -438,6 +453,10 @@
                     mService.mBlackFrame.clearMatrix();
                 }
             }
+
+            if (mDimParams != null) {
+                mDimAnimator.updateParameters(mContext.getResources(), mDimParams, mCurrentTime);
+            }
         } catch (RuntimeException e) {
             Log.wtf(TAG, "Unhandled exception in Window Manager", e);
         } finally {
@@ -450,7 +469,7 @@
     }
 
     WindowState mCurrentFocus;
-    void setCurrentFocus(WindowState currentFocus) {
+    void setCurrentFocus(final WindowState currentFocus) {
         mCurrentFocus = currentFocus;
     }
 
@@ -462,6 +481,20 @@
         mInnerDh = appHeight;
     }
 
+    void startDimming(final WindowStateAnimator winAnimator, final float target,
+                      final int width, final int height) {
+        if (mDimAnimator == null) {
+            mDimAnimator = new DimAnimator(mService.mFxSession);
+        }
+        mService.mH.sendMessage(mService.mH.obtainMessage(SET_DIM_PARAMETERS,
+                new DimAnimator.Parameters(winAnimator, width, height, target)));
+    }
+
+    // TODO(cmautner): Move into Handler
+    void stopDimming() {
+        mService.mH.sendMessage(mService.mH.obtainMessage(SET_DIM_PARAMETERS, null));
+    }
+
     public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
         if (mWindowDetachedWallpaper != null) {
             pw.print("  mWindowDetachedWallpaper="); pw.println(mWindowDetachedWallpaper);
@@ -470,5 +503,11 @@
             pw.println("  mWindowAnimationBackgroundSurface:");
             mWindowAnimationBackgroundSurface.printTo("    ", pw);
         }
+        if (mDimAnimator != null) {
+            pw.println("  mDimAnimator:");
+            mDimAnimator.printTo("    ", pw);
+        } else {
+            pw.println( "  no DimAnimator ");
+        }
     }
 }
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index afbc348..3d6c9f0 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -44,6 +44,8 @@
 import com.android.server.PowerManagerService;
 import com.android.server.Watchdog;
 import com.android.server.am.BatteryStatsService;
+import com.android.server.input.InputFilter;
+import com.android.server.input.InputManagerService;
 
 import android.Manifest;
 import android.app.ActivityManagerNative;
@@ -149,7 +151,7 @@
         implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
     static final String TAG = "WindowManager";
     static final boolean DEBUG = false;
-    static final boolean DEBUG_ADD_REMOVE = true;
+    static final boolean DEBUG_ADD_REMOVE = false;
     static final boolean DEBUG_FOCUS = false;
     static final boolean DEBUG_ANIM = false;
     static final boolean DEBUG_LAYOUT = false;
@@ -158,7 +160,7 @@
     static final boolean DEBUG_INPUT = false;
     static final boolean DEBUG_INPUT_METHOD = false;
     static final boolean DEBUG_VISIBILITY = false;
-    static final boolean DEBUG_WINDOW_MOVEMENT = true;
+    static final boolean DEBUG_WINDOW_MOVEMENT = false;
     static final boolean DEBUG_TOKEN_MOVEMENT = false;
     static final boolean DEBUG_ORIENTATION = false;
     static final boolean DEBUG_APP_ORIENTATION = false;
@@ -171,7 +173,7 @@
     static final boolean DEBUG_SCREEN_ON = false;
     static final boolean DEBUG_SCREENSHOT = false;
     static final boolean DEBUG_BOOT = false;
-    static final boolean DEBUG_LAYOUT_REPEATS = false;
+    static final boolean DEBUG_LAYOUT_REPEATS = true;
     static final boolean SHOW_SURFACE_ALLOC = false;
     static final boolean SHOW_TRANSACTIONS = false;
     static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS;
@@ -353,7 +355,32 @@
      * controlling the ordering of windows in different applications.  This
      * contains AppWindowToken objects.
      */
-    final ArrayList<AppWindowToken> mAppTokens = new ArrayList<AppWindowToken>();
+    final ArrayList<AppWindowToken> mAppTokens = new ArrayList<AppWindowToken>() {
+        @Override
+        public void add(int index, AppWindowToken object) {
+            synchronized (mAnimator) {
+                super.add(index, object);
+            }
+        };
+        @Override
+        public boolean add(AppWindowToken object) {
+            synchronized (mAnimator) {
+                return super.add(object);
+            }
+        };
+        @Override
+        public AppWindowToken remove(int index) {
+            synchronized (mAnimator) {
+                return super.remove(index);
+            }
+        };
+        @Override
+        public boolean remove(Object object) {
+            synchronized (mAnimator) {
+                return super.remove(object);
+            }
+        };
+    };
 
     /**
      * Application tokens that are in the process of exiting, but still
@@ -370,7 +397,32 @@
     /**
      * Z-ordered (bottom-most first) list of all Window objects.
      */
-    final ArrayList<WindowState> mWindows = new ArrayList<WindowState>();
+    final ArrayList<WindowState> mWindows = new ArrayList<WindowState>() {
+        @Override
+        public void add(int index, WindowState object) {
+            synchronized (mAnimator) {
+                super.add(index, object);
+            }
+        };
+        @Override
+        public boolean add(WindowState object) {
+            synchronized (mAnimator) {
+                return super.add(object);
+            }
+        };
+        @Override
+        public WindowState remove(int index) {
+            synchronized (mAnimator) {
+                return super.remove(index);
+            }
+        };
+        @Override
+        public boolean remove(Object object) {
+            synchronized (mAnimator) {
+                return super.remove(object);
+            }
+        };
+    };
 
     /**
      * Fake windows added to the window manager.  Note: ordered from top to
@@ -427,7 +479,6 @@
     IInputMethodManager mInputMethodManager;
 
     SurfaceSession mFxSession;
-    DimAnimator mDimAnimator = null;
     Watermark mWatermark;
     StrictModeFlash mStrictModeFlash;
 
@@ -577,7 +628,7 @@
     float mTransitionAnimationScale = 1.0f;
     float mAnimatorDurationScale = 1.0f;
 
-    final InputManager mInputManager;
+    final InputManagerService mInputManager;
 
     // Who is holding the screen on.
     Session mHoldingScreenOn;
@@ -590,8 +641,10 @@
     /** Pulled out of performLayoutAndPlaceSurfacesLockedInner in order to refactor into multiple
      * methods. */
     class LayoutFields {
-        static final int SET_UPDATE_ROTATION        = 1 << 0;
-        static final int SET_WALLPAPER_MAY_CHANGE   = 1 << 1;
+        static final int SET_UPDATE_ROTATION                = 1 << 0;
+        static final int SET_WALLPAPER_MAY_CHANGE           = 1 << 1;
+        static final int SET_FORCE_HIDING_CHANGED           = 1 << 2;
+        static final int CLEAR_ORIENTATION_CHANGE_COMPLETE  = 1 << 3;
 
         boolean mWallpaperForceHidingChanged = false;
         boolean mWallpaperMayChange = false;
@@ -843,7 +896,7 @@
                 "KEEP_SCREEN_ON_FLAG");
         mHoldingScreenWakeLock.setReferenceCounted(false);
 
-        mInputManager = new InputManager(context, this);
+        mInputManager = new InputManagerService(context, mInputMonitor);
         mAnimator = new WindowAnimator(this, context, mPolicy);
 
         PolicyThread thr = new PolicyThread(mPolicy, this, context, pm);
@@ -864,6 +917,10 @@
         Watchdog.getInstance().addMonitor(this);
     }
 
+    public InputManagerService getInputManagerService() {
+        return mInputManager;
+    }
+
     @Override
     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
             throws RemoteException {
@@ -1214,7 +1271,7 @@
                 AppWindowToken token = curTarget.mAppToken;
                 WindowState highestTarget = null;
                 int highestPos = 0;
-                if (token.animating || token.animation != null) {
+                if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
                     int pos = localmWindows.indexOf(curTarget);
                     while (pos >= 0) {
                         WindowState win = localmWindows.get(pos);
@@ -1274,7 +1331,7 @@
                 mInputMethodTarget = w;
                 mInputMethodTargetWaitingAnim = false;
                 if (w.mAppToken != null) {
-                    setInputMethodAnimLayerAdjustment(w.mAppToken.animLayerAdjustment);
+                    setInputMethodAnimLayerAdjustment(w.mAppToken.mAppAnimator.animLayerAdjustment);
                 } else {
                     setInputMethodAnimLayerAdjustment(0);
                 }
@@ -1537,12 +1594,12 @@
         if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
                 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
                 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
-                        ? wallpaperTarget.mAppToken.animation : null)
+                        ? wallpaperTarget.mAppToken.mAppAnimator.animation : null)
                 + " upper=" + mUpperWallpaperTarget
                 + " lower=" + mLowerWallpaperTarget);
         return (wallpaperTarget != null
                         && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
-                                && wallpaperTarget.mAppToken.animation != null)))
+                                && wallpaperTarget.mAppToken.mAppAnimator.animation != null)))
                 || mUpperWallpaperTarget != null
                 || mLowerWallpaperTarget != null;
     }
@@ -1582,7 +1639,7 @@
             if (w != mAnimator.mWindowDetachedWallpaper && w.mAppToken != null) {
                 // If this window's app token is hidden and not animating,
                 // it is of no interest to us.
-                if (w.mAppToken.hidden && w.mAppToken.animation == null) {
+                if (w.mAppToken.hidden && w.mAppToken.mAppAnimator.animation == null) {
                     if (DEBUG_WALLPAPER) Slog.v(TAG,
                             "Skipping not hidden or animating token: " + w);
                     continue;
@@ -1597,7 +1654,7 @@
                 foundW = w;
                 foundI = i;
                 if (w == mWallpaperTarget && ((w.mAppToken != null
-                        && w.mAppToken.animation != null)
+                        && w.mAppToken.mAppAnimator.animation != null)
                         || w.mWinAnimator.mAnimation != null)) {
                     // The current wallpaper target is animating, so we'll
                     // look behind it for another possible target and figure
@@ -1656,9 +1713,11 @@
             // animating, then we are in our super special mode!
             if (foundW != null && oldW != null) {
                 boolean oldAnim = oldW.mWinAnimator.mAnimation != null
-                        || (oldW.mAppToken != null && oldW.mAppToken.animation != null);
+                        || (oldW.mAppToken != null
+                            && oldW.mAppToken.mAppAnimator.animation != null);
                 boolean foundAnim = foundW.mWinAnimator.mAnimation != null
-                        || (foundW.mAppToken != null && foundW.mAppToken.animation != null);
+                        || (foundW.mAppToken != null &&
+                            foundW.mAppToken.mAppAnimator.animation != null);
                 if (DEBUG_WALLPAPER) {
                     Slog.v(TAG, "New animation: " + foundAnim
                             + " old animation: " + oldAnim);
@@ -1711,10 +1770,10 @@
             // Is it time to stop animating?
             boolean lowerAnimating = mLowerWallpaperTarget.mWinAnimator.mAnimation != null
                     || (mLowerWallpaperTarget.mAppToken != null
-                            && mLowerWallpaperTarget.mAppToken.animation != null);
+                            && mLowerWallpaperTarget.mAppToken.mAppAnimator.animation != null);
             boolean upperAnimating = mUpperWallpaperTarget.mWinAnimator.mAnimation != null
                     || (mUpperWallpaperTarget.mAppToken != null
-                            && mUpperWallpaperTarget.mAppToken.animation != null);
+                            && mUpperWallpaperTarget.mAppToken.mAppAnimator.animation != null);
             if (!lowerAnimating || !upperAnimating) {
                 if (DEBUG_WALLPAPER) {
                     Slog.v(TAG, "No longer animating wallpaper targets!");
@@ -1736,7 +1795,7 @@
             // between two wallpaper targets.
             mWallpaperAnimLayerAdjustment =
                     (mLowerWallpaperTarget == null && foundW.mAppToken != null)
-                    ? foundW.mAppToken.animLayerAdjustment : 0;
+                    ? foundW.mAppToken.mAppAnimator.animLayerAdjustment : 0;
 
             final int maxLayer = mPolicy.getMaxWallpaperLayer()
                     * TYPE_LAYER_MULTIPLIER
@@ -2007,6 +2066,7 @@
                     winAnimator.computeShownFrameLocked();
                     // No need to lay out the windows - we can just set the wallpaper position
                     // directly.
+                    // TODO(cmautner): Don't move this from here, just lock the WindowAnimator.
                     if (winAnimator.mSurfaceX != wallpaper.mShownFrame.left
                             || winAnimator.mSurfaceY != wallpaper.mShownFrame.top) {
                         Surface.openTransaction();
@@ -2306,7 +2366,7 @@
                 + " mExiting=" + win.mExiting
                 + " isAnimating=" + win.mWinAnimator.isAnimating()
                 + " app-animation="
-                + (win.mAppToken != null ? win.mAppToken.animation : null)
+                + (win.mAppToken != null ? win.mAppToken.mAppAnimator.animation : null)
                 + " inPendingTransaction="
                 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
                 + " mDisplayFrozen=" + mDisplayFrozen);
@@ -3174,13 +3234,13 @@
                     }
                     Slog.v(TAG, "Loaded animation " + a + " for " + wtoken, e);
                 }
-                wtoken.setAnimation(a, initialized);
+                wtoken.mAppAnimator.setAnimation(a, initialized);
             }
         } else {
-            wtoken.clearAnimation();
+            wtoken.mAppAnimator.clearAnimation();
         }
 
-        return wtoken.animation != null;
+        return wtoken.mAppAnimator.animation != null;
     }
 
     // -------------------------------------------------------------
@@ -3325,7 +3385,7 @@
                 "addAppToken()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
-        
+
         // Get the dispatching timeout here while we are not holding any locks so that it
         // can be cached by the AppWindowToken.  The timeout value is used later by the
         // input dispatcher in code that does hold locks.  If we did not cache the value
@@ -3828,14 +3888,16 @@
                             wtoken.clientHidden = ttoken.clientHidden;
                             wtoken.sendAppVisibilityToClients();
                         }
-                        if (ttoken.animation != null) {
-                            wtoken.animation = ttoken.animation;
-                            wtoken.animating = ttoken.animating;
-                            wtoken.animLayerAdjustment = ttoken.animLayerAdjustment;
-                            ttoken.animation = null;
-                            ttoken.animLayerAdjustment = 0;
-                            wtoken.updateLayers();
-                            ttoken.updateLayers();
+                        final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
+                        final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
+                        if (tAppAnimator.animation != null) {
+                            wAppAnimator.animation = tAppAnimator.animation;
+                            wAppAnimator.animating = tAppAnimator.animating;
+                            wAppAnimator.animLayerAdjustment = tAppAnimator.animLayerAdjustment;
+                            tAppAnimator.animation = null;
+                            tAppAnimator.animLayerAdjustment = 0;
+                            wAppAnimator.updateLayers();
+                            tAppAnimator.updateLayers();
                         }
 
                         updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
@@ -3860,18 +3922,20 @@
                         mH.sendMessageAtFrontOfQueue(m);
                         return;
                     }
-                    if (ttoken.thumbnail != null) {
+                    final AppWindowAnimator tAppAnimator = ttoken.mAppAnimator;
+                    final AppWindowAnimator wAppAnimator = wtoken.mAppAnimator;
+                    if (tAppAnimator.thumbnail != null) {
                         // The old token is animating with a thumbnail, transfer
                         // that to the new token.
-                        if (wtoken.thumbnail != null) {
-                            wtoken.thumbnail.destroy();
+                        if (wAppAnimator.thumbnail != null) {
+                            wAppAnimator.thumbnail.destroy();
                         }
-                        wtoken.thumbnail = ttoken.thumbnail;
-                        wtoken.thumbnailX = ttoken.thumbnailX;
-                        wtoken.thumbnailY = ttoken.thumbnailY;
-                        wtoken.thumbnailLayer = ttoken.thumbnailLayer;
-                        wtoken.thumbnailAnimation = ttoken.thumbnailAnimation;
-                        ttoken.thumbnail = null;
+                        wAppAnimator.thumbnail = tAppAnimator.thumbnail;
+                        wAppAnimator.thumbnailX = tAppAnimator.thumbnailX;
+                        wAppAnimator.thumbnailY = tAppAnimator.thumbnailY;
+                        wAppAnimator.thumbnailLayer = tAppAnimator.thumbnailLayer;
+                        wAppAnimator.thumbnailAnimation = tAppAnimator.thumbnailAnimation;
+                        tAppAnimator.thumbnail = null;
                     }
                 }
             }
@@ -3961,12 +4025,12 @@
             boolean runningAppAnimation = false;
 
             if (transit != WindowManagerPolicy.TRANSIT_UNSET) {
-                if (wtoken.animation == sDummyAnimation) {
-                    wtoken.animation = null;
+                if (wtoken.mAppAnimator.animation == sDummyAnimation) {
+                    wtoken.mAppAnimator.animation = null;
                 }
                 applyAnimationLocked(wtoken, lp, transit, visible);
                 changed = true;
-                if (wtoken.animation != null) {
+                if (wtoken.mAppAnimator.animation != null) {
                     delayed = runningAppAnimation = true;
                 }
             }
@@ -4029,7 +4093,7 @@
             }
         }
 
-        if (wtoken.animation != null) {
+        if (wtoken.mAppAnimator.animation != null) {
             delayed = true;
         }
 
@@ -4074,7 +4138,7 @@
 
                 if (DEBUG_APP_TRANSITIONS) Slog.v(
                         TAG, "Setting dummy animation on: " + wtoken);
-                wtoken.setDummyAnimation();
+                wtoken.mAppAnimator.setDummyAnimation();
                 mOpeningApps.remove(wtoken);
                 mClosingApps.remove(wtoken);
                 wtoken.waitingToShow = wtoken.waitingToHide = false;
@@ -4124,7 +4188,7 @@
 
     void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
             boolean unfreezeSurfaceNow, boolean force) {
-        if (wtoken.freezingScreen) {
+        if (wtoken.mAppAnimator.freezingScreen) {
             if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken
                     + " force=" + force);
             final int N = wtoken.allAppWindows.size();
@@ -4142,7 +4206,7 @@
             }
             if (force || unfrozeWindows) {
                 if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken);
-                wtoken.freezingScreen = false;
+                wtoken.mAppAnimator.freezingScreen = false;
                 mAppsFreezingScreen--;
             }
             if (unfreezeSurfaceNow) {
@@ -4165,11 +4229,11 @@
             }
             Slog.i(TAG, "Set freezing of " + wtoken.appToken
                     + ": hidden=" + wtoken.hidden + " freezing="
-                    + wtoken.freezingScreen, e);
+                    + wtoken.mAppAnimator.freezingScreen, e);
         }
         if (!wtoken.hiddenRequested) {
-            if (!wtoken.freezingScreen) {
-                wtoken.freezingScreen = true;
+            if (!wtoken.mAppAnimator.freezingScreen) {
+                wtoken.mAppAnimator.freezingScreen = true;
                 mAppsFreezingScreen++;
                 if (mAppsFreezingScreen == 1) {
                     startFreezingDisplayLocked(false);
@@ -4222,7 +4286,7 @@
             }
             final long origId = Binder.clearCallingIdentity();
             if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token
-                    + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.freezingScreen);
+                    + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.mAppAnimator.freezingScreen);
             unsetAppFreezingScreenLocked(wtoken, true, force);
             Binder.restoreCallingIdentity(origId);
         }
@@ -4257,8 +4321,8 @@
                 }
                 if (DEBUG_APP_TRANSITIONS) Slog.v(
                         TAG, "Removing app " + wtoken + " delayed=" + delayed
-                        + " animation=" + wtoken.animation
-                        + " animating=" + wtoken.animating);
+                        + " animation=" + wtoken.mAppAnimator.animation
+                        + " animating=" + wtoken.mAppAnimator.animating);
                 if (delayed) {
                     // set the token aside because it has an active animation to be finished
                     if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
@@ -4268,9 +4332,8 @@
                     // Make sure there is no animation running on this token,
                     // so any windows associated with it will be removed as
                     // soon as their animations are complete
-                    wtoken.clearAnimation();
-                    wtoken.animation = null;
-                    wtoken.animating = false;
+                    wtoken.mAppAnimator.clearAnimation();
+                    wtoken.mAppAnimator.animating = false;
                 }
                 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
                         "removeAppToken: " + wtoken);
@@ -5052,7 +5115,7 @@
         mPolicy.enableScreenAfterBoot();
 
         // Make sure the last requested orientation has been applied.
-        updateRotationUnchecked(false);
+        updateRotationUnchecked(false, false);
     }
 
     public void showBootMessage(final CharSequence msg, final boolean always) {
@@ -5326,7 +5389,7 @@
 
         mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_LOCKED,
                 rotation == -1 ? mRotation : rotation);
-        updateRotationUnchecked(false);
+        updateRotationUnchecked(false, false);
     }
 
     /**
@@ -5342,7 +5405,7 @@
         if (DEBUG_ORIENTATION) Slog.v(TAG, "thawRotation: mRotation=" + mRotation);
 
         mPolicy.setUserRotationMode(WindowManagerPolicy.USER_ROTATION_FREE, 777); // rot not used
-        updateRotationUnchecked(false);
+        updateRotationUnchecked(false, false);
     }
 
     /**
@@ -5352,8 +5415,8 @@
      * such that the current rotation might need to be updated, such as when the
      * device is docked or rotated into a new posture.
      */
-    public void updateRotation(boolean alwaysSendConfiguration) {
-        updateRotationUnchecked(alwaysSendConfiguration);
+    public void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
+        updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);
     }
 
     /**
@@ -5383,8 +5446,7 @@
         }
     }
 
-    public void updateRotationUnchecked(
-            boolean alwaysSendConfiguration) {
+    public void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {
         if(DEBUG_ORIENTATION) Slog.v(TAG, "updateRotationUnchecked("
                    + "alwaysSendConfiguration=" + alwaysSendConfiguration + ")");
 
@@ -5392,6 +5454,10 @@
         boolean changed;
         synchronized(mWindowMap) {
             changed = updateRotationUncheckedLocked(false);
+            if (!changed || forceRelayout) {
+                mLayoutNeeded = true;
+                performLayoutAndPlaceSurfacesLocked();
+            }
         }
 
         if (changed || alwaysSendConfiguration) {
@@ -6416,8 +6482,8 @@
         final long ident = Binder.clearCallingIdentity();
         
         final int result = mInputManager.injectInputEvent(newEvent, pid, uid,
-                sync ? InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH
-                        : InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
+                sync ? InputManagerService.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH
+                        : InputManagerService.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
                 INJECTION_TIMEOUT_MILLIS);
         
         Binder.restoreCallingIdentity(ident);
@@ -6446,8 +6512,8 @@
         }
         
         final int result = mInputManager.injectInputEvent(newEvent, pid, uid,
-                sync ? InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH
-                        : InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
+                sync ? InputManagerService.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH
+                        : InputManagerService.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
                 INJECTION_TIMEOUT_MILLIS);
         
         Binder.restoreCallingIdentity(ident);
@@ -6476,8 +6542,8 @@
         }
         
         final int result = mInputManager.injectInputEvent(newEvent, pid, uid,
-                sync ? InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH
-                        : InputManager.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
+                sync ? InputManagerService.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH
+                        : InputManagerService.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
                 INJECTION_TIMEOUT_MILLIS);
         
         Binder.restoreCallingIdentity(ident);
@@ -6498,7 +6564,7 @@
         final long ident = Binder.clearCallingIdentity();
         
         final int result = mInputManager.injectInputEvent(ev, pid, uid,
-                InputManager.INPUT_EVENT_INJECTION_SYNC_NONE,
+                InputManagerService.INPUT_EVENT_INJECTION_SYNC_NONE,
                 INJECTION_TIMEOUT_MILLIS);
         
         Binder.restoreCallingIdentity(ident);
@@ -6507,16 +6573,16 @@
     
     private boolean reportInjectionResult(int result, int pid) {
         switch (result) {
-            case InputManager.INPUT_EVENT_INJECTION_PERMISSION_DENIED:
+            case InputManagerService.INPUT_EVENT_INJECTION_PERMISSION_DENIED:
                 Slog.w(TAG, "Input event injection from pid " + pid + " permission denied.");
                 throw new SecurityException(
                         "Injecting to another application requires INJECT_EVENTS permission");
-            case InputManager.INPUT_EVENT_INJECTION_SUCCEEDED:
+            case InputManagerService.INPUT_EVENT_INJECTION_SUCCEEDED:
                 return true;
-            case InputManager.INPUT_EVENT_INJECTION_TIMED_OUT:
+            case InputManagerService.INPUT_EVENT_INJECTION_TIMED_OUT:
                 Slog.w(TAG, "Input event injection from pid " + pid + " timed out.");
                 return false;
-            case InputManager.INPUT_EVENT_INJECTION_FAILED:
+            case InputManagerService.INPUT_EVENT_INJECTION_FAILED:
             default:
                 Slog.w(TAG, "Input event injection from pid " + pid + " failed.");
                 return false;
@@ -6584,7 +6650,7 @@
             mInputManager.setDisplaySize(Display.DEFAULT_DISPLAY,
                     mDisplay.getRawWidth(), mDisplay.getRawHeight(),
                     mDisplay.getRawExternalWidth(), mDisplay.getRawExternalHeight());
-            mPolicy.setInitialDisplaySize(mInitialDisplayWidth, mInitialDisplayHeight);
+            mPolicy.setInitialDisplaySize(mDisplay, mInitialDisplayWidth, mInitialDisplayHeight);
         }
 
         try {
@@ -6657,6 +6723,7 @@
         public static final int ANIMATOR_WHAT_OFFSET = 100000;
         public static final int SET_TRANSPARENT_REGION = ANIMATOR_WHAT_OFFSET + 1;
         public static final int SET_WALLPAPER_OFFSET = ANIMATOR_WHAT_OFFSET + 2;
+        public static final int SET_DIM_PARAMETERS = ANIMATOR_WHAT_OFFSET + 3;
 
         private Session mLastReportedHold;
 
@@ -6980,14 +7047,16 @@
 
                 case APP_FREEZE_TIMEOUT: {
                     synchronized (mWindowMap) {
-                        Slog.w(TAG, "App freeze timeout expired.");
-                        int i = mAppTokens.size();
-                        while (i > 0) {
-                            i--;
-                            AppWindowToken tok = mAppTokens.get(i);
-                            if (tok.freezingScreen) {
-                                Slog.w(TAG, "Force clearing freeze: " + tok);
-                                unsetAppFreezingScreenLocked(tok, true, true);
+                        synchronized (mAnimator) {
+                            Slog.w(TAG, "App freeze timeout expired.");
+                            int i = mAppTokens.size();
+                            while (i > 0) {
+                                i--;
+                                AppWindowToken tok = mAppTokens.get(i);
+                                if (tok.mAppAnimator.freezingScreen) {
+                                    Slog.w(TAG, "Force clearing freeze: " + tok);
+                                    unsetAppFreezingScreenLocked(tok, true, true);
+                                }
                             }
                         }
                     }
@@ -7069,6 +7138,7 @@
                 }
 
                 case BULK_UPDATE_PARAMETERS: {
+                    // Used to send multiple changes from the animation side to the layout side.
                     synchronized (mWindowMap) {
                         // TODO(cmautner): As the number of bits grows, use masks of bit groups to
                         //  eliminate unnecessary tests.
@@ -7078,6 +7148,12 @@
                         if ((msg.arg1 & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) {
                             mInnerFields.mWallpaperMayChange = true;
                         }
+                        if ((msg.arg1 & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) {
+                            mInnerFields.mWallpaperForceHidingChanged = true;
+                        }
+                        if ((msg.arg1 & LayoutFields.CLEAR_ORIENTATION_CHANGE_COMPLETE) != 0) {
+                            mInnerFields.mOrientationChangeComplete = false;
+                        }
 
                         requestTraversalLocked();
                     }
@@ -7087,21 +7163,34 @@
                 // Animation messages. Move to Window{State}Animator
                 case SET_TRANSPARENT_REGION: {
                     // TODO(cmautner): Remove sync.
-                    synchronized (mWindowMap) {
+                    synchronized (mAnimator) {
                         Pair<WindowStateAnimator, Region> pair =
                                 (Pair<WindowStateAnimator, Region>) msg.obj;
                         final WindowStateAnimator winAnimator = pair.first;
                         winAnimator.setTransparentRegionHint(pair.second);
                     }
+
+                    scheduleAnimationLocked();
                     break;
                 }
 
                 case SET_WALLPAPER_OFFSET: {
                     // TODO(cmautner): Remove sync.
-                    synchronized (mWindowMap) {
+                    synchronized (mAnimator) {
                         final WindowStateAnimator winAnimator = (WindowStateAnimator) msg.obj;
                         winAnimator.setWallpaperOffset(msg.arg1, msg.arg2);
                     }
+
+                    scheduleAnimationLocked();
+                    break;
+                }
+
+                case SET_DIM_PARAMETERS: {
+                    synchronized (mAnimator) {
+                        mAnimator.mDimParams = (DimAnimator.Parameters) msg.obj;
+                    }
+
+                    scheduleAnimationLocked();
                     break;
                 }
             }
@@ -7281,7 +7370,7 @@
             mBaseDisplayWidth = width;
             mBaseDisplayHeight = height;
         }
-        mPolicy.setInitialDisplaySize(mBaseDisplayWidth, mBaseDisplayHeight);
+        mPolicy.setInitialDisplaySize(mDisplay, mBaseDisplayWidth, mBaseDisplayHeight);
 
         mLayoutNeeded = true;
 
@@ -7313,8 +7402,8 @@
         }
     }
 
-    public boolean canStatusBarHide() {
-        return mPolicy.canStatusBarHide();
+    public boolean hasSystemNavBar() {
+        return mPolicy.hasSystemNavBar();
     }
 
     // -------------------------------------------------------------
@@ -7450,9 +7539,11 @@
                 w.mLayer = curLayer;
             }
             if (w.mTargetAppToken != null) {
-                w.mWinAnimator.mAnimLayer = w.mLayer + w.mTargetAppToken.animLayerAdjustment;
+                w.mWinAnimator.mAnimLayer =
+                        w.mLayer + w.mTargetAppToken.mAppAnimator.animLayerAdjustment;
             } else if (w.mAppToken != null) {
-                w.mWinAnimator.mAnimLayer = w.mLayer + w.mAppToken.animLayerAdjustment;
+                w.mWinAnimator.mAnimLayer =
+                        w.mLayer + w.mAppToken.mAppAnimator.animLayerAdjustment;
             } else {
                 w.mWinAnimator.mAnimLayer = w.mLayer;
             }
@@ -7886,10 +7977,10 @@
                 AppWindowToken wtoken = mOpeningApps.get(i);
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
                         "Now opening app" + wtoken);
-                wtoken.clearThumbnail();
+                wtoken.mAppAnimator.clearThumbnail();
                 wtoken.reportedVisible = false;
                 wtoken.inPendingTransaction = false;
-                wtoken.animation = null;
+                wtoken.mAppAnimator.animation = null;
                 setTokenVisibilityLocked(wtoken, animLp, true,
                         transit, false);
                 wtoken.updateReportedVisibilityLocked();
@@ -7914,9 +8005,9 @@
                 AppWindowToken wtoken = mClosingApps.get(i);
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
                         "Now closing app" + wtoken);
-                wtoken.clearThumbnail();
+                wtoken.mAppAnimator.clearThumbnail();
                 wtoken.inPendingTransaction = false;
-                wtoken.animation = null;
+                wtoken.mAppAnimator.animation = null;
                 setTokenVisibilityLocked(wtoken, animLp, false,
                         transit, false);
                 wtoken.updateReportedVisibilityLocked();
@@ -7928,7 +8019,7 @@
             }
 
             if (mNextAppTransitionThumbnail != null && topOpeningApp != null
-                    && topOpeningApp.animation != null) {
+                    && topOpeningApp.mAppAnimator.animation != null) {
                 // This thumbnail animation is very special, we need to have
                 // an extra surface with the thumbnail included with the animation.
                 Rect dirty = new Rect(0, 0, mNextAppTransitionThumbnail.getWidth(),
@@ -7937,7 +8028,7 @@
                     Surface surface = new Surface(mFxSession, Process.myPid(),
                             "thumbnail anim", 0, dirty.width(), dirty.height(),
                             PixelFormat.TRANSLUCENT, Surface.HIDDEN);
-                    topOpeningApp.thumbnail = surface;
+                    topOpeningApp.mAppAnimator.thumbnail = surface;
                     if (SHOW_TRANSACTIONS) Slog.i(TAG, "  THUMBNAIL "
                             + surface + ": CREATE");
                     Surface drawSurface = new Surface();
@@ -7946,17 +8037,17 @@
                     c.drawBitmap(mNextAppTransitionThumbnail, 0, 0, null);
                     drawSurface.unlockCanvasAndPost(c);
                     drawSurface.release();
-                    topOpeningApp.thumbnailLayer = topOpeningLayer;
+                    topOpeningApp.mAppAnimator.thumbnailLayer = topOpeningLayer;
                     Animation anim = createThumbnailAnimationLocked(transit, true, true);
-                    topOpeningApp.thumbnailAnimation = anim;
+                    topOpeningApp.mAppAnimator.thumbnailAnimation = anim;
                     anim.restrictDuration(MAX_ANIMATION_DURATION);
                     anim.scaleCurrentDuration(mTransitionAnimationScale);
-                    topOpeningApp.thumbnailX = mNextAppTransitionStartX;
-                    topOpeningApp.thumbnailY = mNextAppTransitionStartY;
+                    topOpeningApp.mAppAnimator.thumbnailX = mNextAppTransitionStartX;
+                    topOpeningApp.mAppAnimator.thumbnailY = mNextAppTransitionStartY;
                 } catch (Surface.OutOfResourcesException e) {
                     Slog.e(TAG, "Can't allocate thumbnail surface w=" + dirty.width()
                             + " h=" + dirty.height(), e);
-                    topOpeningApp.clearThumbnail();
+                    topOpeningApp.mAppAnimator.clearThumbnail();
                 }
             }
 
@@ -8038,7 +8129,6 @@
             }
         }
         mInnerFields.mAdjResult |= adjustWallpaperWindowsLocked();
-        mInnerFields.mWallpaperForceHidingChanged = false;
         if (DEBUG_WALLPAPER) Slog.v(TAG, "****** OLD: " + oldWallpaper
                 + " NEW: " + mWallpaperTarget
                 + " LOWER: " + mLowerWallpaperTarget);
@@ -8177,16 +8267,16 @@
             if (!mInnerFields.mDimming) {
                 //Slog.i(TAG, "DIM BEHIND: " + w);
                 mInnerFields.mDimming = true;
-                if (mDimAnimator == null) {
-                    mDimAnimator = new DimAnimator(mFxSession);
-                }
+                final int width, height;
                 if (attrs.type == WindowManager.LayoutParams.TYPE_BOOT_PROGRESS) {
-                    mDimAnimator.show(mCurDisplayWidth, mCurDisplayHeight);
+                    width = mCurDisplayWidth;
+                    height = mCurDisplayHeight;
                 } else {
-                    mDimAnimator.show(innerDw, innerDh);
+                    width = innerDw;
+                    height = innerDh;
                 }
-                mDimAnimator.updateParameters(mContext.getResources(),
-                        w, currentTime);
+                mAnimator.startDimming(w.mWinAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount,
+                        width, height);
             }
         }
     }
@@ -8223,7 +8313,6 @@
             mExitingAppTokens.get(i).hasVisible = false;
         }
 
-        mInnerFields.mOrientationChangeComplete = true;
         mInnerFields.mHoldScreen = null;
         mInnerFields.mScreenBrightness = -1;
         mInnerFields.mButtonBrightness = -1;
@@ -8252,7 +8341,6 @@
         }
 
         try {
-            mInnerFields.mWallpaperForceHidingChanged = false;
             int repeats = 0;
             
             do {
@@ -8263,7 +8351,8 @@
                     break;
                 }
 
-                if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner");
+                if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("On entry to LockedInner",
+                    mPendingLayoutChanges);
 
                 if ((mPendingLayoutChanges & WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
                     if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
@@ -8294,7 +8383,8 @@
                 // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think
                 // it is animating.
                 mPendingLayoutChanges = 0;
-                if (DEBUG_LAYOUT_REPEATS)  debugLayoutRepeats("loop number " + mLayoutRepeatCount);
+                if (DEBUG_LAYOUT_REPEATS)  debugLayoutRepeats("loop number " + mLayoutRepeatCount,
+                    mPendingLayoutChanges);
                 mPolicy.beginAnimationLw(dw, dh);
                 for (i = mWindows.size() - 1; i >= 0; i--) {
                     WindowState w = mWindows.get(i);
@@ -8303,7 +8393,8 @@
                     }
                 }
                 mPendingLayoutChanges |= mPolicy.finishAnimationLw();
-                if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after finishAnimationLw");
+                if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after finishAnimationLw",
+                    mPendingLayoutChanges);
             } while (mPendingLayoutChanges != 0);
 
             final boolean someoneLosingFocus = !mLosingFocus.isEmpty();
@@ -8337,6 +8428,9 @@
                     updateWallpaperVisibilityLocked();
                 }
             }
+            if (!mInnerFields.mDimming) {
+                mAnimator.stopDimming();
+            }
         } catch (RuntimeException e) {
             Log.wtf(TAG, "Unhandled exception in Window Manager", e);
         } finally {
@@ -8348,7 +8442,8 @@
         // to go.
         if (mAppTransitionReady) {
             mPendingLayoutChanges |= handleAppTransitionReadyLocked();
-            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked");
+            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAppTransitionReadyLocked",
+                mPendingLayoutChanges);
         }
 
         mInnerFields.mAdjResult = 0;
@@ -8361,7 +8456,8 @@
             // be out of sync with it.  So here we will just rebuild the
             // entire app window list.  Fun!
             mPendingLayoutChanges |= handleAnimatingStoppedAndTransitionLocked();
-            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock");
+            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after handleAnimStopAndXitionLock",
+                mPendingLayoutChanges);
         }
 
         if (mInnerFields.mWallpaperForceHidingChanged && mPendingLayoutChanges == 0 &&
@@ -8373,9 +8469,10 @@
             // hard -- the wallpaper now needs to be shown behind
             // something that was hidden.
             mPendingLayoutChanges |= animateAwayWallpaperLocked();
-            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked");
+            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animateAwayWallpaperLocked",
+                mPendingLayoutChanges);
         }
-        
+        mInnerFields.mWallpaperForceHidingChanged = false;
 
         if (mInnerFields.mWallpaperMayChange) {
             if (WindowManagerService.DEBUG_WALLPAPER) Slog.v(TAG,
@@ -8405,7 +8502,7 @@
 
         if (mLayoutNeeded) {
             mPendingLayoutChanges |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
-            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded");
+            if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("mLayoutNeeded", mPendingLayoutChanges);
         }
 
         final int N = mWindows.size();
@@ -8426,7 +8523,8 @@
                         mInnerFields.mWallpaperMayChange = true;
                         mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
                         if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
-                            debugLayoutRepeats("updateWindowsAndWallpaperLocked 1");
+                            debugLayoutRepeats("updateWindowsAndWallpaperLocked 1",
+                                mPendingLayoutChanges);
                         }
                     }
                 }
@@ -8455,7 +8553,7 @@
         // associated with exiting/removed apps
         mAnimator.animate();
         mPendingLayoutChanges |= mAnimator.mPendingLayoutChanges;
-        if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animate()");
+        if (DEBUG_LAYOUT_REPEATS) debugLayoutRepeats("after animate()", mPendingLayoutChanges);
 
         if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                 "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
@@ -8550,9 +8648,8 @@
                 // Make sure there is no animation running on this token,
                 // so any windows associated with it will be removed as
                 // soon as their animations are complete
-                token.clearAnimation();
-                token.animation = null;
-                token.animating = false;
+                token.mAppAnimator.clearAnimation();
+                token.mAppAnimator.animating = false;
                 if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
                         "performLayout: App token exiting now removed" + token);
                 mAppTokens.remove(token);
@@ -8629,6 +8726,7 @@
                 !mInnerFields.mUpdateRotation) {
             checkDrawnWindowsLocked();
         }
+        mInnerFields.mOrientationChangeComplete = true;
 
         // Check to see if we are now in a state where the screen should
         // be enabled, because the window obscured flags have changed.
@@ -8822,7 +8920,7 @@
                 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus);
             final WindowState oldFocus = mCurrentFocus;
             mCurrentFocus = newFocus;
-            mAnimator.setCurrentFocus(mCurrentFocus);
+            mAnimator.setCurrentFocus(newFocus);
             mLosingFocus.remove(newFocus);
             int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
 
@@ -8869,12 +8967,11 @@
         WindowState result = null;
         WindowState win;
 
-        int i = mWindows.size() - 1;
         int nextAppIndex = mAppTokens.size()-1;
         WindowToken nextApp = nextAppIndex >= 0
             ? mAppTokens.get(nextAppIndex) : null;
 
-        while (i >= 0) {
+        for (int i = mWindows.size() - 1; i >= 0; i--) {
             win = mWindows.get(i);
 
             if (localLOGV || DEBUG_FOCUS) Slog.v(
@@ -8887,7 +8984,6 @@
 
             // If this window's application has been removed, just skip it.
             if (thisApp != null && thisApp.removed) {
-                i--;
                 continue;
             }
 
@@ -8927,8 +9023,6 @@
                 result = win;
                 break;
             }
-
-            i--;
         }
 
         return result;
@@ -9192,11 +9286,6 @@
         mPolicy.lockNow();
     }
 
-    void dumpInput(FileDescriptor fd, PrintWriter pw, boolean dumpAll) {
-        pw.println("WINDOW MANAGER INPUT (dumpsys window input)");
-        mInputManager.dump(pw);
-    }
-
     void dumpPolicyLocked(FileDescriptor fd, PrintWriter pw, String[] args, boolean dumpAll) {
         pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
         mPolicy.dump("    ", fd, pw, args);
@@ -9476,12 +9565,6 @@
             pw.print("  mSystemBooted="); pw.print(mSystemBooted);
                     pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
             pw.print("  mLayoutNeeded="); pw.println(mLayoutNeeded);
-            if (mDimAnimator != null) {
-                pw.println("  mDimAnimator:");
-                mDimAnimator.printTo("    ", pw);
-            } else {
-                pw.println( "  no DimAnimator ");
-            }
             pw.print("  mDisplayFrozen="); pw.print(mDisplayFrozen);
                     pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen);
                     pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen);
@@ -9592,7 +9675,6 @@
                 pw.println("Window manager dump options:");
                 pw.println("  [-a] [-h] [cmd] ...");
                 pw.println("  cmd may be one of:");
-                pw.println("    i[input]: input subsystem state");
                 pw.println("    p[policy]: policy state");
                 pw.println("    s[essions]: active sessions");
                 pw.println("    t[okens]: token list");
@@ -9613,10 +9695,7 @@
         if (opti < args.length) {
             String cmd = args[opti];
             opti++;
-            if ("input".equals(cmd) || "i".equals(cmd)) {
-                dumpInput(fd, pw, true);
-                return;
-            } else if ("policy".equals(cmd) || "p".equals(cmd)) {
+            if ("policy".equals(cmd) || "p".equals(cmd)) {
                 synchronized(mWindowMap) {
                     dumpPolicyLocked(fd, pw, args, true);
                 }
@@ -9651,8 +9730,6 @@
             }
         }
 
-        dumpInput(fd, pw, dumpAll);
-
         synchronized(mWindowMap) {
             if (dumpAll) {
                 pw.println("-------------------------------------------------------------------------------");
@@ -9691,10 +9768,10 @@
         requestTraversalLocked();
     }
 
-    void debugLayoutRepeats(final String msg) {
+    void debugLayoutRepeats(final String msg, int pendingLayoutChanges) {
         if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) {
-            Slog.v(TAG, "Layouts looping: " + msg);
-            Slog.v(TAG, "mPendingLayoutChanges = 0x" + Integer.toHexString(mPendingLayoutChanges));
+            Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" +
+                    Integer.toHexString(pendingLayoutChanges));
         }
     }
 
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index b74aa61..4de6425 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -23,6 +23,8 @@
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 
+import com.android.server.input.InputWindowHandle;
+
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Matrix;
@@ -65,6 +67,9 @@
     WindowToken mRootToken;
     AppWindowToken mAppToken;
     AppWindowToken mTargetAppToken;
+
+    // mAttrs.flags is tested in animation without being locked. If the bits tested are ever
+    // modified they will need to be locked.
     final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
     final DeathRecipient mDeathRecipient;
     final WindowState mAttachedWindow;
@@ -621,7 +626,7 @@
         }
         final AppWindowToken atoken = mAppToken;
         final boolean animating = atoken != null
-                ? (atoken.animation != null) : false;
+                ? (atoken.mAppAnimator.animation != null) : false;
         return mHasSurface && !mDestroying && !mExiting
                 && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
                 && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
@@ -637,7 +642,7 @@
     public boolean isWinVisibleLw() {
         final AppWindowToken atoken = mAppToken;
         return mHasSurface && mPolicyVisibility && !mAttachedHidden
-                && (atoken == null || !atoken.hiddenRequested || atoken.animating)
+                && (atoken == null || !atoken.hiddenRequested || atoken.mAppAnimator.animating)
                 && !mExiting && !mDestroying;
     }
 
@@ -685,7 +690,7 @@
         final AppWindowToken atoken = mAppToken;
         if (atoken != null) {
             return ((!mAttachedHidden && !atoken.hiddenRequested)
-                            || mWinAnimator.mAnimation != null || atoken.animation != null);
+                            || mWinAnimator.mAnimation != null || atoken.mAppAnimator.animation != null);
         }
         return !mAttachedHidden || mWinAnimator.mAnimation != null;
     }
@@ -703,7 +708,7 @@
                 && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
                                 && !mRootToken.hidden)
                         || mWinAnimator.mAnimation != null
-                        || ((mAppToken != null) && (mAppToken.animation != null)));
+                        || ((mAppToken != null) && (mAppToken.mAppAnimator.animation != null)));
     }
 
     /**
@@ -746,7 +751,7 @@
         return (mAttrs.format == PixelFormat.OPAQUE
                         || mAttrs.type == TYPE_WALLPAPER)
                 && isDrawnLw() && mWinAnimator.mAnimation == null
-                && (mAppToken == null || mAppToken.animation == null);
+                && (mAppToken == null || mAppToken.mAppAnimator.animation == null);
     }
 
     /**
@@ -867,6 +872,7 @@
         return true;
     }
 
+    @Override
     public boolean hideLw(boolean doAnimation) {
         return hideLw(doAnimation, true);
     }
@@ -909,6 +915,11 @@
         return true;
     }
 
+    @Override
+    public boolean isAlive() {
+        return mClient.asBinder().isBinderAlive();
+    }
+
     private static void applyInsets(Region outRegion, Rect frame, Rect inset) {
         outRegion.set(
                 frame.left + inset.left, frame.top + inset.top,
@@ -962,8 +973,9 @@
             pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
                     pw.print(" mSubLayer="); pw.print(mSubLayer);
                     pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
-                    pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
-                          : (mAppToken != null ? mAppToken.animLayerAdjustment : 0)));
+                    pw.print((mTargetAppToken != null ?
+                            mTargetAppToken.mAppAnimator.animLayerAdjustment
+                          : (mAppToken != null ? mAppToken.mAppAnimator.animLayerAdjustment : 0)));
                     pw.print("="); pw.print(mWinAnimator.mAnimLayer);
                     pw.print(" mLastLayer="); pw.println(mWinAnimator.mLastLayer);
         }
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index 4979a4c..6d0921e 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -5,6 +5,8 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 
+import static com.android.server.wm.WindowManagerService.LayoutFields.CLEAR_ORIENTATION_CHANGE_COMPLETE;
+
 import android.content.Context;
 import android.graphics.Matrix;
 import android.graphics.PixelFormat;
@@ -160,7 +162,7 @@
         return mAnimation != null
                 || (attached != null && attached.mWinAnimator.mAnimation != null)
                 || (atoken != null &&
-                        (atoken.animation != null
+                        (atoken.mAppAnimator.animation != null
                                 || atoken.inPendingTransaction));
     }
 
@@ -226,7 +228,7 @@
             }
             mHasLocalTransformation = false;
             if ((!mLocalAnimating || mAnimationIsEntrance) && mWin.mAppToken != null
-                    && mWin.mAppToken.animation != null) {
+                    && mWin.mAppToken.mAppAnimator.animation != null) {
                 // When our app token is animating, we kind-of pretend like
                 // we are as well.  Note the mLocalAnimating mAnimationIsEntrance
                 // part of this check means that we will only do this if
@@ -313,8 +315,9 @@
         }
 
         finishExit();
-        mService.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
-        if (WindowManagerService.DEBUG_LAYOUT_REPEATS) mService.debugLayoutRepeats("WindowState");
+        mAnimator.mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
+        if (WindowManagerService.DEBUG_LAYOUT_REPEATS) mService.debugLayoutRepeats(
+                "WindowStateAnimator", mAnimator.mPendingLayoutChanges);
 
         if (mWin.mAppToken != null) {
             mWin.mAppToken.updateReportedVisibilityLocked();
@@ -613,9 +616,10 @@
         Transformation attachedTransformation =
                 (mAttachedWindow != null && mAttachedWindow.mWinAnimator.mHasLocalTransformation)
                 ? mAttachedWindow.mWinAnimator.mTransformation : null;
-        Transformation appTransformation =
-                (mWin.mAppToken != null && mWin.mAppToken.hasTransformation)
-                ? mWin.mAppToken.transformation : null;
+        final AppWindowAnimator appAnimator =
+                mWin.mAppToken == null ? null : mWin.mAppToken.mAppAnimator;
+        Transformation appTransformation = (appAnimator != null && appAnimator.hasTransformation)
+                ? appAnimator.transformation : null;
 
         // Wallpapers are animated based on the "real" window they
         // are currently targeting.
@@ -629,11 +633,13 @@
                     Slog.v(TAG, "WP target attached xform: " + attachedTransformation);
                 }
             }
-            if (mService.mWallpaperTarget.mAppToken != null &&
-                    mService.mWallpaperTarget.mAppToken.hasTransformation &&
-                    mService.mWallpaperTarget.mAppToken.animation != null &&
-                    !mService.mWallpaperTarget.mAppToken.animation.getDetachWallpaper()) {
-                appTransformation = mService.mWallpaperTarget.mAppToken.transformation;
+            final AppWindowAnimator wpAppAnimator = mService.mWallpaperTarget.mAppToken == null
+                    ? null : mService.mWallpaperTarget.mAppToken.mAppAnimator;
+            if (wpAppAnimator != null &&
+                    wpAppAnimator.hasTransformation &&
+                    wpAppAnimator.animation != null &&
+                    !wpAppAnimator.animation.getDetachWallpaper()) {
+                appTransformation = wpAppAnimator.transformation;
                 if (WindowManagerService.DEBUG_WALLPAPER && appTransformation != null) {
                     Slog.v(TAG, "WP target app xform: " + appTransformation);
                 }
@@ -916,7 +922,7 @@
         if (displayed) {
             if (w.mOrientationChanging) {
                 if (!w.isDrawnLw()) {
-                    mService.mInnerFields.mOrientationChangeComplete = false;
+                    mAnimator.mBulkUpdateParams |= CLEAR_ORIENTATION_CHANGE_COMPLETE;
                     if (DEBUG_ORIENTATION) Slog.v(TAG,
                             "Orientation continue waiting for draw in " + w);
                 } else {
@@ -981,7 +987,7 @@
                     + (mWin.mAppToken != null ? mWin.mAppToken.hidden : false)
                     + " animating=" + mAnimating
                     + " tok animating="
-                    + (mWin.mAppToken != null ? mWin.mAppToken.animating : false));
+                    + (mWin.mAppToken != null ? mWin.mAppToken.mAppAnimator.animating : false));
             if (!showSurfaceRobustlyLocked()) {
                 return false;
             }
diff --git a/services/jni/Android.mk b/services/jni/Android.mk
index c02dd36..ac4fd15 100644
--- a/services/jni/Android.mk
+++ b/services/jni/Android.mk
@@ -4,9 +4,9 @@
 LOCAL_SRC_FILES:= \
     com_android_server_AlarmManagerService.cpp \
     com_android_server_BatteryService.cpp \
-    com_android_server_InputApplicationHandle.cpp \
-    com_android_server_InputManager.cpp \
-    com_android_server_InputWindowHandle.cpp \
+    com_android_server_input_InputApplicationHandle.cpp \
+    com_android_server_input_InputManagerService.cpp \
+    com_android_server_input_InputWindowHandle.cpp \
     com_android_server_LightsService.cpp \
     com_android_server_PowerManagerService.cpp \
     com_android_server_SerialService.cpp \
diff --git a/services/jni/com_android_server_InputApplicationHandle.cpp b/services/jni/com_android_server_input_InputApplicationHandle.cpp
similarity index 96%
rename from services/jni/com_android_server_InputApplicationHandle.cpp
rename to services/jni/com_android_server_input_InputApplicationHandle.cpp
index c76ab53..0109430 100644
--- a/services/jni/com_android_server_InputApplicationHandle.cpp
+++ b/services/jni/com_android_server_input_InputApplicationHandle.cpp
@@ -21,7 +21,7 @@
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/threads.h>
 
-#include "com_android_server_InputApplicationHandle.h"
+#include "com_android_server_input_InputApplicationHandle.h"
 
 namespace android {
 
@@ -135,12 +135,12 @@
         LOG_FATAL_IF(! var, "Unable to find field " fieldName);
 
 int register_android_server_InputApplicationHandle(JNIEnv* env) {
-    int res = jniRegisterNativeMethods(env, "com/android/server/wm/InputApplicationHandle",
+    int res = jniRegisterNativeMethods(env, "com/android/server/input/InputApplicationHandle",
             gInputApplicationHandleMethods, NELEM(gInputApplicationHandleMethods));
     LOG_FATAL_IF(res < 0, "Unable to register native methods.");
 
     jclass clazz;
-    FIND_CLASS(clazz, "com/android/server/wm/InputApplicationHandle");
+    FIND_CLASS(clazz, "com/android/server/input/InputApplicationHandle");
 
     GET_FIELD_ID(gInputApplicationHandleClassInfo.ptr, clazz,
             "ptr", "I");
diff --git a/services/jni/com_android_server_InputApplicationHandle.h b/services/jni/com_android_server_input_InputApplicationHandle.h
similarity index 100%
rename from services/jni/com_android_server_InputApplicationHandle.h
rename to services/jni/com_android_server_input_InputApplicationHandle.h
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_input_InputManagerService.cpp
similarity index 73%
rename from services/jni/com_android_server_InputManager.cpp
rename to services/jni/com_android_server_input_InputManagerService.cpp
index 5c3e002..22795bf 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_input_InputManagerService.cpp
@@ -46,8 +46,8 @@
 #include <android/graphics/GraphicsJNI.h>
 
 #include "com_android_server_PowerManagerService.h"
-#include "com_android_server_InputApplicationHandle.h"
-#include "com_android_server_InputWindowHandle.h"
+#include "com_android_server_input_InputApplicationHandle.h"
+#include "com_android_server_input_InputWindowHandle.h"
 
 namespace android {
 
@@ -77,7 +77,7 @@
     jmethodID getLongPressTimeout;
     jmethodID getPointerLayer;
     jmethodID getPointerIcon;
-} gCallbacksClassInfo;
+} gServiceClassInfo;
 
 static struct {
     jclass clazz;
@@ -166,7 +166,7 @@
     virtual ~NativeInputManager();
 
 public:
-    NativeInputManager(jobject contextObj, jobject callbacksObj, const sp<Looper>& looper);
+    NativeInputManager(jobject contextObj, jobject serviceObj, const sp<Looper>& looper);
 
     inline sp<InputManager> getInputManager() const { return mInputManager; }
 
@@ -222,7 +222,7 @@
     sp<InputManager> mInputManager;
 
     jobject mContextObj;
-    jobject mCallbacksObj;
+    jobject mServiceObj;
     sp<Looper> mLooper;
 
     Mutex mLock;
@@ -269,12 +269,12 @@
 
 
 NativeInputManager::NativeInputManager(jobject contextObj,
-        jobject callbacksObj, const sp<Looper>& looper) :
+        jobject serviceObj, const sp<Looper>& looper) :
         mLooper(looper) {
     JNIEnv* env = jniEnv();
 
     mContextObj = env->NewGlobalRef(contextObj);
-    mCallbacksObj = env->NewGlobalRef(callbacksObj);
+    mServiceObj = env->NewGlobalRef(serviceObj);
 
     {
         AutoMutex _l(mLock);
@@ -298,7 +298,7 @@
     JNIEnv* env = jniEnv();
 
     env->DeleteGlobalRef(mContextObj);
-    env->DeleteGlobalRef(mCallbacksObj);
+    env->DeleteGlobalRef(mServiceObj);
 }
 
 void NativeInputManager::dump(String8& dump) {
@@ -387,15 +387,15 @@
 void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outConfig) {
     JNIEnv* env = jniEnv();
 
-    jint virtualKeyQuietTime = env->CallIntMethod(mCallbacksObj,
-            gCallbacksClassInfo.getVirtualKeyQuietTimeMillis);
+    jint virtualKeyQuietTime = env->CallIntMethod(mServiceObj,
+            gServiceClassInfo.getVirtualKeyQuietTimeMillis);
     if (!checkAndClearExceptionFromCallback(env, "getVirtualKeyQuietTimeMillis")) {
         outConfig->virtualKeyQuietTime = milliseconds_to_nanoseconds(virtualKeyQuietTime);
     }
 
     outConfig->excludedDeviceNames.clear();
-    jobjectArray excludedDeviceNames = jobjectArray(env->CallObjectMethod(mCallbacksObj,
-            gCallbacksClassInfo.getExcludedDeviceNames));
+    jobjectArray excludedDeviceNames = jobjectArray(env->CallObjectMethod(mServiceObj,
+            gServiceClassInfo.getExcludedDeviceNames));
     if (!checkAndClearExceptionFromCallback(env, "getExcludedDeviceNames") && excludedDeviceNames) {
         jsize length = env->GetArrayLength(excludedDeviceNames);
         for (jsize i = 0; i < length; i++) {
@@ -408,14 +408,14 @@
         env->DeleteLocalRef(excludedDeviceNames);
     }
 
-    jint hoverTapTimeout = env->CallIntMethod(mCallbacksObj,
-            gCallbacksClassInfo.getHoverTapTimeout);
+    jint hoverTapTimeout = env->CallIntMethod(mServiceObj,
+            gServiceClassInfo.getHoverTapTimeout);
     if (!checkAndClearExceptionFromCallback(env, "getHoverTapTimeout")) {
-        jint doubleTapTimeout = env->CallIntMethod(mCallbacksObj,
-                gCallbacksClassInfo.getDoubleTapTimeout);
+        jint doubleTapTimeout = env->CallIntMethod(mServiceObj,
+                gServiceClassInfo.getDoubleTapTimeout);
         if (!checkAndClearExceptionFromCallback(env, "getDoubleTapTimeout")) {
-            jint longPressTimeout = env->CallIntMethod(mCallbacksObj,
-                    gCallbacksClassInfo.getLongPressTimeout);
+            jint longPressTimeout = env->CallIntMethod(mServiceObj,
+                    gServiceClassInfo.getLongPressTimeout);
             if (!checkAndClearExceptionFromCallback(env, "getLongPressTimeout")) {
                 outConfig->pointerGestureTapInterval = milliseconds_to_nanoseconds(hoverTapTimeout);
 
@@ -430,8 +430,8 @@
         }
     }
 
-    jint hoverTapSlop = env->CallIntMethod(mCallbacksObj,
-            gCallbacksClassInfo.getHoverTapSlop);
+    jint hoverTapSlop = env->CallIntMethod(mServiceObj,
+            gServiceClassInfo.getHoverTapSlop);
     if (!checkAndClearExceptionFromCallback(env, "getHoverTapSlop")) {
         outConfig->pointerGestureTapSlop = hoverTapSlop;
     }
@@ -467,8 +467,8 @@
         controller->setDisplayOrientation(mLocked.displayOrientation);
 
         JNIEnv* env = jniEnv();
-        jobject pointerIconObj = env->CallObjectMethod(mCallbacksObj,
-                gCallbacksClassInfo.getPointerIcon);
+        jobject pointerIconObj = env->CallObjectMethod(mServiceObj,
+                gServiceClassInfo.getPointerIcon);
         if (!checkAndClearExceptionFromCallback(env, "getPointerIcon")) {
             PointerIcon pointerIcon;
             status_t status = android_view_PointerIcon_load(env, pointerIconObj,
@@ -490,7 +490,7 @@
 void NativeInputManager::ensureSpriteControllerLocked() {
     if (mLocked.spriteController == NULL) {
         JNIEnv* env = jniEnv();
-        jint layer = env->CallIntMethod(mCallbacksObj, gCallbacksClassInfo.getPointerLayer);
+        jint layer = env->CallIntMethod(mServiceObj, gServiceClassInfo.getPointerLayer);
         if (checkAndClearExceptionFromCallback(env, "getPointerLayer")) {
             layer = -1;
         }
@@ -509,7 +509,7 @@
 
     switch (switchCode) {
     case SW_LID:
-        env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyLidSwitchChanged,
+        env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyLidSwitchChanged,
                 when, switchValue == 0);
         checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged");
         break;
@@ -523,7 +523,7 @@
 
     JNIEnv* env = jniEnv();
 
-    env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyConfigurationChanged, when);
+    env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyConfigurationChanged, when);
     checkAndClearExceptionFromCallback(env, "notifyConfigurationChanged");
 }
 
@@ -540,8 +540,8 @@
     jobject inputWindowHandleObj =
             getInputWindowHandleObjLocalRef(env, inputWindowHandle);
 
-    jlong newTimeout = env->CallLongMethod(mCallbacksObj,
-                gCallbacksClassInfo.notifyANR, inputApplicationHandleObj, inputWindowHandleObj);
+    jlong newTimeout = env->CallLongMethod(mServiceObj,
+                gServiceClassInfo.notifyANR, inputApplicationHandleObj, inputWindowHandleObj);
     if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
         newTimeout = 0; // abort dispatch
     } else {
@@ -563,7 +563,7 @@
     jobject inputWindowHandleObj =
             getInputWindowHandleObjLocalRef(env, inputWindowHandle);
     if (inputWindowHandleObj) {
-        env->CallVoidMethod(mCallbacksObj, gCallbacksClassInfo.notifyInputChannelBroken,
+        env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyInputChannelBroken,
                 inputWindowHandleObj);
         checkAndClearExceptionFromCallback(env, "notifyInputChannelBroken");
 
@@ -574,14 +574,14 @@
 void NativeInputManager::getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
     JNIEnv* env = jniEnv();
 
-    jint keyRepeatTimeout = env->CallIntMethod(mCallbacksObj,
-            gCallbacksClassInfo.getKeyRepeatTimeout);
+    jint keyRepeatTimeout = env->CallIntMethod(mServiceObj,
+            gServiceClassInfo.getKeyRepeatTimeout);
     if (!checkAndClearExceptionFromCallback(env, "getKeyRepeatTimeout")) {
         outConfig->keyRepeatTimeout = milliseconds_to_nanoseconds(keyRepeatTimeout);
     }
 
-    jint keyRepeatDelay = env->CallIntMethod(mCallbacksObj,
-            gCallbacksClassInfo.getKeyRepeatDelay);
+    jint keyRepeatDelay = env->CallIntMethod(mServiceObj,
+            gServiceClassInfo.getKeyRepeatDelay);
     if (!checkAndClearExceptionFromCallback(env, "getKeyRepeatDelay")) {
         outConfig->keyRepeatDelay = milliseconds_to_nanoseconds(keyRepeatDelay);
     }
@@ -734,7 +734,7 @@
     }
 
     // The callee is responsible for recycling the event.
-    jboolean pass = env->CallBooleanMethod(mCallbacksObj, gCallbacksClassInfo.filterInputEvent,
+    jboolean pass = env->CallBooleanMethod(mServiceObj, gServiceClassInfo.filterInputEvent,
             inputEventObj, policyFlags);
     if (checkAndClearExceptionFromCallback(env, "filterInputEvent")) {
         pass = true;
@@ -758,8 +758,8 @@
         jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
         jint wmActions;
         if (keyEventObj) {
-            wmActions = env->CallIntMethod(mCallbacksObj,
-                    gCallbacksClassInfo.interceptKeyBeforeQueueing,
+            wmActions = env->CallIntMethod(mServiceObj,
+                    gServiceClassInfo.interceptKeyBeforeQueueing,
                     keyEventObj, policyFlags, isScreenOn);
             if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
                 wmActions = 0;
@@ -802,8 +802,8 @@
             }
         } else {
             JNIEnv* env = jniEnv();
-            jint wmActions = env->CallIntMethod(mCallbacksObj,
-                        gCallbacksClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
+            jint wmActions = env->CallIntMethod(mServiceObj,
+                        gServiceClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
                         policyFlags);
             if (checkAndClearExceptionFromCallback(env,
                     "interceptMotionBeforeQueueingWhenScreenOff")) {
@@ -858,8 +858,8 @@
         jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
         jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
         if (keyEventObj) {
-            jlong delayMillis = env->CallLongMethod(mCallbacksObj,
-                    gCallbacksClassInfo.interceptKeyBeforeDispatching,
+            jlong delayMillis = env->CallLongMethod(mServiceObj,
+                    gServiceClassInfo.interceptKeyBeforeDispatching,
                     inputWindowHandleObj, keyEventObj, policyFlags);
             bool error = checkAndClearExceptionFromCallback(env, "interceptKeyBeforeDispatching");
             android_view_KeyEvent_recycle(env, keyEventObj);
@@ -891,8 +891,8 @@
         jobject inputWindowHandleObj = getInputWindowHandleObjLocalRef(env, inputWindowHandle);
         jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
         if (keyEventObj) {
-            jobject fallbackKeyEventObj = env->CallObjectMethod(mCallbacksObj,
-                    gCallbacksClassInfo.dispatchUnhandledKey,
+            jobject fallbackKeyEventObj = env->CallObjectMethod(mServiceObj,
+                    gServiceClassInfo.dispatchUnhandledKey,
                     inputWindowHandleObj, keyEventObj, policyFlags);
             if (checkAndClearExceptionFromCallback(env, "dispatchUnhandledKey")) {
                 fallbackKeyEventObj = NULL;
@@ -925,8 +925,8 @@
 bool NativeInputManager::checkInjectEventsPermissionNonReentrant(
         int32_t injectorPid, int32_t injectorUid) {
     JNIEnv* env = jniEnv();
-    jboolean result = env->CallBooleanMethod(mCallbacksObj,
-            gCallbacksClassInfo.checkInjectEventsPermission, injectorPid, injectorUid);
+    jboolean result = env->CallBooleanMethod(mServiceObj,
+            gServiceClassInfo.checkInjectEventsPermission, injectorPid, injectorUid);
     if (checkAndClearExceptionFromCallback(env, "checkInjectEventsPermission")) {
         result = false;
     }
@@ -947,103 +947,75 @@
 
 // ----------------------------------------------------------------------------
 
-static sp<NativeInputManager> gNativeInputManager;
-
-static bool checkInputManagerUnitialized(JNIEnv* env) {
-    if (gNativeInputManager == NULL) {
-        ALOGE("Input manager not initialized.");
-        jniThrowRuntimeException(env, "Input manager not initialized.");
-        return true;
-    }
-    return false;
+static jint nativeInit(JNIEnv* env, jclass clazz,
+        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
+    sp<Looper> looper = android_os_MessageQueue_getLooper(env, messageQueueObj);
+    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj, looper);
+    im->incStrong(serviceObj);
+    return reinterpret_cast<jint>(im);
 }
 
-static void android_server_InputManager_nativeInit(JNIEnv* env, jclass clazz,
-        jobject contextObj, jobject callbacksObj, jobject messageQueueObj) {
-    if (gNativeInputManager == NULL) {
-        sp<Looper> looper = android_os_MessageQueue_getLooper(env, messageQueueObj);
-        gNativeInputManager = new NativeInputManager(contextObj, callbacksObj, looper);
-    } else {
-        ALOGE("Input manager already initialized.");
-        jniThrowRuntimeException(env, "Input manager already initialized.");
-    }
-}
+static void nativeStart(JNIEnv* env, jclass clazz, jint ptr) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
-static void android_server_InputManager_nativeStart(JNIEnv* env, jclass clazz) {
-    if (checkInputManagerUnitialized(env)) {
-        return;
-    }
-
-    status_t result = gNativeInputManager->getInputManager()->start();
+    status_t result = im->getInputManager()->start();
     if (result) {
         jniThrowRuntimeException(env, "Input manager could not be started.");
     }
 }
 
-static void android_server_InputManager_nativeSetDisplaySize(JNIEnv* env, jclass clazz,
+static void nativeSetDisplaySize(JNIEnv* env, jclass clazz, jint ptr,
         jint displayId, jint width, jint height, jint externalWidth, jint externalHeight) {
-    if (checkInputManagerUnitialized(env)) {
-        return;
-    }
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
     // XXX we could get this from the SurfaceFlinger directly instead of requiring it
     // to be passed in like this, not sure which is better but leaving it like this
     // keeps the window manager in direct control of when display transitions propagate down
     // to the input dispatcher
-    gNativeInputManager->setDisplaySize(displayId, width, height, externalWidth, externalHeight);
+    im->setDisplaySize(displayId, width, height, externalWidth, externalHeight);
 }
 
-static void android_server_InputManager_nativeSetDisplayOrientation(JNIEnv* env, jclass clazz,
-        jint displayId, jint orientation) {
-    if (checkInputManagerUnitialized(env)) {
-        return;
-    }
+static void nativeSetDisplayOrientation(JNIEnv* env, jclass clazz,
+        jint ptr, jint displayId, jint orientation) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
-    gNativeInputManager->setDisplayOrientation(displayId, orientation);
+    im->setDisplayOrientation(displayId, orientation);
 }
 
-static jint android_server_InputManager_nativeGetScanCodeState(JNIEnv* env, jclass clazz,
-        jint deviceId, jint sourceMask, jint scanCode) {
-    if (checkInputManagerUnitialized(env)) {
-        return AKEY_STATE_UNKNOWN;
-    }
+static jint nativeGetScanCodeState(JNIEnv* env, jclass clazz,
+        jint ptr, jint deviceId, jint sourceMask, jint scanCode) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
-    return gNativeInputManager->getInputManager()->getReader()->getScanCodeState(
+    return im->getInputManager()->getReader()->getScanCodeState(
             deviceId, uint32_t(sourceMask), scanCode);
 }
 
-static jint android_server_InputManager_nativeGetKeyCodeState(JNIEnv* env, jclass clazz,
-        jint deviceId, jint sourceMask, jint keyCode) {
-    if (checkInputManagerUnitialized(env)) {
-        return AKEY_STATE_UNKNOWN;
-    }
+static jint nativeGetKeyCodeState(JNIEnv* env, jclass clazz,
+        jint ptr, jint deviceId, jint sourceMask, jint keyCode) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
-    return gNativeInputManager->getInputManager()->getReader()->getKeyCodeState(
+    return im->getInputManager()->getReader()->getKeyCodeState(
             deviceId, uint32_t(sourceMask), keyCode);
 }
 
-static jint android_server_InputManager_nativeGetSwitchState(JNIEnv* env, jclass clazz,
-        jint deviceId, jint sourceMask, jint sw) {
-    if (checkInputManagerUnitialized(env)) {
-        return AKEY_STATE_UNKNOWN;
-    }
+static jint nativeGetSwitchState(JNIEnv* env, jclass clazz,
+        jint ptr, jint deviceId, jint sourceMask, jint sw) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
-    return gNativeInputManager->getInputManager()->getReader()->getSwitchState(
+    return im->getInputManager()->getReader()->getSwitchState(
             deviceId, uint32_t(sourceMask), sw);
 }
 
-static jboolean android_server_InputManager_nativeHasKeys(JNIEnv* env, jclass clazz,
-        jint deviceId, jint sourceMask, jintArray keyCodes, jbooleanArray outFlags) {
-    if (checkInputManagerUnitialized(env)) {
-        return JNI_FALSE;
-    }
+static jboolean nativeHasKeys(JNIEnv* env, jclass clazz,
+        jint ptr, jint deviceId, jint sourceMask, jintArray keyCodes, jbooleanArray outFlags) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
     int32_t* codes = env->GetIntArrayElements(keyCodes, NULL);
     uint8_t* flags = env->GetBooleanArrayElements(outFlags, NULL);
     jsize numCodes = env->GetArrayLength(keyCodes);
     jboolean result;
     if (numCodes == env->GetArrayLength(keyCodes)) {
-        result = gNativeInputManager->getInputManager()->getReader()->hasKeys(
+        result = im->getInputManager()->getReader()->hasKeys(
                 deviceId, uint32_t(sourceMask), numCodes, codes, flags);
     } else {
         result = JNI_FALSE;
@@ -1059,21 +1031,18 @@
              "inputChannel is not initialized");
 }
 
-static void android_server_InputManager_handleInputChannelDisposed(JNIEnv* env,
+static void handleInputChannelDisposed(JNIEnv* env,
         jobject inputChannelObj, const sp<InputChannel>& inputChannel, void* data) {
+    NativeInputManager* im = static_cast<NativeInputManager*>(data);
+
     ALOGW("Input channel object '%s' was disposed without first being unregistered with "
             "the input manager!", inputChannel->getName().string());
-
-    if (gNativeInputManager != NULL) {
-        gNativeInputManager->unregisterInputChannel(env, inputChannel);
-    }
+    im->unregisterInputChannel(env, inputChannel);
 }
 
-static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
-        jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {
-    if (checkInputManagerUnitialized(env)) {
-        return;
-    }
+static void nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
+        jint ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
     sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
             inputChannelObj);
@@ -1085,7 +1054,7 @@
     sp<InputWindowHandle> inputWindowHandle =
             android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
 
-    status_t status = gNativeInputManager->registerInputChannel(
+    status_t status = im->registerInputChannel(
             env, inputChannel, inputWindowHandle, monitor);
     if (status) {
         String8 message;
@@ -1096,15 +1065,13 @@
 
     if (! monitor) {
         android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
-                android_server_InputManager_handleInputChannelDisposed, NULL);
+                handleInputChannelDisposed, im);
     }
 }
 
-static void android_server_InputManager_nativeUnregisterInputChannel(JNIEnv* env, jclass clazz,
-        jobject inputChannelObj) {
-    if (checkInputManagerUnitialized(env)) {
-        return;
-    }
+static void nativeUnregisterInputChannel(JNIEnv* env, jclass clazz,
+        jint ptr, jobject inputChannelObj) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
     sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
             inputChannelObj);
@@ -1115,7 +1082,7 @@
 
     android_view_InputChannel_setDisposeCallback(env, inputChannelObj, NULL, NULL);
 
-    status_t status = gNativeInputManager->unregisterInputChannel(env, inputChannel);
+    status_t status = im->unregisterInputChannel(env, inputChannel);
     if (status && status != BAD_VALUE) { // ignore already unregistered channel
         String8 message;
         message.appendFormat("Failed to unregister input channel.  status=%d", status);
@@ -1123,21 +1090,17 @@
     }
 }
 
-static void android_server_InputManager_nativeSetInputFilterEnabled(JNIEnv* env, jclass clazz,
-        jboolean enabled) {
-    if (checkInputManagerUnitialized(env)) {
-        return;
-    }
+static void nativeSetInputFilterEnabled(JNIEnv* env, jclass clazz,
+        jint ptr, jboolean enabled) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
-    gNativeInputManager->getInputManager()->getDispatcher()->setInputFilterEnabled(enabled);
+    im->getInputManager()->getDispatcher()->setInputFilterEnabled(enabled);
 }
 
-static jint android_server_InputManager_nativeInjectInputEvent(JNIEnv* env, jclass clazz,
-        jobject inputEventObj, jint injectorPid, jint injectorUid,
+static jint nativeInjectInputEvent(JNIEnv* env, jclass clazz,
+        jint ptr, jobject inputEventObj, jint injectorPid, jint injectorUid,
         jint syncMode, jint timeoutMillis, jint policyFlags) {
-    if (checkInputManagerUnitialized(env)) {
-        return INPUT_EVENT_INJECTION_FAILED;
-    }
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
     if (env->IsInstanceOf(inputEventObj, gKeyEventClassInfo.clazz)) {
         KeyEvent keyEvent;
@@ -1147,7 +1110,7 @@
             return INPUT_EVENT_INJECTION_FAILED;
         }
 
-        return gNativeInputManager->getInputManager()->getDispatcher()->injectInputEvent(
+        return im->getInputManager()->getDispatcher()->injectInputEvent(
                 & keyEvent, injectorPid, injectorUid, syncMode, timeoutMillis,
                 uint32_t(policyFlags));
     } else if (env->IsInstanceOf(inputEventObj, gMotionEventClassInfo.clazz)) {
@@ -1157,7 +1120,7 @@
             return INPUT_EVENT_INJECTION_FAILED;
         }
 
-        return gNativeInputManager->getInputManager()->getDispatcher()->injectInputEvent(
+        return im->getInputManager()->getDispatcher()->injectInputEvent(
                 motionEvent, injectorPid, injectorUid, syncMode, timeoutMillis,
                 uint32_t(policyFlags));
     } else {
@@ -1166,50 +1129,40 @@
     }
 }
 
-static void android_server_InputManager_nativeSetInputWindows(JNIEnv* env, jclass clazz,
-        jobjectArray windowHandleObjArray) {
-    if (checkInputManagerUnitialized(env)) {
-        return;
-    }
+static void nativeSetInputWindows(JNIEnv* env, jclass clazz,
+        jint ptr, jobjectArray windowHandleObjArray) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
-    gNativeInputManager->setInputWindows(env, windowHandleObjArray);
+    im->setInputWindows(env, windowHandleObjArray);
 }
 
-static void android_server_InputManager_nativeSetFocusedApplication(JNIEnv* env, jclass clazz,
-        jobject applicationHandleObj) {
-    if (checkInputManagerUnitialized(env)) {
-        return;
-    }
+static void nativeSetFocusedApplication(JNIEnv* env, jclass clazz,
+        jint ptr, jobject applicationHandleObj) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
-    gNativeInputManager->setFocusedApplication(env, applicationHandleObj);
+    im->setFocusedApplication(env, applicationHandleObj);
 }
 
-static void android_server_InputManager_nativeSetInputDispatchMode(JNIEnv* env,
-        jclass clazz, jboolean enabled, jboolean frozen) {
-    if (checkInputManagerUnitialized(env)) {
-        return;
-    }
+static void nativeSetInputDispatchMode(JNIEnv* env,
+        jclass clazz, jint ptr, jboolean enabled, jboolean frozen) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
-    gNativeInputManager->setInputDispatchMode(enabled, frozen);
+    im->setInputDispatchMode(enabled, frozen);
 }
 
-static void android_server_InputManager_nativeSetSystemUiVisibility(JNIEnv* env,
-        jclass clazz, jint visibility) {
-    if (checkInputManagerUnitialized(env)) {
-        return;
-    }
+static void nativeSetSystemUiVisibility(JNIEnv* env,
+        jclass clazz, jint ptr, jint visibility) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
-    gNativeInputManager->setSystemUiVisibility(visibility);
+    im->setSystemUiVisibility(visibility);
 }
 
-static jobject android_server_InputManager_nativeGetInputDevice(JNIEnv* env,
-        jclass clazz, jint deviceId) {
-    if (checkInputManagerUnitialized(env)) {
-        return NULL;
-    }
+static jobject nativeGetInputDevice(JNIEnv* env,
+        jclass clazz, jint ptr, jint deviceId) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
     InputDeviceInfo deviceInfo;
-    status_t status = gNativeInputManager->getInputManager()->getReader()->getInputDeviceInfo(
+    status_t status = im->getInputManager()->getReader()->getInputDeviceInfo(
             deviceId, & deviceInfo);
     if (status) {
         return NULL;
@@ -1249,14 +1202,12 @@
     return deviceObj;
 }
 
-static jintArray android_server_InputManager_nativeGetInputDeviceIds(JNIEnv* env,
-        jclass clazz) {
-    if (checkInputManagerUnitialized(env)) {
-        return NULL;
-    }
+static jintArray nativeGetInputDeviceIds(JNIEnv* env,
+        jclass clazz, jint ptr) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
     Vector<int> deviceIds;
-    gNativeInputManager->getInputManager()->getReader()->getInputDeviceIds(deviceIds);
+    im->getInputManager()->getReader()->getInputDeviceIds(deviceIds);
 
     jintArray deviceIdsObj = env->NewIntArray(deviceIds.size());
     if (! deviceIdsObj) {
@@ -1267,25 +1218,21 @@
     return deviceIdsObj;
 }
 
-static void android_server_InputManager_nativeGetInputConfiguration(JNIEnv* env,
-        jclass clazz, jobject configObj) {
-    if (checkInputManagerUnitialized(env)) {
-        return;
-    }
+static void nativeGetInputConfiguration(JNIEnv* env,
+        jclass clazz, jint ptr, jobject configObj) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
     InputConfiguration config;
-    gNativeInputManager->getInputManager()->getReader()->getInputConfiguration(& config);
+    im->getInputManager()->getReader()->getInputConfiguration(& config);
 
     env->SetIntField(configObj, gConfigurationClassInfo.touchscreen, config.touchScreen);
     env->SetIntField(configObj, gConfigurationClassInfo.keyboard, config.keyboard);
     env->SetIntField(configObj, gConfigurationClassInfo.navigation, config.navigation);
 }
 
-static jboolean android_server_InputManager_nativeTransferTouchFocus(JNIEnv* env,
-        jclass clazz, jobject fromChannelObj, jobject toChannelObj) {
-    if (checkInputManagerUnitialized(env)) {
-        return false;
-    }
+static jboolean nativeTransferTouchFocus(JNIEnv* env,
+        jclass clazz, jint ptr, jobject fromChannelObj, jobject toChannelObj) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
     sp<InputChannel> fromChannel =
             android_view_InputChannel_getInputChannel(env, fromChannelObj);
@@ -1296,101 +1243,93 @@
         return false;
     }
 
-    return gNativeInputManager->getInputManager()->getDispatcher()->
+    return im->getInputManager()->getDispatcher()->
             transferTouchFocus(fromChannel, toChannel);
 }
 
-static void android_server_InputManager_nativeSetPointerSpeed(JNIEnv* env,
-        jclass clazz, jint speed) {
-    if (checkInputManagerUnitialized(env)) {
-        return;
-    }
+static void nativeSetPointerSpeed(JNIEnv* env,
+        jclass clazz, jint ptr, jint speed) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
-    gNativeInputManager->setPointerSpeed(speed);
+    im->setPointerSpeed(speed);
 }
 
-static void android_server_InputManager_nativeSetShowTouches(JNIEnv* env,
-        jclass clazz, jboolean enabled) {
-    if (checkInputManagerUnitialized(env)) {
-        return;
-    }
+static void nativeSetShowTouches(JNIEnv* env,
+        jclass clazz, jint ptr, jboolean enabled) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
-    gNativeInputManager->setShowTouches(enabled);
+    im->setShowTouches(enabled);
 }
 
-static jstring android_server_InputManager_nativeDump(JNIEnv* env, jclass clazz) {
-    if (checkInputManagerUnitialized(env)) {
-        return NULL;
-    }
+static jstring nativeDump(JNIEnv* env, jclass clazz, jint ptr) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
     String8 dump;
-    gNativeInputManager->dump(dump);
+    im->dump(dump);
     return env->NewStringUTF(dump.string());
 }
 
-static void android_server_InputManager_nativeMonitor(JNIEnv* env, jclass clazz) {
-    if (checkInputManagerUnitialized(env)) {
-        return;
-    }
+static void nativeMonitor(JNIEnv* env, jclass clazz, jint ptr) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
 
-    gNativeInputManager->getInputManager()->getReader()->monitor();
-    gNativeInputManager->getInputManager()->getDispatcher()->monitor();
+    im->getInputManager()->getReader()->monitor();
+    im->getInputManager()->getDispatcher()->monitor();
 }
 
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gInputManagerMethods[] = {
     /* name, signature, funcPtr */
-    { "nativeInit", "(Landroid/content/Context;"
-            "Lcom/android/server/wm/InputManager$Callbacks;Landroid/os/MessageQueue;)V",
-            (void*) android_server_InputManager_nativeInit },
-    { "nativeStart", "()V",
-            (void*) android_server_InputManager_nativeStart },
-    { "nativeSetDisplaySize", "(IIIII)V",
-            (void*) android_server_InputManager_nativeSetDisplaySize },
-    { "nativeSetDisplayOrientation", "(II)V",
-            (void*) android_server_InputManager_nativeSetDisplayOrientation },
-    { "nativeGetScanCodeState", "(III)I",
-            (void*) android_server_InputManager_nativeGetScanCodeState },
-    { "nativeGetKeyCodeState", "(III)I",
-            (void*) android_server_InputManager_nativeGetKeyCodeState },
-    { "nativeGetSwitchState", "(III)I",
-            (void*) android_server_InputManager_nativeGetSwitchState },
-    { "nativeHasKeys", "(II[I[Z)Z",
-            (void*) android_server_InputManager_nativeHasKeys },
+    { "nativeInit",
+            "(Lcom/android/server/input/InputManagerService;Landroid/content/Context;Landroid/os/MessageQueue;)I",
+            (void*) nativeInit },
+    { "nativeStart", "(I)V",
+            (void*) nativeStart },
+    { "nativeSetDisplaySize", "(IIIIII)V",
+            (void*) nativeSetDisplaySize },
+    { "nativeSetDisplayOrientation", "(III)V",
+            (void*) nativeSetDisplayOrientation },
+    { "nativeGetScanCodeState", "(IIII)I",
+            (void*) nativeGetScanCodeState },
+    { "nativeGetKeyCodeState", "(IIII)I",
+            (void*) nativeGetKeyCodeState },
+    { "nativeGetSwitchState", "(IIII)I",
+            (void*) nativeGetSwitchState },
+    { "nativeHasKeys", "(III[I[Z)Z",
+            (void*) nativeHasKeys },
     { "nativeRegisterInputChannel",
-            "(Landroid/view/InputChannel;Lcom/android/server/wm/InputWindowHandle;Z)V",
-            (void*) android_server_InputManager_nativeRegisterInputChannel },
-    { "nativeUnregisterInputChannel", "(Landroid/view/InputChannel;)V",
-            (void*) android_server_InputManager_nativeUnregisterInputChannel },
-    { "nativeSetInputFilterEnabled", "(Z)V",
-            (void*) android_server_InputManager_nativeSetInputFilterEnabled },
-    { "nativeInjectInputEvent", "(Landroid/view/InputEvent;IIIII)I",
-            (void*) android_server_InputManager_nativeInjectInputEvent },
-    { "nativeSetInputWindows", "([Lcom/android/server/wm/InputWindowHandle;)V",
-            (void*) android_server_InputManager_nativeSetInputWindows },
-    { "nativeSetFocusedApplication", "(Lcom/android/server/wm/InputApplicationHandle;)V",
-            (void*) android_server_InputManager_nativeSetFocusedApplication },
-    { "nativeSetInputDispatchMode", "(ZZ)V",
-            (void*) android_server_InputManager_nativeSetInputDispatchMode },
-    { "nativeSetSystemUiVisibility", "(I)V",
-            (void*) android_server_InputManager_nativeSetSystemUiVisibility },
-    { "nativeGetInputDevice", "(I)Landroid/view/InputDevice;",
-            (void*) android_server_InputManager_nativeGetInputDevice },
-    { "nativeGetInputDeviceIds", "()[I",
-            (void*) android_server_InputManager_nativeGetInputDeviceIds },
-    { "nativeGetInputConfiguration", "(Landroid/content/res/Configuration;)V",
-            (void*) android_server_InputManager_nativeGetInputConfiguration },
-    { "nativeTransferTouchFocus", "(Landroid/view/InputChannel;Landroid/view/InputChannel;)Z",
-            (void*) android_server_InputManager_nativeTransferTouchFocus },
-    { "nativeSetPointerSpeed", "(I)V",
-            (void*) android_server_InputManager_nativeSetPointerSpeed },
-    { "nativeSetShowTouches", "(Z)V",
-            (void*) android_server_InputManager_nativeSetShowTouches },
-    { "nativeDump", "()Ljava/lang/String;",
-            (void*) android_server_InputManager_nativeDump },
-    { "nativeMonitor", "()V",
-            (void*) android_server_InputManager_nativeMonitor },
+            "(ILandroid/view/InputChannel;Lcom/android/server/input/InputWindowHandle;Z)V",
+            (void*) nativeRegisterInputChannel },
+    { "nativeUnregisterInputChannel", "(ILandroid/view/InputChannel;)V",
+            (void*) nativeUnregisterInputChannel },
+    { "nativeSetInputFilterEnabled", "(IZ)V",
+            (void*) nativeSetInputFilterEnabled },
+    { "nativeInjectInputEvent", "(ILandroid/view/InputEvent;IIIII)I",
+            (void*) nativeInjectInputEvent },
+    { "nativeSetInputWindows", "(I[Lcom/android/server/input/InputWindowHandle;)V",
+            (void*) nativeSetInputWindows },
+    { "nativeSetFocusedApplication", "(ILcom/android/server/input/InputApplicationHandle;)V",
+            (void*) nativeSetFocusedApplication },
+    { "nativeSetInputDispatchMode", "(IZZ)V",
+            (void*) nativeSetInputDispatchMode },
+    { "nativeSetSystemUiVisibility", "(II)V",
+            (void*) nativeSetSystemUiVisibility },
+    { "nativeGetInputDevice", "(II)Landroid/view/InputDevice;",
+            (void*) nativeGetInputDevice },
+    { "nativeGetInputDeviceIds", "(I)[I",
+            (void*) nativeGetInputDeviceIds },
+    { "nativeGetInputConfiguration", "(ILandroid/content/res/Configuration;)V",
+            (void*) nativeGetInputConfiguration },
+    { "nativeTransferTouchFocus", "(ILandroid/view/InputChannel;Landroid/view/InputChannel;)Z",
+            (void*) nativeTransferTouchFocus },
+    { "nativeSetPointerSpeed", "(II)V",
+            (void*) nativeSetPointerSpeed },
+    { "nativeSetShowTouches", "(IZ)V",
+            (void*) nativeSetShowTouches },
+    { "nativeDump", "(I)Ljava/lang/String;",
+            (void*) nativeDump },
+    { "nativeMonitor", "(I)V",
+            (void*) nativeMonitor },
 };
 
 #define FIND_CLASS(var, className) \
@@ -1406,77 +1345,77 @@
         LOG_FATAL_IF(! var, "Unable to find field " fieldName);
 
 int register_android_server_InputManager(JNIEnv* env) {
-    int res = jniRegisterNativeMethods(env, "com/android/server/wm/InputManager",
+    int res = jniRegisterNativeMethods(env, "com/android/server/input/InputManagerService",
             gInputManagerMethods, NELEM(gInputManagerMethods));
     LOG_FATAL_IF(res < 0, "Unable to register native methods.");
 
     // Callbacks
 
     jclass clazz;
-    FIND_CLASS(clazz, "com/android/server/wm/InputManager$Callbacks");
+    FIND_CLASS(clazz, "com/android/server/input/InputManagerService");
 
-    GET_METHOD_ID(gCallbacksClassInfo.notifyConfigurationChanged, clazz,
+    GET_METHOD_ID(gServiceClassInfo.notifyConfigurationChanged, clazz,
             "notifyConfigurationChanged", "(J)V");
 
-    GET_METHOD_ID(gCallbacksClassInfo.notifyLidSwitchChanged, clazz,
+    GET_METHOD_ID(gServiceClassInfo.notifyLidSwitchChanged, clazz,
             "notifyLidSwitchChanged", "(JZ)V");
 
-    GET_METHOD_ID(gCallbacksClassInfo.notifyInputChannelBroken, clazz,
-            "notifyInputChannelBroken", "(Lcom/android/server/wm/InputWindowHandle;)V");
+    GET_METHOD_ID(gServiceClassInfo.notifyInputChannelBroken, clazz,
+            "notifyInputChannelBroken", "(Lcom/android/server/input/InputWindowHandle;)V");
 
-    GET_METHOD_ID(gCallbacksClassInfo.notifyANR, clazz,
+    GET_METHOD_ID(gServiceClassInfo.notifyANR, clazz,
             "notifyANR",
-            "(Lcom/android/server/wm/InputApplicationHandle;Lcom/android/server/wm/InputWindowHandle;)J");
+            "(Lcom/android/server/input/InputApplicationHandle;Lcom/android/server/input/InputWindowHandle;)J");
 
-    GET_METHOD_ID(gCallbacksClassInfo.filterInputEvent, clazz,
+    GET_METHOD_ID(gServiceClassInfo.filterInputEvent, clazz,
             "filterInputEvent", "(Landroid/view/InputEvent;I)Z");
 
-    GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeQueueing, clazz,
+    GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeQueueing, clazz,
             "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;IZ)I");
 
-    GET_METHOD_ID(gCallbacksClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
+    GET_METHOD_ID(gServiceClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
             clazz,
             "interceptMotionBeforeQueueingWhenScreenOff", "(I)I");
 
-    GET_METHOD_ID(gCallbacksClassInfo.interceptKeyBeforeDispatching, clazz,
+    GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeDispatching, clazz,
             "interceptKeyBeforeDispatching",
-            "(Lcom/android/server/wm/InputWindowHandle;Landroid/view/KeyEvent;I)J");
+            "(Lcom/android/server/input/InputWindowHandle;Landroid/view/KeyEvent;I)J");
 
-    GET_METHOD_ID(gCallbacksClassInfo.dispatchUnhandledKey, clazz,
+    GET_METHOD_ID(gServiceClassInfo.dispatchUnhandledKey, clazz,
             "dispatchUnhandledKey",
-            "(Lcom/android/server/wm/InputWindowHandle;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
+            "(Lcom/android/server/input/InputWindowHandle;Landroid/view/KeyEvent;I)Landroid/view/KeyEvent;");
 
-    GET_METHOD_ID(gCallbacksClassInfo.checkInjectEventsPermission, clazz,
+    GET_METHOD_ID(gServiceClassInfo.checkInjectEventsPermission, clazz,
             "checkInjectEventsPermission", "(II)Z");
 
-    GET_METHOD_ID(gCallbacksClassInfo.getVirtualKeyQuietTimeMillis, clazz,
+    GET_METHOD_ID(gServiceClassInfo.getVirtualKeyQuietTimeMillis, clazz,
             "getVirtualKeyQuietTimeMillis", "()I");
 
-    GET_METHOD_ID(gCallbacksClassInfo.getExcludedDeviceNames, clazz,
+    GET_METHOD_ID(gServiceClassInfo.getExcludedDeviceNames, clazz,
             "getExcludedDeviceNames", "()[Ljava/lang/String;");
 
-    GET_METHOD_ID(gCallbacksClassInfo.getKeyRepeatTimeout, clazz,
+    GET_METHOD_ID(gServiceClassInfo.getKeyRepeatTimeout, clazz,
             "getKeyRepeatTimeout", "()I");
 
-    GET_METHOD_ID(gCallbacksClassInfo.getKeyRepeatDelay, clazz,
+    GET_METHOD_ID(gServiceClassInfo.getKeyRepeatDelay, clazz,
             "getKeyRepeatDelay", "()I");
 
-    GET_METHOD_ID(gCallbacksClassInfo.getHoverTapTimeout, clazz,
+    GET_METHOD_ID(gServiceClassInfo.getHoverTapTimeout, clazz,
             "getHoverTapTimeout", "()I");
 
-    GET_METHOD_ID(gCallbacksClassInfo.getHoverTapSlop, clazz,
+    GET_METHOD_ID(gServiceClassInfo.getHoverTapSlop, clazz,
             "getHoverTapSlop", "()I");
 
-    GET_METHOD_ID(gCallbacksClassInfo.getDoubleTapTimeout, clazz,
+    GET_METHOD_ID(gServiceClassInfo.getDoubleTapTimeout, clazz,
             "getDoubleTapTimeout", "()I");
 
-    GET_METHOD_ID(gCallbacksClassInfo.getLongPressTimeout, clazz,
+    GET_METHOD_ID(gServiceClassInfo.getLongPressTimeout, clazz,
             "getLongPressTimeout", "()I");
 
-    GET_METHOD_ID(gCallbacksClassInfo.getPointerLayer, clazz,
+    GET_METHOD_ID(gServiceClassInfo.getPointerLayer, clazz,
             "getPointerLayer", "()I");
 
-    GET_METHOD_ID(gCallbacksClassInfo.getPointerIcon, clazz,
+    GET_METHOD_ID(gServiceClassInfo.getPointerIcon, clazz,
             "getPointerIcon", "()Landroid/view/PointerIcon;");
 
     // KeyEvent
@@ -1484,7 +1423,6 @@
     FIND_CLASS(gKeyEventClassInfo.clazz, "android/view/KeyEvent");
     gKeyEventClassInfo.clazz = jclass(env->NewGlobalRef(gKeyEventClassInfo.clazz));
 
-
     // MotionEvent
 
     FIND_CLASS(gMotionEventClassInfo.clazz, "android/view/MotionEvent");
diff --git a/services/jni/com_android_server_InputWindowHandle.cpp b/services/jni/com_android_server_input_InputWindowHandle.cpp
similarity index 96%
rename from services/jni/com_android_server_InputWindowHandle.cpp
rename to services/jni/com_android_server_input_InputWindowHandle.cpp
index 0607eee..01fb781 100644
--- a/services/jni/com_android_server_InputWindowHandle.cpp
+++ b/services/jni/com_android_server_input_InputWindowHandle.cpp
@@ -24,8 +24,8 @@
 #include <android_view_InputChannel.h>
 #include <android/graphics/Region.h>
 
-#include "com_android_server_InputWindowHandle.h"
-#include "com_android_server_InputApplicationHandle.h"
+#include "com_android_server_input_InputWindowHandle.h"
+#include "com_android_server_input_InputApplicationHandle.h"
 
 namespace android {
 
@@ -218,19 +218,19 @@
         LOG_FATAL_IF(! var, "Unable to find field " fieldName);
 
 int register_android_server_InputWindowHandle(JNIEnv* env) {
-    int res = jniRegisterNativeMethods(env, "com/android/server/wm/InputWindowHandle",
+    int res = jniRegisterNativeMethods(env, "com/android/server/input/InputWindowHandle",
             gInputWindowHandleMethods, NELEM(gInputWindowHandleMethods));
     LOG_FATAL_IF(res < 0, "Unable to register native methods.");
 
     jclass clazz;
-    FIND_CLASS(clazz, "com/android/server/wm/InputWindowHandle");
+    FIND_CLASS(clazz, "com/android/server/input/InputWindowHandle");
 
     GET_FIELD_ID(gInputWindowHandleClassInfo.ptr, clazz,
             "ptr", "I");
 
     GET_FIELD_ID(gInputWindowHandleClassInfo.inputApplicationHandle,
             clazz,
-            "inputApplicationHandle", "Lcom/android/server/wm/InputApplicationHandle;");
+            "inputApplicationHandle", "Lcom/android/server/input/InputApplicationHandle;");
 
     GET_FIELD_ID(gInputWindowHandleClassInfo.inputChannel, clazz,
             "inputChannel", "Landroid/view/InputChannel;");
diff --git a/services/jni/com_android_server_InputWindowHandle.h b/services/jni/com_android_server_input_InputWindowHandle.h
similarity index 100%
rename from services/jni/com_android_server_InputWindowHandle.h
rename to services/jni/com_android_server_input_InputWindowHandle.h
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index dd6c426..16ddd91 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -35,6 +35,7 @@
 
 #include <gui/ISensorServer.h>
 #include <gui/ISensorEventConnection.h>
+#include <gui/SensorEventQueue.h>
 
 #include <hardware/sensors.h>
 
@@ -587,10 +588,9 @@
         count = numEvents;
     }
 
-    if (count == 0)
-        return 0;
-
-    ssize_t size = mChannel->write(scratch, count*sizeof(sensors_event_t));
+    // NOTE: ASensorEvent and sensors_event_t are the same type
+    ssize_t size = SensorEventQueue::write(mChannel,
+            reinterpret_cast<ASensorEvent const*>(scratch), count);
     if (size == -EAGAIN) {
         // the destination doesn't accept events anymore, it's probably
         // full. For now, we just drop the events on the floor.
@@ -598,9 +598,6 @@
         return size;
     }
 
-    //ALOGE_IF(size<0, "dropping %d events on the floor (%s)",
-    //        count, strerror(-size));
-
     return size < 0 ? status_t(size) : status_t(NO_ERROR);
 }
 
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 60be35a..cc3c328 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -32,6 +32,7 @@
     <uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
     <uses-permission android:name="android.permission.MODIFY_NETWORK_ACCOUNTING" />
     <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
 
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 88ee867..1773e33 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -70,6 +70,7 @@
 import android.os.INetworkManagementService;
 import android.os.IPowerManager;
 import android.os.MessageQueue.IdleHandler;
+import android.os.SystemClock;
 import android.os.UserId;
 import android.test.AndroidTestCase;
 import android.test.mock.MockPackageManager;
diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
index daf20183..103d8e1 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
@@ -84,7 +84,7 @@
  */
 @LargeTest
 public class NetworkStatsServiceTest extends AndroidTestCase {
-    private static final String TAG = "NetworkStatsServiceTest";
+    private static final String TAG  = "NetworkStatsServiceTest";
 
     private static final String TEST_IFACE = "test0";
     private static final String TEST_IFACE2 = "test1";
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkStatsCollectionTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkStatsCollectionTest.java
index 7f05f56..e40f166 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkStatsCollectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkStatsCollectionTest.java
@@ -20,8 +20,6 @@
 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
 
 import android.content.res.Resources;
-import android.net.ConnectivityManager;
-import android.net.NetworkIdentity;
 import android.net.NetworkStats;
 import android.net.NetworkTemplate;
 import android.test.AndroidTestCase;
@@ -145,12 +143,6 @@
         }
     }
 
-    public static NetworkIdentitySet buildWifiIdent() {
-        final NetworkIdentitySet set = new NetworkIdentitySet();
-        set.add(new NetworkIdentity(ConnectivityManager.TYPE_WIFI, 0, null, false));
-        return set;
-    }
-
     private static void assertSummaryTotal(NetworkStatsCollection collection,
             NetworkTemplate template, long rxBytes, long rxPackets, long txBytes, long txPackets) {
         final NetworkStats.Entry entry = collection.getSummary(
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 6d3b46d..bc50906 100755
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -23,7 +23,6 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
-import android.util.Log;
 
 import com.android.internal.telephony.IPhoneSubInfo;
 import com.android.internal.telephony.ITelephony;
@@ -85,6 +84,10 @@
         return sInstance;
     }
 
+    /** {@hide} */
+    public static TelephonyManager from(Context context) {
+        return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+    }
 
     //
     // Broadcast Intent actions
diff --git a/test-runner/src/android/test/AndroidTestRunner.java b/test-runner/src/android/test/AndroidTestRunner.java
index fc9832c..30876d0 100644
--- a/test-runner/src/android/test/AndroidTestRunner.java
+++ b/test-runner/src/android/test/AndroidTestRunner.java
@@ -28,6 +28,7 @@
 import junit.framework.TestSuite;
 import junit.runner.BaseTestRunner;
 
+import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.util.List;
 
@@ -91,15 +92,35 @@
 
     private TestCase buildSingleTestMethod(Class testClass, String testMethodName) {
         try {
-            TestCase testCase = (TestCase) testClass.newInstance();
+            Constructor c = testClass.getConstructor();
+            return newSingleTestMethod(testClass, testMethodName, c);
+        } catch (NoSuchMethodException e) {
+        }
+
+        try {
+            Constructor c = testClass.getConstructor(String.class);
+            return newSingleTestMethod(testClass, testMethodName, c, testMethodName);
+        } catch (NoSuchMethodException e) {
+        }
+
+        return null;
+    }
+
+    private TestCase newSingleTestMethod(Class testClass, String testMethodName,
+            Constructor constructor, Object... args) {
+        try {
+            TestCase testCase = (TestCase) constructor.newInstance(args);
             testCase.setName(testMethodName);
             return testCase;
         } catch (IllegalAccessException e) {
             runFailed("Could not access test class. Class: " + testClass.getName());
         } catch (InstantiationException e) {
             runFailed("Could not instantiate test class. Class: " + testClass.getName());
+        } catch (IllegalArgumentException e) {
+            runFailed("Illegal argument passed to constructor. Class: " + testClass.getName());
+        } catch (InvocationTargetException e) {
+            runFailed("Constructor thew an exception. Class: " + testClass.getName());
         }
-
         return null;
     }
 
diff --git a/tests/BiDiTests/AndroidManifest.xml b/tests/BiDiTests/AndroidManifest.xml
index c60edd8..4aead814 100644
--- a/tests/BiDiTests/AndroidManifest.xml
+++ b/tests/BiDiTests/AndroidManifest.xml
@@ -19,7 +19,9 @@
     android:versionCode="1"
     android:versionName="1.0">
 
-    <application android:label="BiDiTests" android:hardwareAccelerated="true">
+    <application android:label="BiDiTests"
+                 android:hardwareAccelerated="true"
+                 android:supportsRtl="true" >
 
         <activity android:name=".BiDiTestActivity"
             android:windowSoftInputMode="stateAlwaysHidden">
diff --git a/tests/BiDiTests/res/layout/textview_alignment_ltr.xml b/tests/BiDiTests/res/layout/textview_alignment_ltr.xml
new file mode 100644
index 0000000..0e1adba
--- /dev/null
+++ b/tests/BiDiTests/res/layout/textview_alignment_ltr.xml
@@ -0,0 +1,578 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/textview_alignment_ltr"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:layoutDirection="ltr">
+
+        <TableLayout android:orientation="vertical"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content">
+
+            <TableRow>
+                <TextView android:text="(unspecified)"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/textview_text"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/hebrew_text"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
+
+            <TableRow>
+                <TextView android:text="gravity (default)"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/textview_text"
+                          android:textAlignment="gravity"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/hebrew_text"
+                          android:textAlignment="gravity"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
+
+            <TableRow>
+                <TextView android:text="gravity left"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/textview_text"
+                          android:textAlignment="gravity"
+                          android:gravity="left"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/hebrew_text"
+                          android:textAlignment="gravity"
+                          android:gravity="left"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
+
+            <TableRow>
+                <TextView android:text="gravity right"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/textview_text"
+                          android:textAlignment="gravity"
+                          android:gravity="right"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/hebrew_text"
+                          android:textAlignment="gravity"
+                          android:gravity="right"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
+
+            <TableRow>
+                <TextView android:text="gravity start"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/textview_text"
+                          android:textAlignment="gravity"
+                          android:gravity="start"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/hebrew_text"
+                          android:textAlignment="gravity"
+                          android:gravity="start"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
+
+            <TableRow>
+                <TextView android:text="gravity end"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/textview_text"
+                          android:textAlignment="gravity"
+                          android:gravity="end"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/hebrew_text"
+                          android:textAlignment="gravity"
+                          android:gravity="end"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
+
+            <TableRow>
+                <TextView android:text="gravity center"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/textview_text"
+                          android:textAlignment="gravity"
+                          android:gravity="center"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/hebrew_text"
+                          android:textAlignment="gravity"
+                          android:gravity="center"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
+
+            <TableRow>
+                <TextView android:text="gravity center_horizontal"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/textview_text"
+                          android:textAlignment="gravity"
+                          android:gravity="center_horizontal"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/hebrew_text"
+                          android:textAlignment="gravity"
+                          android:gravity="center_horizontal"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
+
+            <TableRow>
+                <TextView android:text="center"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/textview_text"
+                          android:textAlignment="center"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/hebrew_text"
+                          android:textAlignment="center"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
+
+            <TableRow>
+                <TextView android:text="textStart"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/textview_text"
+                          android:textAlignment="textStart"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/hebrew_text"
+                          android:textAlignment="textStart"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
+
+            <TableRow>
+                <TextView android:text="textEnd"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/textview_text"
+                          android:textAlignment="textEnd"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/hebrew_text"
+                          android:textAlignment="textEnd"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
+
+            <TableRow>
+                <TextView android:text="viewStart"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginRight="7dip"
+                          android:layout_marginLeft="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/textview_text"
+                          android:textAlignment="viewStart"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/hebrew_text"
+                          android:textAlignment="viewStart"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
+
+            <TableRow>
+                <TextView android:text="viewEnd"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginRight="7dip"
+                          android:layout_marginLeft="7dip"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/textview_text"
+                          android:textAlignment="viewEnd"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/hebrew_text"
+                          android:textAlignment="viewEnd"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                          />
+            </TableRow>
+
+            <TableRow android:textAlignment="gravity"
+                      android:gravity="center_horizontal">
+
+                <TextView android:text="inherit gravity (default)"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginRight="7dip"
+                          android:layout_marginLeft="7dip"
+                        />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/textview_text"
+                          android:textAlignment="inherit"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                        />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/hebrew_text"
+                          android:textAlignment="inherit"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                        />
+            </TableRow>
+
+            <TableRow android:textAlignment="center">
+
+                <TextView android:text="inherit gravity center"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginRight="7dip"
+                          android:layout_marginLeft="7dip"
+                        />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/textview_text"
+                          android:textAlignment="inherit"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                        />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/hebrew_text"
+                          android:textAlignment="inherit"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                        />
+            </TableRow>
+
+            <TableRow android:textAlignment="textStart">
+
+                <TextView android:text="inherit textStart"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginRight="7dip"
+                          android:layout_marginLeft="7dip"
+                        />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/textview_text"
+                          android:textAlignment="inherit"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                        />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/hebrew_text"
+                          android:textAlignment="inherit"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                        />
+            </TableRow>
+
+            <TableRow android:textAlignment="textEnd">
+
+                <TextView android:text="inherit textEnd"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginRight="7dip"
+                          android:layout_marginLeft="7dip"
+                        />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/textview_text"
+                          android:textAlignment="inherit"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                        />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/hebrew_text"
+                          android:textAlignment="inherit"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                        />
+            </TableRow>
+
+            <TableRow android:textAlignment="viewStart">
+
+                <TextView android:text="inherit viewStart"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginRight="7dip"
+                          android:layout_marginLeft="7dip"
+                        />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/textview_text"
+                          android:textAlignment="inherit"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                        />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/hebrew_text"
+                          android:textAlignment="inherit"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                        />
+            </TableRow>
+
+            <TableRow android:textAlignment="viewEnd">
+
+                <TextView android:text="inherit viewEnd"
+                          android:layout_width="wrap_content"
+                          android:layout_height="wrap_content"
+                          android:typeface="serif"
+                          android:layout_marginRight="7dip"
+                          android:layout_marginLeft="7dip"
+                        />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/textview_text"
+                          android:textAlignment="inherit"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                        />
+                <TextView android:layout_height="wrap_content"
+                          android:layout_width="200dip"
+                          android:textSize="24dip"
+                          android:text="@string/hebrew_text"
+                          android:textAlignment="inherit"
+                          android:layout_marginLeft="7dip"
+                          android:layout_marginRight="7dip"
+                          android:background="#444444"
+                        />
+            </TableRow>
+
+        </TableLayout>
+
+</FrameLayout>
diff --git a/tests/BiDiTests/res/layout/textview_alignment_rtl.xml b/tests/BiDiTests/res/layout/textview_alignment_rtl.xml
new file mode 100644
index 0000000..12a90d5
--- /dev/null
+++ b/tests/BiDiTests/res/layout/textview_alignment_rtl.xml
@@ -0,0 +1,578 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+             android:id="@+id/textview_alignment_rtl"
+             android:layout_width="fill_parent"
+             android:layout_height="fill_parent"
+             android:layoutDirection="rtl">
+
+    <TableLayout android:orientation="vertical"
+                 android:layout_width="wrap_content"
+                 android:layout_height="wrap_content">
+
+        <TableRow>
+            <TextView android:text="(unspecified)"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:typeface="serif"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/hebrew_text"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+        </TableRow>
+
+        <TableRow>
+            <TextView android:text="gravity (default)"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:typeface="serif"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textAlignment="gravity"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/hebrew_text"
+                      android:textAlignment="gravity"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+        </TableRow>
+
+        <TableRow>
+            <TextView android:text="gravity left"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:typeface="serif"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textAlignment="gravity"
+                      android:gravity="left"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/hebrew_text"
+                      android:textAlignment="gravity"
+                      android:gravity="left"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+        </TableRow>
+
+        <TableRow>
+            <TextView android:text="gravity right"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:typeface="serif"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textAlignment="gravity"
+                      android:gravity="right"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/hebrew_text"
+                      android:textAlignment="gravity"
+                      android:gravity="right"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+        </TableRow>
+
+        <TableRow>
+            <TextView android:text="gravity start"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:typeface="serif"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textAlignment="gravity"
+                      android:gravity="start"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/hebrew_text"
+                      android:textAlignment="gravity"
+                      android:gravity="start"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+        </TableRow>
+
+        <TableRow>
+            <TextView android:text="gravity end"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:typeface="serif"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textAlignment="gravity"
+                      android:gravity="end"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/hebrew_text"
+                      android:textAlignment="gravity"
+                      android:gravity="end"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+        </TableRow>
+
+        <TableRow>
+            <TextView android:text="gravity center"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:typeface="serif"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textAlignment="gravity"
+                      android:gravity="center"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/hebrew_text"
+                      android:textAlignment="gravity"
+                      android:gravity="center"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+        </TableRow>
+
+        <TableRow>
+            <TextView android:text="gravity center_horizontal"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:typeface="serif"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textAlignment="gravity"
+                      android:gravity="center_horizontal"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/hebrew_text"
+                      android:textAlignment="gravity"
+                      android:gravity="center_horizontal"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+        </TableRow>
+
+        <TableRow>
+            <TextView android:text="center"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:typeface="serif"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textAlignment="center"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/hebrew_text"
+                      android:textAlignment="center"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+        </TableRow>
+
+        <TableRow>
+            <TextView android:text="textStart"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:typeface="serif"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textAlignment="textStart"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/hebrew_text"
+                      android:textAlignment="textStart"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+        </TableRow>
+
+        <TableRow>
+            <TextView android:text="textEnd"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:typeface="serif"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textAlignment="textEnd"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/hebrew_text"
+                      android:textAlignment="textEnd"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+        </TableRow>
+
+        <TableRow>
+            <TextView android:text="viewStart"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:typeface="serif"
+                      android:layout_marginRight="7dip"
+                      android:layout_marginLeft="7dip"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textAlignment="viewStart"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/hebrew_text"
+                      android:textAlignment="viewStart"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+        </TableRow>
+
+        <TableRow>
+            <TextView android:text="viewEnd"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:typeface="serif"
+                      android:layout_marginRight="7dip"
+                      android:layout_marginLeft="7dip"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textAlignment="viewEnd"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/hebrew_text"
+                      android:textAlignment="viewEnd"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+        </TableRow>
+
+        <TableRow android:textAlignment="gravity"
+                  android:gravity="center_horizontal">
+
+            <TextView android:text="inherit gravity (default)"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:typeface="serif"
+                      android:layout_marginRight="7dip"
+                      android:layout_marginLeft="7dip"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textAlignment="inherit"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/hebrew_text"
+                      android:textAlignment="inherit"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+        </TableRow>
+
+        <TableRow android:textAlignment="center">
+
+            <TextView android:text="inherit gravity center"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:typeface="serif"
+                      android:layout_marginRight="7dip"
+                      android:layout_marginLeft="7dip"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textAlignment="inherit"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/hebrew_text"
+                      android:textAlignment="inherit"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+        </TableRow>
+
+        <TableRow android:textAlignment="textStart">
+
+            <TextView android:text="inherit textStart"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:typeface="serif"
+                      android:layout_marginRight="7dip"
+                      android:layout_marginLeft="7dip"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textAlignment="inherit"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/hebrew_text"
+                      android:textAlignment="inherit"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+        </TableRow>
+
+        <TableRow android:textAlignment="textEnd">
+
+            <TextView android:text="inherit textEnd"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:typeface="serif"
+                      android:layout_marginRight="7dip"
+                      android:layout_marginLeft="7dip"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textAlignment="inherit"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/hebrew_text"
+                      android:textAlignment="inherit"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+        </TableRow>
+
+        <TableRow android:textAlignment="viewStart">
+
+            <TextView android:text="inherit viewStart"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:typeface="serif"
+                      android:layout_marginRight="7dip"
+                      android:layout_marginLeft="7dip"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textAlignment="inherit"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/hebrew_text"
+                      android:textAlignment="inherit"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+        </TableRow>
+
+        <TableRow android:textAlignment="viewEnd">
+
+            <TextView android:text="inherit viewEnd"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:typeface="serif"
+                      android:layout_marginRight="7dip"
+                      android:layout_marginLeft="7dip"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/textview_text"
+                      android:textAlignment="inherit"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+            <TextView android:layout_height="wrap_content"
+                      android:layout_width="200dip"
+                      android:textSize="24dip"
+                      android:text="@string/hebrew_text"
+                      android:textAlignment="inherit"
+                      android:layout_marginLeft="7dip"
+                      android:layout_marginRight="7dip"
+                      android:background="#444444"
+                    />
+        </TableRow>
+
+    </TableLayout>
+
+</FrameLayout>
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
index c5a1235..209597e 100644
--- a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
@@ -104,6 +104,16 @@
         addItem(result, "Canvas", BiDiTestCanvas.class, R.id.canvas);
         addItem(result, "Canvas2", BiDiTestCanvas2.class, R.id.canvas2);
 
+        addItem(result, "TextView LTR", BiDiTestTextViewLtr.class, R.id.textview_ltr);
+        addItem(result, "TextView RTL", BiDiTestTextViewRtl.class, R.id.textview_rtl);
+        addItem(result, "TextView LOC", BiDiTestTextViewLocale.class, R.id.textview_locale);
+
+        addItem(result, "TextDirection LTR", BiDiTestTextViewDirectionLtr.class, R.id.textview_direction_ltr);
+        addItem(result, "TextDirection RTL", BiDiTestTextViewDirectionRtl.class, R.id.textview_direction_rtl);
+
+        addItem(result, "TextAlignment LTR", BiDiTestTextViewAlignmentLtr.class, R.id.textview_alignment_ltr);
+        addItem(result, "TextAlignment RTL", BiDiTestTextViewAlignmentRtl.class, R.id.textview_alignment_rtl);
+
         addItem(result, "Linear LTR", BiDiTestLinearLayoutLtr.class, R.id.linear_layout_ltr);
         addItem(result, "Linear RTL", BiDiTestLinearLayoutRtl.class, R.id.linear_layout_rtl);
         addItem(result, "Linear LOC", BiDiTestLinearLayoutLocale.class, R.id.linear_layout_locale);
@@ -134,15 +144,9 @@
 
         addItem(result, "Margin MIXED", BiDiTestViewGroupMarginMixed.class, R.id.view_group_margin_mixed);
 
-        addItem(result, "TextView LTR", BiDiTestTextViewLtr.class, R.id.textview_ltr);
-        addItem(result, "TextView RTL", BiDiTestTextViewRtl.class, R.id.textview_rtl);
-        addItem(result, "TextView LOC", BiDiTestTextViewLocale.class, R.id.textview_locale);
-
-        addItem(result, "TextDirection LTR", BiDiTestTextViewDirectionLtr.class, R.id.textview_direction_ltr);
-        addItem(result, "TextDirection RTL", BiDiTestTextViewDirectionRtl.class, R.id.textview_direction_rtl);
-
         addItem(result, "TextView Drawables LTR", BiDiTestTextViewDrawablesLtr.class, R.id.textview_drawables_ltr);
         addItem(result, "TextView Drawables RTL", BiDiTestTextViewDrawablesRtl.class, R.id.textview_drawables_rtl);
+
         addItem(result, "Gallery LTR", BiDiTestGalleryLtr.class, R.id.gallery_ltr);
         addItem(result, "Gallery RTL", BiDiTestGalleryRtl.class, R.id.gallery_rtl);
 
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewAlignmentLtr.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewAlignmentLtr.java
new file mode 100644
index 0000000..5ea5d81
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewAlignmentLtr.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class BiDiTestTextViewAlignmentLtr extends Fragment {
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.textview_alignment_ltr, container, false);
+    }
+}
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewAlignmentRtl.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewAlignmentRtl.java
new file mode 100644
index 0000000..fcc7a5d
--- /dev/null
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestTextViewAlignmentRtl.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.bidi;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class BiDiTestTextViewAlignmentRtl extends Fragment {
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        return inflater.inflate(R.layout.textview_alignment_rtl, container, false);
+    }
+}
diff --git a/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java b/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java
index a13c0c9..b7e80d4 100644
--- a/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java
+++ b/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java
@@ -52,7 +52,7 @@
      * Test that dumps all the data usage metrics for wifi to instrumentation out.
      */
     public void testWifiIdle() {
-        NetworkTemplate template = NetworkTemplate.buildTemplateWifi();
+        NetworkTemplate template = NetworkTemplate.buildTemplateWifiWildcard();
         fetchStats(template);
     }
 
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index f4c0841..3775f9f 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -42,6 +42,15 @@
         </activity>
 
         <activity
+                android:name="DatePickerActivity"
+                android:label="_DatePicker">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity
                 android:name="ClipRegionActivity"
                 android:label="_ClipRegion">
             <intent-filter>
@@ -657,5 +666,14 @@
             </intent-filter>
         </activity>
 
+        <activity
+                android:name="ViewPropertyAlphaActivity"
+                android:label="_ViewPropAlpha">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
     </application>
 </manifest>
diff --git a/tests/HwAccelerationTest/res/layout/date_picker.xml b/tests/HwAccelerationTest/res/layout/date_picker.xml
new file mode 100644
index 0000000..742a03b
--- /dev/null
+++ b/tests/HwAccelerationTest/res/layout/date_picker.xml
@@ -0,0 +1,83 @@
+<?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.
+*/
+-->
+
+<!-- Layout of date picker-->
+
+<!-- The width of this container is manually set a little bigger than the one of the children
+     contained in it. This helps to prevent rounding errors when toggling the "Show year" option -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_gravity="center_horizontal"
+              android:layout_width="270dip"
+              android:layout_height="wrap_content">
+
+    <CheckBox
+            android:id="@+id/yearToggle"
+            android:text="Provide a year"
+            android:paddingTop="5dip"
+            android:paddingBottom="5dip"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            android:layout_gravity="center_horizontal"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"/>
+    <!-- Warning: everything within the parent is removed and re-ordered depending
+         on the date format selected by the user. -->
+    <LinearLayout
+            android:id="@+id/parent"
+            android:orientation="horizontal"
+            android:layout_gravity="center_horizontal"
+            android:animateLayoutChanges="true"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content">
+
+        <!-- Month -->
+        <NumberPicker
+                android:id="@+id/month"
+                android:layout_width="80dip"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="1dip"
+                android:layout_marginRight="1dip"
+                android:focusable="true"
+                android:focusableInTouchMode="true"
+                />
+
+        <!-- Day -->
+        <NumberPicker
+                android:id="@+id/day"
+                android:layout_width="80dip"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="1dip"
+                android:layout_marginRight="1dip"
+                android:focusable="true"
+                android:focusableInTouchMode="true"
+                />
+
+        <!-- Year -->
+        <NumberPicker
+                android:id="@+id/year"
+                android:layout_width="95dip"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="1dip"
+                android:layout_marginRight="1dip"
+                android:focusable="true"
+                android:focusableInTouchMode="true"
+                />
+    </LinearLayout>
+</LinearLayout>
diff --git a/tests/HwAccelerationTest/res/layout/view_properties.xml b/tests/HwAccelerationTest/res/layout/view_properties.xml
new file mode 100644
index 0000000..d7ed8192
--- /dev/null
+++ b/tests/HwAccelerationTest/res/layout/view_properties.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="fill_parent"
+              android:layout_height="fill_parent"
+              android:id="@+id/container">
+    <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Invalidate"
+            android:id="@+id/invalidateButton"/>
+    <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Button"
+            android:id="@+id/button"/>
+    <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Some text"
+            android:id="@+id/textview"/>
+    <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/spantext"/>
+    <EditText
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Edit text"
+            android:id="@+id/edittext"/>
+    <EditText
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Selected text"
+            android:id="@+id/selectedtext"/>
+    <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Some text"
+            android:background="#00ff00"
+            android:id="@+id/textviewbackground"/>
+    <ImageView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/icon"
+            android:id="@+id/imageview"/>
+    <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:id="@+id/layout">
+        <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="Button"/>
+        <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="Some text"/>
+        <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="Some text"
+                android:background="#00ff00"/>
+    </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/DatePicker.java b/tests/HwAccelerationTest/src/com/android/test/hwui/DatePicker.java
new file mode 100644
index 0000000..db247e3
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/DatePicker.java
@@ -0,0 +1,474 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.annotation.Widget;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.format.DateFormat;
+import android.util.AttributeSet;
+import android.util.SparseArray;
+import android.view.ContextThemeWrapper;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.NumberPicker;
+
+import java.text.DateFormatSymbols;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
+/**
+ * A view for selecting a month / year / day based on a calendar like layout.
+ *
+ * <p>See the <a href="{@docRoot}resources/tutorials/views/hello-datepicker.html">Date Picker
+ * tutorial</a>.</p>
+ *
+ * For a dialog using this view, see {@link android.app.DatePickerDialog}.
+ */
+@Widget
+public class DatePicker extends FrameLayout {
+
+    private static final int DEFAULT_START_YEAR = 1900;
+    private static final int DEFAULT_END_YEAR = 2100;
+
+    /* UI Components */
+    private final CheckBox mYearToggle;
+    private final NumberPicker mDayPicker;
+    private final NumberPicker mMonthPicker;
+    private final NumberPicker mYearPicker;
+
+    /**
+     * How we notify users the date has changed.
+     */
+    private OnDateChangedListener mOnDateChangedListener;
+
+    private int mDay;
+    private int mMonth;
+    private int mYear;
+    private boolean mYearOptional = true;
+    private boolean mHasYear;
+
+    /**
+     * The callback used to indicate the user changes the date.
+     */
+    public interface OnDateChangedListener {
+
+        /**
+         * @param view The view associated with this listener.
+         * @param year The year that was set.
+         * @param monthOfYear The month that was set (0-11) for compatibility
+         *  with {@link java.util.Calendar}.
+         * @param dayOfMonth The day of the month that was set.
+         */
+        void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth);
+    }
+
+    public DatePicker(Context context) {
+        this(context, null);
+    }
+
+    public DatePicker(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    @SuppressWarnings("deprecation")
+    public DatePicker(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        ContextThemeWrapper themed = new ContextThemeWrapper(context,
+                com.android.internal.R.style.Theme_Holo_Light_Dialog_Alert);
+        LayoutInflater inflater = (LayoutInflater) themed.getSystemService(
+                        Context.LAYOUT_INFLATER_SERVICE);
+        inflater.inflate(R.layout.date_picker, this, true);
+
+        mDayPicker = (NumberPicker) findViewById(R.id.day);
+        mDayPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
+        mDayPicker.setOnLongPressUpdateInterval(100);
+        mDayPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
+            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
+                mDay = newVal;
+                notifyDateChanged();
+            }
+        });
+        mMonthPicker = (NumberPicker) findViewById(R.id.month);
+        mMonthPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
+        DateFormatSymbols dfs = new DateFormatSymbols();
+        String[] months = dfs.getShortMonths();
+
+        /*
+         * If the user is in a locale where the month names are numeric,
+         * use just the number instead of the "month" character for
+         * consistency with the other fields.
+         */
+        if (months[0].startsWith("1")) {
+            for (int i = 0; i < months.length; i++) {
+                months[i] = String.valueOf(i + 1);
+            }
+            mMonthPicker.setMinValue(1);
+            mMonthPicker.setMaxValue(12);
+        } else {
+            mMonthPicker.setMinValue(1);
+            mMonthPicker.setMaxValue(12);
+            mMonthPicker.setDisplayedValues(months);
+        }
+
+        mMonthPicker.setOnLongPressUpdateInterval(200);
+        mMonthPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
+            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
+
+                /* We display the month 1-12 but store it 0-11 so always
+                 * subtract by one to ensure our internal state is always 0-11
+                 */
+                mMonth = newVal - 1;
+                // Adjust max day of the month
+                adjustMaxDay();
+                notifyDateChanged();
+                updateDaySpinner();
+            }
+        });
+        mYearPicker = (NumberPicker) findViewById(R.id.year);
+        mYearPicker.setOnLongPressUpdateInterval(100);
+        mYearPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
+            public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
+                mYear = newVal;
+                // Adjust max day for leap years if needed
+                adjustMaxDay();
+                notifyDateChanged();
+                updateDaySpinner();
+            }
+        });
+
+        mYearToggle = (CheckBox) findViewById(R.id.yearToggle);
+        mYearToggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+            @Override
+            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+                mHasYear = isChecked;
+                adjustMaxDay();
+                notifyDateChanged();
+                updateSpinners();
+            }
+        });
+
+        // attributes
+        TypedArray a = context.obtainStyledAttributes(attrs,
+                com.android.internal.R.styleable.DatePicker);
+
+        int mStartYear =
+                a.getInt(com.android.internal.R.styleable.DatePicker_startYear, DEFAULT_START_YEAR);
+        int mEndYear =
+                a.getInt(com.android.internal.R.styleable.DatePicker_endYear, DEFAULT_END_YEAR);
+        mYearPicker.setMinValue(mStartYear);
+        mYearPicker.setMaxValue(mEndYear);
+
+        a.recycle();
+
+        // initialize to current date
+        Calendar cal = Calendar.getInstance();
+        init(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), null);
+
+        // re-order the number pickers to match the current date format
+        reorderPickers(months);
+
+        if (!isEnabled()) {
+            setEnabled(false);
+        }
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        super.setEnabled(enabled);
+        mDayPicker.setEnabled(enabled);
+        mMonthPicker.setEnabled(enabled);
+        mYearPicker.setEnabled(enabled);
+    }
+
+    private void reorderPickers(String[] months) {
+        java.text.DateFormat format;
+        String order;
+
+        /*
+         * If the user is in a locale where the medium date format is
+         * still numeric (Japanese and Czech, for example), respect
+         * the date format order setting.  Otherwise, use the order
+         * that the locale says is appropriate for a spelled-out date.
+         */
+
+        if (months[0].startsWith("1")) {
+            format = DateFormat.getDateFormat(getContext());
+        } else {
+            format = DateFormat.getMediumDateFormat(getContext());
+        }
+
+        if (format instanceof SimpleDateFormat) {
+            order = ((SimpleDateFormat) format).toPattern();
+        } else {
+            // Shouldn't happen, but just in case.
+            order = new String(DateFormat.getDateFormatOrder(getContext()));
+        }
+
+        /* Remove the 3 pickers from their parent and then add them back in the
+         * required order.
+         */
+        LinearLayout parent = (LinearLayout) findViewById(R.id.parent);
+        parent.removeAllViews();
+
+        boolean quoted = false;
+        boolean didDay = false, didMonth = false, didYear = false;
+
+        for (int i = 0; i < order.length(); i++) {
+            char c = order.charAt(i);
+
+            if (c == '\'') {
+                quoted = !quoted;
+            }
+
+            if (!quoted) {
+                if (c == DateFormat.DATE && !didDay) {
+                    parent.addView(mDayPicker);
+                    didDay = true;
+                } else if ((c == DateFormat.MONTH || c == 'L') && !didMonth) {
+                    parent.addView(mMonthPicker);
+                    didMonth = true;
+                } else if (c == DateFormat.YEAR && !didYear) {
+                    parent.addView (mYearPicker);
+                    didYear = true;
+                }
+            }
+        }
+
+        // Shouldn't happen, but just in case.
+        if (!didMonth) {
+            parent.addView(mMonthPicker);
+        }
+        if (!didDay) {
+            parent.addView(mDayPicker);
+        }
+        if (!didYear) {
+            parent.addView(mYearPicker);
+        }
+    }
+
+    public void updateDate(int year, int monthOfYear, int dayOfMonth) {
+        if (mYear != year || mMonth != monthOfYear || mDay != dayOfMonth) {
+            mYear = (mYearOptional && year == 0) ? getCurrentYear() : year;
+            mMonth = monthOfYear;
+            mDay = dayOfMonth;
+            updateSpinners();
+            reorderPickers(new DateFormatSymbols().getShortMonths());
+            notifyDateChanged();
+        }
+    }
+
+    private static int getCurrentYear() {
+        return Calendar.getInstance().get(Calendar.YEAR);
+    }
+
+    private static class SavedState extends BaseSavedState {
+
+        private final int mYear;
+        private final int mMonth;
+        private final int mDay;
+        private final boolean mHasYear;
+        private final boolean mYearOptional;
+
+        /**
+         * Constructor called from {@link DatePicker#onSaveInstanceState()}
+         */
+        private SavedState(Parcelable superState, int year, int month, int day, boolean hasYear,
+                boolean yearOptional) {
+            super(superState);
+            mYear = year;
+            mMonth = month;
+            mDay = day;
+            mHasYear = hasYear;
+            mYearOptional = yearOptional;
+        }
+
+        /**
+         * Constructor called from {@link #CREATOR}
+         */
+        private SavedState(Parcel in) {
+            super(in);
+            mYear = in.readInt();
+            mMonth = in.readInt();
+            mDay = in.readInt();
+            mHasYear = in.readInt() != 0;
+            mYearOptional = in.readInt() != 0;
+        }
+
+        public int getYear() {
+            return mYear;
+        }
+
+        public int getMonth() {
+            return mMonth;
+        }
+
+        public int getDay() {
+            return mDay;
+        }
+
+        public boolean hasYear() {
+            return mHasYear;
+        }
+
+        public boolean isYearOptional() {
+            return mYearOptional;
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            super.writeToParcel(dest, flags);
+            dest.writeInt(mYear);
+            dest.writeInt(mMonth);
+            dest.writeInt(mDay);
+            dest.writeInt(mHasYear ? 1 : 0);
+            dest.writeInt(mYearOptional ? 1 : 0);
+        }
+
+        @SuppressWarnings("unused")
+        public static final Parcelable.Creator<SavedState> CREATOR =
+                new Creator<SavedState>() {
+
+                    public SavedState createFromParcel(Parcel in) {
+                        return new SavedState(in);
+                    }
+
+                    public SavedState[] newArray(int size) {
+                        return new SavedState[size];
+                    }
+                };
+    }
+
+
+    /**
+     * Override so we are in complete control of save / restore for this widget.
+     */
+    @Override
+    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
+        dispatchThawSelfOnly(container);
+    }
+
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        Parcelable superState = super.onSaveInstanceState();
+
+        return new SavedState(superState, mYear, mMonth, mDay, mHasYear, mYearOptional);
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable state) {
+        SavedState ss = (SavedState) state;
+        super.onRestoreInstanceState(ss.getSuperState());
+        mYear = ss.getYear();
+        mMonth = ss.getMonth();
+        mDay = ss.getDay();
+        mHasYear = ss.hasYear();
+        mYearOptional = ss.isYearOptional();
+        updateSpinners();
+    }
+
+    /**
+     * Initialize the state.
+     * @param year The initial year.
+     * @param monthOfYear The initial month.
+     * @param dayOfMonth The initial day of the month.
+     * @param onDateChangedListener How user is notified date is changed by user, can be null.
+     */
+    public void init(int year, int monthOfYear, int dayOfMonth,
+            OnDateChangedListener onDateChangedListener) {
+        init(year, monthOfYear, dayOfMonth, false, onDateChangedListener);
+    }
+
+    /**
+     * Initialize the state.
+     * @param year The initial year or 0 if no year has been specified
+     * @param monthOfYear The initial month.
+     * @param dayOfMonth The initial day of the month.
+     * @param yearOptional True if the user can toggle the year
+     * @param onDateChangedListener How user is notified date is changed by user, can be null.
+     */
+    public void init(int year, int monthOfYear, int dayOfMonth, boolean yearOptional,
+            OnDateChangedListener onDateChangedListener) {
+        mYear = (yearOptional && year == 0) ? getCurrentYear() : year;
+        mMonth = monthOfYear;
+        mDay = dayOfMonth;
+        mYearOptional = yearOptional;
+        mHasYear = !yearOptional || (year != 0);
+        mOnDateChangedListener = onDateChangedListener;
+        updateSpinners();
+    }
+
+    private void updateSpinners() {
+        updateDaySpinner();
+        mYearToggle.setChecked(mHasYear);
+        mYearToggle.setVisibility(mYearOptional ? View.VISIBLE : View.GONE);
+        mYearPicker.setValue(mYear);
+        mYearPicker.setVisibility(mHasYear ? View.VISIBLE : View.GONE);
+
+        /* The month display uses 1-12 but our internal state stores it
+         * 0-11 so add one when setting the display.
+         */
+        mMonthPicker.setValue(mMonth + 1);
+    }
+
+    private void updateDaySpinner() {
+        Calendar cal = Calendar.getInstance();
+        // if year was not set, use 2000 as it was a leap year
+        cal.set(mHasYear ? mYear : 2000, mMonth, 1);
+        int max = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
+        mDayPicker.setMinValue(1);
+        mDayPicker.setMaxValue(max);
+        mDayPicker.setValue(mDay);
+    }
+
+    public int getYear() {
+        return (mYearOptional && !mHasYear) ? 0 : mYear;
+    }
+
+    public int getMonth() {
+        return mMonth;
+    }
+
+    public int getDayOfMonth() {
+        return mDay;
+    }
+
+    private void adjustMaxDay(){
+        Calendar cal = Calendar.getInstance();
+        // if year was not set, use 2000 as it was a leap year
+        cal.set(Calendar.YEAR, mHasYear ? mYear : 2000);
+        cal.set(Calendar.MONTH, mMonth);
+        int max = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
+        if (mDay > max) {
+            mDay = max;
+        }
+    }
+
+    private void notifyDateChanged() {
+        if (mOnDateChangedListener != null) {
+            int year = (mYearOptional && !mHasYear) ? 0 : mYear;
+            mOnDateChangedListener.onDateChanged(DatePicker.this, year, mMonth, mDay);
+        }
+    }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/DatePickerActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/DatePickerActivity.java
new file mode 100644
index 0000000..5482ee2
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/DatePickerActivity.java
@@ -0,0 +1,38 @@
+/*
+ * 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.test.hwui;
+
+import android.app.Activity;
+import android.graphics.drawable.ColorDrawable;
+import android.os.Bundle;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class DatePickerActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        DatePicker picker = new DatePicker(this);
+        picker.init(2012, 3, 3, true, new DatePicker.OnDateChangedListener() {
+            @Override
+            public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
+            }
+        });
+        setContentView(picker);
+        getWindow().setBackgroundDrawable(new ColorDrawable(0xffffffff));
+    }
+}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewPropertyAlphaActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewPropertyAlphaActivity.java
new file mode 100644
index 0000000..738801d
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewPropertyAlphaActivity.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.os.Bundle;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
+import android.text.style.BackgroundColorSpan;
+import android.text.style.ForegroundColorSpan;
+import android.text.style.ImageSpan;
+import android.text.style.SuggestionSpan;
+import android.text.style.UnderlineSpan;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+public class ViewPropertyAlphaActivity extends Activity {
+    
+    MyView myViewAlphaDefault, myViewAlphaHandled;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.view_properties);
+
+        getWindow().getDecorView().postDelayed(new Runnable() {
+            @Override
+            public void run() {
+                startAnim(R.id.button);
+                startAnim(R.id.textview);
+                startAnim(R.id.spantext);
+                startAnim(R.id.edittext);
+                startAnim(R.id.selectedtext);
+                startAnim(R.id.textviewbackground);
+                startAnim(R.id.layout);
+                startAnim(R.id.imageview);
+                startAnim(myViewAlphaDefault);
+                startAnim(myViewAlphaHandled);
+                EditText selectedText = (EditText) findViewById(R.id.selectedtext);
+                selectedText.setSelection(3, 8);
+            }
+        }, 2000);
+        
+        Button invalidator = (Button) findViewById(R.id.invalidateButton);
+        invalidator.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                findViewById(R.id.textview).invalidate();
+                findViewById(R.id.spantext).invalidate();
+            }
+        });
+
+        TextView textView = (TextView) findViewById(R.id.spantext);
+        if (textView != null) {
+            SpannableStringBuilder text =
+                    new SpannableStringBuilder("Now this is a short text message with spans");
+
+            text.setSpan(new BackgroundColorSpan(Color.RED), 0, 3,
+                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            text.setSpan(new ForegroundColorSpan(Color.BLUE), 4, 9,
+                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            text.setSpan(new SuggestionSpan(this, new String[]{"longer"}, 3), 11, 16,
+                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            text.setSpan(new UnderlineSpan(), 17, 20,
+                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            text.setSpan(new ImageSpan(this, R.drawable.icon), 21, 22,
+                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+            textView.setText(text);
+        }
+        
+        LinearLayout container = (LinearLayout) findViewById(R.id.container);
+        myViewAlphaDefault = new MyView(this, false);
+        myViewAlphaDefault.setLayoutParams(new LinearLayout.LayoutParams(75, 75));
+        container.addView(myViewAlphaDefault);
+        myViewAlphaHandled = new MyView(this, true);
+        myViewAlphaHandled.setLayoutParams(new LinearLayout.LayoutParams(75, 75));
+        container.addView(myViewAlphaHandled);
+    }
+
+    private void startAnim(View target) {
+        ObjectAnimator anim = ObjectAnimator.ofFloat(target, View.ALPHA, 0);
+        anim.setRepeatCount(ValueAnimator.INFINITE);
+        anim.setRepeatMode(ValueAnimator.REVERSE);
+        anim.setDuration(1000);
+        anim.start();
+    }
+    private void startAnim(int id) {
+        startAnim(findViewById(id));
+    }
+    
+    private static class MyView extends View {
+        private int mMyAlpha = 255;
+        private boolean mHandleAlpha;
+        private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+        
+        private MyView(Context context, boolean handleAlpha) {
+            super(context);
+            mHandleAlpha = handleAlpha;
+            mPaint.setColor(Color.RED);
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            if (mHandleAlpha) {
+                mPaint.setAlpha(mMyAlpha);
+            }
+            canvas.drawCircle(30, 30, 30, mPaint);
+        }
+
+        @Override
+        protected boolean onSetAlpha(int alpha) {
+            if (mHandleAlpha) {
+                mMyAlpha = alpha;
+                return true;
+            }
+            return super.onSetAlpha(alpha);
+        }
+    }
+
+}
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
index 87baf76..7c03313 100644
--- a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
@@ -23,7 +23,6 @@
 import android.webkit.WebSettingsClassic;
 import android.webkit.WebView;
 import android.webkit.WebViewClassic;
-import android.widget.Toast;
 
 import java.util.ArrayList;
 
@@ -72,10 +71,7 @@
             mContext = c;
         }
 
-        /** Show a toast from the web page */
         public void animationComplete() {
-            Toast.makeText(mContext, "Animation complete!", Toast.LENGTH_SHORT).show();
-            //Log.d(LOGTAG, "anim complete");
             mAnimationTime = System.currentTimeMillis();
         }
     }
diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
index c3ac22c..58f65be 100644
--- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
@@ -412,7 +412,7 @@
     @SmallTest
     public void testSET_ORIENTATION() {
         try {
-            mWm.updateRotation(true);
+            mWm.updateRotation(true, false);
             mWm.getSwitchState(0);
             fail("IWindowManager.updateRotation did not throw SecurityException as"
                     + " expected");
diff --git a/tools/aapt/Images.cpp b/tools/aapt/Images.cpp
index 2b9b056..9de685a 100644
--- a/tools/aapt/Images.cpp
+++ b/tools/aapt/Images.cpp
@@ -57,6 +57,13 @@
     bool is9Patch;
     Res_png_9patch info9Patch;
 
+    // Layout padding, if relevant
+    bool haveLayoutBounds;
+    int32_t layoutBoundsLeft;
+    int32_t layoutBoundsTop;
+    int32_t layoutBoundsRight;
+    int32_t layoutBoundsBottom;
+
     png_uint_32 allocHeight;
     png_bytepp allocRows;
 };
@@ -129,33 +136,62 @@
        &interlace_type, &compression_type, NULL);
 }
 
-static bool is_tick(png_bytep p, bool transparent, const char** outError)
+#define COLOR_TRANSPARENT 0
+#define COLOR_WHITE 0xFFFFFFFF
+#define COLOR_TICK  0xFF000000
+#define COLOR_LAYOUT_BOUNDS_TICK 0xFF0000FF
+
+enum {
+    TICK_TYPE_NONE,
+    TICK_TYPE_TICK,
+    TICK_TYPE_LAYOUT_BOUNDS,
+    TICK_TYPE_BOTH
+};
+
+static int tick_type(png_bytep p, bool transparent, const char** outError)
 {
+    png_uint_32 color = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
+
     if (transparent) {
         if (p[3] == 0) {
-            return false;
+            return TICK_TYPE_NONE;
         }
+        if (color == COLOR_LAYOUT_BOUNDS_TICK) {
+            return TICK_TYPE_LAYOUT_BOUNDS;
+        }
+        if (color == COLOR_TICK) {
+            return TICK_TYPE_TICK;
+        }
+
+        // Error cases
         if (p[3] != 0xff) {
             *outError = "Frame pixels must be either solid or transparent (not intermediate alphas)";
-            return false;
+            return TICK_TYPE_NONE;
         }
         if (p[0] != 0 || p[1] != 0 || p[2] != 0) {
-            *outError = "Ticks in transparent frame must be black";
+            *outError = "Ticks in transparent frame must be black or red";
         }
-        return true;
+        return TICK_TYPE_TICK;
     }
 
     if (p[3] != 0xFF) {
         *outError = "White frame must be a solid color (no alpha)";
     }
-    if (p[0] == 0xFF && p[1] == 0xFF && p[2] == 0xFF) {
-        return false;
+    if (color == COLOR_WHITE) {
+        return TICK_TYPE_NONE;
     }
+    if (color == COLOR_TICK) {
+        return TICK_TYPE_TICK;
+    }
+    if (color == COLOR_LAYOUT_BOUNDS_TICK) {
+        return TICK_TYPE_LAYOUT_BOUNDS;
+    }
+
     if (p[0] != 0 || p[1] != 0 || p[2] != 0) {
-        *outError = "Ticks in white frame must be black";
-        return false;
+        *outError = "Ticks in white frame must be black or red";
+        return TICK_TYPE_NONE;
     }
-    return true;
+    return TICK_TYPE_TICK;
 }
 
 enum {
@@ -175,7 +211,7 @@
     bool found = false;
 
     for (i=1; i<width-1; i++) {
-        if (is_tick(row+i*4, transparent, outError)) {
+        if (TICK_TYPE_TICK == tick_type(row+i*4, transparent, outError)) {
             if (state == TICK_START ||
                 (state == TICK_OUTSIDE_1 && multipleAllowed)) {
                 *outLeft = i-1;
@@ -224,7 +260,7 @@
     bool found = false;
 
     for (i=1; i<height-1; i++) {
-        if (is_tick(rows[i]+offset, transparent, outError)) {
+        if (TICK_TYPE_TICK == tick_type(rows[i]+offset, transparent, outError)) {
             if (state == TICK_START ||
                 (state == TICK_OUTSIDE_1 && multipleAllowed)) {
                 *outTop = i-1;
@@ -262,6 +298,83 @@
     return NO_ERROR;
 }
 
+static status_t get_horizontal_layout_bounds_ticks(
+        png_bytep row, int width, bool transparent, bool required,
+        int32_t* outLeft, int32_t* outRight, const char** outError)
+{
+    int i;
+    *outLeft = *outRight = 0;
+
+    // Look for left tick
+    if (TICK_TYPE_LAYOUT_BOUNDS == tick_type(row + 4, transparent, outError)) {
+        // Starting with a layout padding tick
+        i = 1;
+        while (i < width - 1) {
+            (*outLeft)++;
+            i++;
+            int tick = tick_type(row + i * 4, transparent, outError);
+            if (tick != TICK_TYPE_LAYOUT_BOUNDS) {
+                break;
+            }
+        }
+    }
+
+    // Look for right tick
+    if (TICK_TYPE_LAYOUT_BOUNDS == tick_type(row + (width - 2) * 4, transparent, outError)) {
+        // Ending with a layout padding tick
+        i = width - 2;
+        while (i > 1) {
+            (*outRight)++;
+            i--;
+            int tick = tick_type(row+i*4, transparent, outError);
+            if (tick != TICK_TYPE_LAYOUT_BOUNDS) {
+                break;
+            }
+        }
+    }
+
+    return NO_ERROR;
+}
+
+static status_t get_vertical_layout_bounds_ticks(
+        png_bytepp rows, int offset, int height, bool transparent, bool required,
+        int32_t* outTop, int32_t* outBottom, const char** outError)
+{
+    int i;
+    *outTop = *outBottom = 0;
+
+    // Look for top tick
+    if (TICK_TYPE_LAYOUT_BOUNDS == tick_type(rows[1] + offset, transparent, outError)) {
+        // Starting with a layout padding tick
+        i = 1;
+        while (i < height - 1) {
+            (*outTop)++;
+            i++;
+            int tick = tick_type(rows[i] + offset, transparent, outError);
+            if (tick != TICK_TYPE_LAYOUT_BOUNDS) {
+                break;
+            }
+        }
+    }
+
+    // Look for bottom tick
+    if (TICK_TYPE_LAYOUT_BOUNDS == tick_type(rows[height - 2] + offset, transparent, outError)) {
+        // Ending with a layout padding tick
+        i = height - 2;
+        while (i > 1) {
+            (*outBottom)++;
+            i--;
+            int tick = tick_type(rows[i] + offset, transparent, outError);
+            if (tick != TICK_TYPE_LAYOUT_BOUNDS) {
+                break;
+            }
+        }
+    }
+
+    return NO_ERROR;
+}
+
+
 static uint32_t get_color(
     png_bytepp rows, int left, int top, int right, int bottom)
 {
@@ -353,6 +466,9 @@
     image->info9Patch.paddingLeft = image->info9Patch.paddingRight =
         image->info9Patch.paddingTop = image->info9Patch.paddingBottom = -1;
 
+    image->layoutBoundsLeft = image->layoutBoundsRight =
+        image->layoutBoundsTop = image->layoutBoundsBottom = 0;
+
     png_bytep p = image->rows[0];
     bool transparent = p[3] == 0;
     bool hasColor = false;
@@ -408,6 +524,25 @@
         goto getout;
     }
 
+    // Find left and right of layout padding...
+    get_horizontal_layout_bounds_ticks(image->rows[H-1], W, transparent, false,
+                                        &image->layoutBoundsLeft,
+                                        &image->layoutBoundsRight, &errorMsg);
+
+    get_vertical_layout_bounds_ticks(image->rows, (W-1)*4, H, transparent, false,
+                                        &image->layoutBoundsTop,
+                                        &image->layoutBoundsBottom, &errorMsg);
+
+    image->haveLayoutBounds = image->layoutBoundsLeft != 0
+                               || image->layoutBoundsRight != 0
+                               || image->layoutBoundsTop != 0
+                               || image->layoutBoundsBottom != 0;
+
+    if (image->haveLayoutBounds) {
+        NOISY(printf("layoutBounds=%d %d %d %d\n", image->layoutBoundsLeft, image->layoutBoundsTop,
+                image->layoutBoundsRight, image->layoutBoundsBottom));
+    }
+
     // Copy patch data into image
     image->info9Patch.numXDivs = numXDivs;
     image->info9Patch.numYDivs = numYDivs;
@@ -845,8 +980,9 @@
     int bit_depth, interlace_type, compression_type;
     int i;
 
-    png_unknown_chunk unknowns[1];
+    png_unknown_chunk unknowns[2];
     unknowns[0].data = NULL;
+    unknowns[1].data = NULL;
 
     png_bytepp outRows = (png_bytepp) malloc((int) imageInfo.height * png_sizeof(png_bytep));
     if (outRows == (png_bytepp) 0) {
@@ -916,23 +1052,42 @@
     }
 
     if (imageInfo.is9Patch) {
+        int chunk_count = 1 + (imageInfo.haveLayoutBounds ? 1 : 0);
+        int p_index = imageInfo.haveLayoutBounds ? 1 : 0;
+        int b_index = 0;
+        png_byte *chunk_names = imageInfo.haveLayoutBounds
+                ? (png_byte*)"npLb\0npTc\0"
+                : (png_byte*)"npTc";
         NOISY(printf("Adding 9-patch info...\n"));
-        strcpy((char*)unknowns[0].name, "npTc");
-        unknowns[0].data = (png_byte*)imageInfo.info9Patch.serialize();
-        unknowns[0].size = imageInfo.info9Patch.serializedSize();
+        strcpy((char*)unknowns[p_index].name, "npTc");
+        unknowns[p_index].data = (png_byte*)imageInfo.info9Patch.serialize();
+        unknowns[p_index].size = imageInfo.info9Patch.serializedSize();
         // TODO: remove the check below when everything works
-        checkNinePatchSerialization(&imageInfo.info9Patch, unknowns[0].data);
+        checkNinePatchSerialization(&imageInfo.info9Patch, unknowns[p_index].data);
+
+        if (imageInfo.haveLayoutBounds) {
+            int chunk_size = sizeof(png_uint_32) * 4;
+            strcpy((char*)unknowns[b_index].name, "npLb");
+            unknowns[b_index].data = (png_byte*) calloc(chunk_size, 1);
+            memcpy(unknowns[b_index].data, &imageInfo.layoutBoundsLeft, chunk_size);
+            unknowns[b_index].size = chunk_size;
+        }
+
         png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_ALWAYS,
-                                    (png_byte*)"npTc", 1);
-        png_set_unknown_chunks(write_ptr, write_info, unknowns, 1);
+                                    chunk_names, chunk_count);
+        png_set_unknown_chunks(write_ptr, write_info, unknowns, chunk_count);
         // XXX I can't get this to work without forcibly changing
         // the location to what I want...  which apparently is supposed
         // to be a private API, but everything else I have tried results
         // in the location being set to what I -last- wrote so I never
         // get written. :p
         png_set_unknown_chunk_location(write_ptr, write_info, 0, PNG_HAVE_PLTE);
+        if (imageInfo.haveLayoutBounds) {
+            png_set_unknown_chunk_location(write_ptr, write_info, 1, PNG_HAVE_PLTE);
+        }
     }
 
+
     png_write_info(write_ptr, write_info);
 
     png_bytepp rows;
@@ -954,6 +1109,7 @@
     }
     free(outRows);
     free(unknowns[0].data);
+    free(unknowns[1].data);
 
     png_get_IHDR(write_ptr, write_info, &width, &height,
        &bit_depth, &color_type, &interlace_type,
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
index eadec02..b76b8cf 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -524,7 +524,8 @@
         int nativeInt = sManager.addNewDelegate(delegate);
 
         // and create/return a new Bitmap with it
-        return new Bitmap(nativeInt, null /* buffer */, isMutable, null /*ninePatchChunk*/, density);
+        return new Bitmap(nativeInt, null /* buffer */, isMutable, null /*ninePatchChunk*/, 
+                density);
     }
 
     /**
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
index 8b1d41a..0755670 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
@@ -88,7 +88,7 @@
     // ---- unused implementation of IWindowManager ----
 
     @Override
-    public boolean canStatusBarHide() throws RemoteException {
+    public boolean hasSystemNavBar() throws RemoteException {
         // TODO Auto-generated method stub
         return false;
     }
@@ -468,9 +468,8 @@
     }
 
     @Override
-    public void updateRotation(boolean arg0) throws RemoteException {
+    public void updateRotation(boolean arg0, boolean arg1) throws RemoteException {
         // TODO Auto-generated method stub
-
     }
 
     @Override
diff --git a/voip/java/com/android/server/sip/SipService.java b/voip/java/com/android/server/sip/SipService.java
index 97afc81..a477fd1 100644
--- a/voip/java/com/android/server/sip/SipService.java
+++ b/voip/java/com/android/server/sip/SipService.java
@@ -453,9 +453,8 @@
         public SipSessionGroupExt(SipProfile localProfile,
                 PendingIntent incomingCallPendingIntent,
                 ISipSessionListener listener) throws SipException {
-            String password = localProfile.getPassword();
-            SipProfile p = duplicate(localProfile);
-            mSipGroup = createSipSessionGroup(mLocalIp, p, password);
+            mSipGroup = new SipSessionGroup(duplicate(localProfile),
+                    localProfile.getPassword(), mTimer, mMyWakeLock);
             mIncomingCallPendingIntent = incomingCallPendingIntent;
             mAutoRegistration.setListener(listener);
         }
@@ -478,27 +477,6 @@
             mSipGroup.setWakeupTimer(timer);
         }
 
-        // network connectivity is tricky because network can be disconnected
-        // at any instant so need to deal with exceptions carefully even when
-        // you think you are connected
-        private SipSessionGroup createSipSessionGroup(String localIp,
-                SipProfile localProfile, String password) throws SipException {
-            try {
-                return new SipSessionGroup(localIp, localProfile, password,
-                        mTimer, mMyWakeLock);
-            } catch (IOException e) {
-                // network disconnected
-                Log.w(TAG, "createSipSessionGroup(): network disconnected?");
-                if (localIp != null) {
-                    return createSipSessionGroup(null, localProfile, password);
-                } else {
-                    // recursive
-                    Log.wtf(TAG, "impossible! recursive!");
-                    throw new RuntimeException("createSipSessionGroup");
-                }
-            }
-        }
-
         private SipProfile duplicate(SipProfile p) {
             try {
                 return new SipProfile.Builder(p).setPassword("*").build();
@@ -530,7 +508,7 @@
                 throws SipException {
             mSipGroup.onConnectivityChanged();
             if (connected) {
-                resetGroup(mLocalIp);
+                mSipGroup.reset();
                 if (mOpenedToReceiveCalls) openToReceiveCalls();
             } else {
                 // close mSipGroup but remember mOpenedToReceiveCalls
@@ -541,22 +519,6 @@
             }
         }
 
-        private void resetGroup(String localIp) throws SipException {
-            try {
-                mSipGroup.reset(localIp);
-            } catch (IOException e) {
-                // network disconnected
-                Log.w(TAG, "resetGroup(): network disconnected?");
-                if (localIp != null) {
-                    resetGroup(null); // reset w/o local IP
-                } else {
-                    // recursive
-                    Log.wtf(TAG, "impossible!");
-                    throw new RuntimeException("resetGroup");
-                }
-            }
-        }
-
         public void close() {
             mOpenedToReceiveCalls = false;
             mSipGroup.close();
diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java
index 877a0a4..6acd456 100644
--- a/voip/java/com/android/server/sip/SipSessionGroup.java
+++ b/voip/java/com/android/server/sip/SipSessionGroup.java
@@ -40,6 +40,7 @@
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.net.DatagramSocket;
+import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.text.ParseException;
 import java.util.Collection;
@@ -47,13 +48,11 @@
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
-import java.util.TooManyListenersException;
 
 import javax.sip.ClientTransaction;
 import javax.sip.Dialog;
 import javax.sip.DialogTerminatedEvent;
 import javax.sip.IOExceptionEvent;
-import javax.sip.InvalidArgumentException;
 import javax.sip.ListeningPoint;
 import javax.sip.ObjectInUseException;
 import javax.sip.RequestEvent;
@@ -132,18 +131,17 @@
     private int mExternalPort;
 
     /**
-     * @param myself the local profile with password crossed out
+     * @param profile the local profile with password crossed out
      * @param password the password of the profile
      * @throws IOException if cannot assign requested address
      */
-    public SipSessionGroup(String localIp, SipProfile myself, String password,
-            SipWakeupTimer timer, SipWakeLock wakeLock) throws SipException,
-            IOException {
-        mLocalProfile = myself;
+    public SipSessionGroup(SipProfile profile, String password,
+            SipWakeupTimer timer, SipWakeLock wakeLock) throws SipException {
+        mLocalProfile = profile;
         mPassword = password;
         mWakeupTimer = timer;
         mWakeLock = wakeLock;
-        reset(localIp);
+        reset();
     }
 
     // TODO: remove this method once SipWakeupTimer can better handle variety
@@ -152,43 +150,64 @@
         mWakeupTimer = timer;
     }
 
-    synchronized void reset(String localIp) throws SipException, IOException {
-        mLocalIp = localIp;
-        if (localIp == null) return;
-
-        SipProfile myself = mLocalProfile;
-        SipFactory sipFactory = SipFactory.getInstance();
+    synchronized void reset() throws SipException {
         Properties properties = new Properties();
+
+        String protocol = mLocalProfile.getProtocol();
+        int port = mLocalProfile.getPort();
+        String server = mLocalProfile.getProxyAddress();
+
+        if (!TextUtils.isEmpty(server)) {
+            properties.setProperty("javax.sip.OUTBOUND_PROXY",
+                    server + ':' + port + '/' + protocol);
+        } else {
+            server = mLocalProfile.getSipDomain();
+        }
+        if (server.startsWith("[") && server.endsWith("]")) {
+            server = server.substring(1, server.length() - 1);
+        }
+
+        String local = null;
+        try {
+            for (InetAddress remote : InetAddress.getAllByName(server)) {
+                DatagramSocket socket = new DatagramSocket();
+                socket.connect(remote, port);
+                if (socket.isConnected()) {
+                    local = socket.getLocalAddress().getHostAddress();
+                    port = socket.getLocalPort();
+                    socket.close();
+                    break;
+                }
+                socket.close();
+            }
+        } catch (Exception e) {
+            // ignore.
+        }
+        if (local == null) {
+            // We are unable to reach the server. Just bail out.
+            return;
+        }
+
+        close();
+        mLocalIp = local;
+
         properties.setProperty("javax.sip.STACK_NAME", getStackName());
         properties.setProperty(
                 "gov.nist.javax.sip.THREAD_POOL_SIZE", THREAD_POOL_SIZE);
-        String outboundProxy = myself.getProxyAddress();
-        if (!TextUtils.isEmpty(outboundProxy)) {
-            Log.v(TAG, "outboundProxy is " + outboundProxy);
-            properties.setProperty("javax.sip.OUTBOUND_PROXY", outboundProxy
-                    + ":" + myself.getPort() + "/" + myself.getProtocol());
-        }
-        SipStack stack = mSipStack = sipFactory.createSipStack(properties);
-
+        mSipStack = SipFactory.getInstance().createSipStack(properties);
         try {
-            SipProvider provider = stack.createSipProvider(
-                    stack.createListeningPoint(localIp, allocateLocalPort(),
-                            myself.getProtocol()));
+            SipProvider provider = mSipStack.createSipProvider(
+                    mSipStack.createListeningPoint(local, port, protocol));
             provider.addSipListener(this);
-            mSipHelper = new SipHelper(stack, provider);
-        } catch (InvalidArgumentException e) {
-            throw new IOException(e.getMessage());
-        } catch (TooManyListenersException e) {
-            // must never happen
-            throw new SipException("SipSessionGroup constructor", e);
+            mSipHelper = new SipHelper(mSipStack, provider);
+        } catch (SipException e) {
+            throw e;
+        } catch (Exception e) {
+            throw new SipException("failed to initialize SIP stack", e);
         }
-        Log.d(TAG, " start stack for " + myself.getUriString());
-        stack.start();
 
-        mCallReceiverSession = null;
-        mSessionMap.clear();
-
-        resetExternalAddress();
+        Log.d(TAG, " start stack for " + mLocalProfile.getUriString());
+        mSipStack.start();
     }
 
     synchronized void onConnectivityChanged() {
@@ -234,6 +253,7 @@
             mSipStack = null;
             mSipHelper = null;
         }
+        resetExternalAddress();
     }
 
     public synchronized boolean isClosed() {
@@ -257,17 +277,6 @@
         return (isClosed() ? null : new SipSessionImpl(listener));
     }
 
-    private static int allocateLocalPort() throws SipException {
-        try {
-            DatagramSocket s = new DatagramSocket();
-            int localPort = s.getLocalPort();
-            s.close();
-            return localPort;
-        } catch (IOException e) {
-            throw new SipException("allocateLocalPort()", e);
-        }
-    }
-
     synchronized boolean containsSession(String callId) {
         return mSessionMap.containsKey(callId);
     }
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
index 2fc6c20..c7f6bf0 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java
@@ -380,6 +380,7 @@
             mHandler = new P2pHandler(looper);
             mChannelListener = l;
         }
+        private final static int INVALID_LISTENER_KEY = 0;
         private ChannelListener mChannelListener;
         private HashMap<Integer, Object> mListenerMap = new HashMap<Integer, Object>();
         private Object mListenerMapLock = new Object();
@@ -450,16 +451,19 @@
         }
 
         int putListener(Object listener) {
-            if (listener == null) return 0;
+            if (listener == null) return INVALID_LISTENER_KEY;
             int key;
             synchronized (mListenerMapLock) {
-                key = mListenerKey++;
+                do {
+                    key = mListenerKey++;
+                } while (key == INVALID_LISTENER_KEY);
                 mListenerMap.put(key, listener);
             }
             return key;
         }
 
         Object getListener(int key) {
+            if (key == INVALID_LISTENER_KEY) return null;
             synchronized (mListenerMapLock) {
                 return mListenerMap.remove(key);
             }