Merge "Avoid waking EGL in getInitCount"
diff --git a/Android.mk b/Android.mk
index d27dbab..9c51fc62 100644
--- a/Android.mk
+++ b/Android.mk
@@ -118,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/INetworkStatsSession.aidl \
 	core/java/android/net/nsd/INsdManager.aidl \
 	core/java/android/nfc/INdefPushCallback.aidl \
 	core/java/android/nfc/INfcAdapter.aidl \
diff --git a/api/current.txt b/api/current.txt
index f00911b..180ac91 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -80,7 +80,7 @@
     field public static final java.lang.String READ_EXTERNAL_STORAGE = "android.permission.READ_EXTERNAL_STORAGE";
     field public static final java.lang.String READ_FRAME_BUFFER = "android.permission.READ_FRAME_BUFFER";
     field public static final java.lang.String READ_HISTORY_BOOKMARKS = "com.android.browser.permission.READ_HISTORY_BOOKMARKS";
-    field public static final java.lang.String READ_INPUT_STATE = "android.permission.READ_INPUT_STATE";
+    field public static final deprecated java.lang.String READ_INPUT_STATE = "android.permission.READ_INPUT_STATE";
     field public static final java.lang.String READ_LOGS = "android.permission.READ_LOGS";
     field public static final java.lang.String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE";
     field public static final java.lang.String READ_PROFILE = "android.permission.READ_PROFILE";
@@ -934,6 +934,7 @@
     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 supportsSentenceSpellCheck = 16843698; // 0x10103b2
     field public static final int supportsUploading = 16843419; // 0x101029b
     field public static final int switchMinWidth = 16843632; // 0x1010370
     field public static final int switchPadding = 16843633; // 0x1010371
@@ -16687,6 +16688,7 @@
     field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/phone_v2";
     field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/phone_v2";
     field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String NORMALIZED_NUMBER = "data4";
     field public static final java.lang.String NUMBER = "data1";
     field public static final int TYPE_ASSISTANT = 19; // 0x13
     field public static final int TYPE_CALLBACK = 8; // 0x8
@@ -17047,6 +17049,7 @@
 
   protected static abstract interface ContactsContract.PhoneLookupColumns {
     field public static final java.lang.String LABEL = "label";
+    field public static final java.lang.String NORMALIZED_NUMBER = "normalized_number";
     field public static final java.lang.String NUMBER = "number";
     field public static final java.lang.String TYPE = "type";
   }
@@ -25280,11 +25283,13 @@
     method public android.view.textservice.SpellCheckerInfo getSpellChecker();
     method public void getSuggestions(android.view.textservice.TextInfo, int);
     method public void getSuggestions(android.view.textservice.TextInfo[], int, boolean);
+    method public boolean isSentenceSpellCheckSupported();
     method public boolean isSessionDisconnected();
     field public static final java.lang.String SERVICE_META_DATA = "android.view.textservice.scs";
   }
 
   public static abstract interface SpellCheckerSession.SpellCheckerSessionListener {
+    method public abstract void onGetSentenceSuggestions(android.view.textservice.SentenceSuggestionsInfo[]);
     method public abstract void onGetSuggestions(android.view.textservice.SuggestionsInfo[]);
   }
 
@@ -25768,7 +25773,8 @@
     method public deprecated void emulateShiftHeld();
     method public static deprecated void enablePlatformNotifications();
     method public static java.lang.String findAddress(java.lang.String);
-    method public int findAll(java.lang.String);
+    method public deprecated int findAll(java.lang.String);
+    method public void findAllAsync(java.lang.String);
     method public void findNext(boolean);
     method public void flingScroll(int, int);
     method public void freeMemory();
@@ -25819,6 +25825,7 @@
     method public void saveWebArchive(java.lang.String, boolean, android.webkit.ValueCallback<java.lang.String>);
     method public void setCertificate(android.net.http.SslCertificate);
     method public void setDownloadListener(android.webkit.DownloadListener);
+    method public void setFindListener(android.webkit.WebView.FindListener);
     method public void setHorizontalScrollbarOverlay(boolean);
     method public void setHttpAuthUsernamePassword(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
     method public void setInitialScale(int);
@@ -25837,6 +25844,10 @@
     field public static final java.lang.String SCHEME_TEL = "tel:";
   }
 
+  public static abstract interface WebView.FindListener {
+    method public abstract void onFindResultReceived(int, int, boolean);
+  }
+
   public static class WebView.HitTestResult {
     method public java.lang.String getExtra();
     method public int getType();
diff --git a/cmds/app_process/Android.mk b/cmds/app_process/Android.mk
index 2391b72..b39c335 100644
--- a/cmds/app_process/Android.mk
+++ b/cmds/app_process/Android.mk
@@ -13,3 +13,29 @@
 LOCAL_MODULE:= app_process
 
 include $(BUILD_EXECUTABLE)
+
+
+# Build a variant of app_process binary linked with ASan runtime.
+# ARM-only at the moment.
+ifeq ($(TARGET_ARCH),arm)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	app_main.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+	libutils \
+	libbinder \
+	libandroid_runtime
+
+LOCAL_MODULE := app_process__asan
+LOCAL_MODULE_TAGS := eng
+LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)/asan
+LOCAL_MODULE_STEM := app_process
+LOCAL_ADDRESS_SANITIZER := true
+
+include $(BUILD_EXECUTABLE)
+
+endif # ifeq($(TARGET_ARCH),arm)
diff --git a/cmds/input/src/com/android/commands/input/Input.java b/cmds/input/src/com/android/commands/input/Input.java
index c4c3b8a..3037881 100755
--- a/cmds/input/src/com/android/commands/input/Input.java
+++ b/cmds/input/src/com/android/commands/input/Input.java
@@ -16,11 +16,12 @@
 
 package com.android.commands.input;
 
+import android.hardware.input.InputManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.util.Log;
-import android.view.IWindowManager;
+import android.view.InputDevice;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -33,8 +34,6 @@
 public class Input {
     private static final String TAG = "Input";
 
-    private IWindowManager mWindowManager;
-
     /**
      * Command-line entry point.
      *
@@ -44,13 +43,6 @@
         (new Input()).run(args);
     }
 
-    private IWindowManager getWindowManager() {
-        if (mWindowManager == null) {
-            mWindowManager = (IWindowManager.Stub.asInterface(ServiceManager.getService("window")));
-        }
-        return mWindowManager;
-    }
-
     private void run(String[] args) {
         if (args.length < 1) {
             showUsage();
@@ -127,8 +119,10 @@
 
     private void sendKeyEvent(int keyCode) {
         long now = SystemClock.uptimeMillis();
-        injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0));
-        injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0));
+        injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0, 0,
+                KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD));
+        injectKeyEvent(new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0, 0,
+                KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0, InputDevice.SOURCE_KEYBOARD));
     }
 
     private void sendTap(float x, float y) {
@@ -150,23 +144,14 @@
     }
 
     private void injectKeyEvent(KeyEvent event) {
-        try {
-            Log.i(TAG, "InjectKeyEvent: " + event);
-            getWindowManager().injectKeyEvent(event, true);
-        } catch (RemoteException ex) {
-            Log.i(TAG, "RemoteException", ex);
-        }
+        Log.i(TAG, "InjectKeyEvent: " + event);
+        InputManager.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
     }
 
     private void injectPointerEvent(MotionEvent event) {
-        try {
-            Log.i("Input", "InjectPointerEvent: " + event);
-            getWindowManager().injectPointerEvent(event, true);
-        } catch (RemoteException ex) {
-            Log.i(TAG, "RemoteException", ex);
-        } finally {
-            event.recycle();
-        }
+        event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
+        Log.i("Input", "InjectPointerEvent: " + event);
+        InputManager.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
     }
 
     private static final float lerp(float a, float b, float alpha) {
@@ -174,7 +159,7 @@
     }
 
     private void showUsage() {
-        System.err.println("usage: input [text|keyevent]");
+        System.err.println("usage: input ...");
         System.err.println("       input text <string>");
         System.err.println("       input keyevent <key code>");
         System.err.println("       input tap <x> <y>");
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 3e123ba..7207e29 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2522,7 +2522,19 @@
                 if (onOptionsItemSelected(item)) {
                     return true;
                 }
-                return mFragments.dispatchOptionsItemSelected(item);
+                if (mFragments.dispatchOptionsItemSelected(item)) {
+                    return true;
+                }
+                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;
                 
             case Window.FEATURE_CONTEXT_MENU:
                 EventLog.writeEvent(50000, 1, item.getTitleCondensed());
@@ -2654,15 +2666,6 @@
         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;
     }
 
@@ -4865,11 +4868,19 @@
      * 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.
+     * Activity subclasses may override this method to modify the Intent returned by
+     * super.getParentActivityIntent() or to implement a different mechanism of retrieving
+     * the parent intent entirely.
      *
-     * @return a new Intent targeting the defined parent of this activity
+     * @return a new Intent targeting the defined parent of this activity or null if
+     *         there is no valid parent.
      */
     public Intent getParentActivityIntent() {
-        return new Intent().setClassName(this, mActivityInfo.parentActivityName);
+        final String parentName = mActivityInfo.parentActivityName;
+        if (TextUtils.isEmpty(parentName)) {
+            return null;
+        }
+        return new Intent().setClassName(this, parentName);
     }
 
     // ------------------ Internal API ------------------
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 000abc5..a3fdf3e 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -867,6 +867,16 @@
             return true;
         }
 
+        case GET_UID_FOR_INTENT_SENDER_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IIntentSender r = IIntentSender.Stub.asInterface(
+                data.readStrongBinder());
+            int res = getUidForIntentSender(r);
+            reply.writeNoException();
+            reply.writeInt(res);
+            return true;
+        }
+
         case SET_PROCESS_LIMIT_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             int max = data.readInt();
@@ -2714,6 +2724,18 @@
         reply.recycle();
         return res;
     }
+    public int getUidForIntentSender(IIntentSender sender) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(sender.asBinder());
+        mRemote.transact(GET_UID_FOR_INTENT_SENDER_TRANSACTION, data, reply, 0);
+        reply.readException();
+        int res = reply.readInt();
+        data.recycle();
+        reply.recycle();
+        return res;
+    }
     public void setProcessLimit(int max) throws RemoteException
     {
         Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 9dde51c..c5d7b91 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.IInputManager;
 import android.hardware.input.InputManager;
 import android.hardware.usb.IUsbManager;
 import android.hardware.usb.UsbManager;
@@ -325,9 +326,9 @@
                 }});
 
         registerService(INPUT_SERVICE, new ServiceFetcher() {
-            public Object createService(ContextImpl ctx) {
-                return new InputManager(ctx);
-            }});
+                public Object createService(ContextImpl ctx) {
+                    return new InputManager(ctx);
+                }});
 
         registerService(INPUT_METHOD_SERVICE, new ServiceFetcher() {
                 public Object createService(ContextImpl ctx) {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 0f287c1..c71b186 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -175,6 +175,7 @@
     public boolean clearApplicationUserData(final String packageName,
             final IPackageDataObserver observer, int userId) throws RemoteException;
     public String getPackageForIntentSender(IIntentSender sender) throws RemoteException;
+    public int getUidForIntentSender(IIntentSender sender) throws RemoteException;
     
     public void setProcessLimit(int max) throws RemoteException;
     public int getProcessLimit() throws RemoteException;
@@ -531,6 +532,7 @@
     int START_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+89;
     int BACKUP_AGENT_CREATED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+90;
     int UNBIND_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+91;
+    int GET_UID_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+92;
 
 
     int START_ACTIVITY_IN_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+94;
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index e4f7950..f955713 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -23,6 +23,7 @@
 import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
+import android.hardware.input.InputManager;
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.IBinder;
@@ -35,6 +36,7 @@
 import android.util.AndroidRuntimeException;
 import android.util.Log;
 import android.view.IWindowManager;
+import android.view.InputDevice;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -859,11 +861,30 @@
      */
     public void sendKeySync(KeyEvent event) {
         validateNotAppThread();
-        try {
-            (IWindowManager.Stub.asInterface(ServiceManager.getService("window")))
-                .injectKeyEvent(event, true);
-        } catch (RemoteException e) {
+
+        long downTime = event.getDownTime();
+        long eventTime = event.getEventTime();
+        int action = event.getAction();
+        int code = event.getKeyCode();
+        int repeatCount = event.getRepeatCount();
+        int metaState = event.getMetaState();
+        int deviceId = event.getDeviceId();
+        int scancode = event.getScanCode();
+        int source = event.getSource();
+        int flags = event.getFlags();
+        if (source == InputDevice.SOURCE_UNKNOWN) {
+            source = InputDevice.SOURCE_KEYBOARD;
         }
+        if (eventTime == 0) {
+            eventTime = SystemClock.uptimeMillis();
+        }
+        if (downTime == 0) {
+            downTime = eventTime;
+        }
+        KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
+                deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source);
+        InputManager.injectInputEvent(newEvent,
+                InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
     }
     
     /**
@@ -902,11 +923,10 @@
      */
     public void sendPointerSync(MotionEvent event) {
         validateNotAppThread();
-        try {
-            (IWindowManager.Stub.asInterface(ServiceManager.getService("window")))
-                .injectPointerEvent(event, true);
-        } catch (RemoteException e) {
+        if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
+            event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
         }
+        InputManager.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
     }
 
     /**
@@ -922,11 +942,10 @@
      */
     public void sendTrackballEventSync(MotionEvent event) {
         validateNotAppThread();
-        try {
-            (IWindowManager.Stub.asInterface(ServiceManager.getService("window")))
-                .injectTrackballEvent(event, true);
-        } catch (RemoteException e) {
+        if ((event.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) {
+            event.setSource(InputDevice.SOURCE_TRACKBALL);
         }
+        InputManager.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
     }
 
     /**
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 2a9f1af..18d682d 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2000,8 +2000,8 @@
      * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_USB_ANLG_HEADSET_PLUG =
-            "android.intent.action.USB_ANLG_HEADSET_PLUG";
+    public static final String ACTION_ANALOG_AUDIO_DOCK_PLUG =
+            "android.intent.action.ANALOG_AUDIO_DOCK_PLUG";
 
     /**
      * Broadcast Action: A digital audio speaker/headset plugged in or unplugged.
@@ -2015,8 +2015,8 @@
      * @hide
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_USB_DGTL_HEADSET_PLUG =
-            "android.intent.action.USB_DGTL_HEADSET_PLUG";
+    public static final String ACTION_DIGITAL_AUDIO_DOCK_PLUG =
+            "android.intent.action.DIGITAL_AUDIO_DOCK_PLUG";
 
     /**
      * Broadcast Action: A HMDI cable was plugged or unplugged
@@ -2034,6 +2034,38 @@
             "android.intent.action.HDMI_AUDIO_PLUG";
 
     /**
+     * Broadcast Action: A USB audio accessory was plugged in or unplugged.
+     *
+     * <p>The intent will have the following extra values:
+     * <ul>
+     *   <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>
+     *   <li><em>card</em> - ALSA card number (integer) </li>
+     *   <li><em>device</em> - ALSA device number (integer) </li>
+     * </ul>
+     * </ul>
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_USB_AUDIO_ACCESSORY_PLUG =
+            "android.intent.action.USB_AUDIO_ACCESSORY_PLUG";
+
+    /**
+     * Broadcast Action: A USB audio device was plugged in or unplugged.
+     *
+     * <p>The intent will have the following extra values:
+     * <ul>
+     *   <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>
+     *   <li><em>card</em> - ALSA card number (integer) </li>
+     *   <li><em>device</em> - ALSA device number (integer) </li>
+     * </ul>
+     * </ul>
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_USB_AUDIO_DEVICE_PLUG =
+            "android.intent.action.USB_AUDIO_DEVICE_PLUG";
+
+    /**
      * <p>Broadcast Action: The user has switched on advanced settings in the settings app:</p>
      * <ul>
      *   <li><em>state</em> - A boolean value indicating whether the settings is on or off.</li>
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 15ccda3..7571993 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -94,10 +94,12 @@
     public static class SplitPermissionInfo {
         public final String rootPerm;
         public final String[] newPerms;
+        public final int targetSdk;
 
-        public SplitPermissionInfo(String rootPerm, String[] newPerms) {
+        public SplitPermissionInfo(String rootPerm, String[] newPerms, int targetSdk) {
             this.rootPerm = rootPerm;
             this.newPerms = newPerms;
+            this.targetSdk = targetSdk;
         }
     }
 
@@ -126,7 +128,14 @@
     public static final PackageParser.SplitPermissionInfo SPLIT_PERMISSIONS[] =
         new PackageParser.SplitPermissionInfo[] {
             new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
-                    new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE })
+                    new String[] { android.Manifest.permission.READ_EXTERNAL_STORAGE },
+                    android.os.Build.VERSION_CODES.CUR_DEVELOPMENT+1),
+            new PackageParser.SplitPermissionInfo(android.Manifest.permission.READ_CONTACTS,
+                    new String[] { android.Manifest.permission.READ_CALL_LOG },
+                    android.os.Build.VERSION_CODES.JELLY_BEAN),
+            new PackageParser.SplitPermissionInfo(android.Manifest.permission.WRITE_CONTACTS,
+                    new String[] { android.Manifest.permission.WRITE_CALL_LOG },
+                    android.os.Build.VERSION_CODES.JELLY_BEAN)
     };
 
     private String mArchiveSourcePath;
@@ -1293,8 +1302,9 @@
         for (int is=0; is<NS; is++) {
             final PackageParser.SplitPermissionInfo spi
                     = PackageParser.SPLIT_PERMISSIONS[is];
-            if (!pkg.requestedPermissions.contains(spi.rootPerm)) {
-                break;
+            if (pkg.applicationInfo.targetSdkVersion >= spi.targetSdk
+                    || !pkg.requestedPermissions.contains(spi.rootPerm)) {
+                continue;
             }
             for (int in=0; in<spi.newPerms.length; in++) {
                 final String perm = spi.newPerms[in];
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 85061bb..c2abce5 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -16,6 +16,22 @@
 
 package android.hardware.input;
 
+import android.view.InputDevice;
+import android.view.InputEvent;
+
 /** @hide */
 interface IInputManager {
+    // Gets input device information.
+    InputDevice getInputDevice(int deviceId);
+    int[] getInputDeviceIds();
+
+    // Reports whether the hardware supports the given keys; returns true if successful
+    boolean hasKeys(int deviceId, int sourceMask, in int[] keyCodes, out boolean[] keyExists);
+
+    // Temporarily changes the pointer speed.
+    void tryPointerSpeed(int speed);
+
+    // Injects an input event into the system.  To inject into windows owned by other
+    // applications, the caller must have the INJECT_EVENTS permission.
+    boolean injectInputEvent(in InputEvent ev, int mode);
 }
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 6093404..5ead1f4 100755
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -31,9 +31,16 @@
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.os.Bundle;
+import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
 import android.util.Log;
+import android.view.InputDevice;
+import android.view.InputEvent;
 import android.view.KeyCharacterMap;
 import android.view.KeyCharacterMap.UnavailableException;
 
@@ -53,6 +60,8 @@
 public final class InputManager {
     private static final String TAG = "InputManager";
 
+    private static final IInputManager sIm;
+
     private final Context mContext;
 
     // Used to simulate a persistent data store.
@@ -118,6 +127,53 @@
     public static final String META_DATA_KEYBOARD_LAYOUTS =
             "android.hardware.input.metadata.KEYBOARD_LAYOUTS";
 
+    /**
+     * Pointer Speed: The minimum (slowest) pointer speed (-7).
+     * @hide
+     */
+    public static final int MIN_POINTER_SPEED = -7;
+
+    /**
+     * Pointer Speed: The maximum (fastest) pointer speed (7).
+     * @hide
+     */
+    public static final int MAX_POINTER_SPEED = 7;
+
+    /**
+     * Pointer Speed: The default pointer speed (0).
+     * @hide
+     */
+    public static final int DEFAULT_POINTER_SPEED = 0;
+
+    /**
+     * Input Event Injection Synchronization Mode: None.
+     * Never blocks.  Injection is asynchronous and is assumed always to be successful.
+     * @hide
+     */
+    public static final int INJECT_INPUT_EVENT_MODE_ASYNC = 0; // see InputDispatcher.h
+
+    /**
+     * Input Event Injection Synchronization Mode: Wait for result.
+     * Waits for previous events to be dispatched so that the input dispatcher can
+     * determine whether input event injection will be permitted based on the current
+     * input focus.  Does not wait for the input event to finish being handled
+     * by the application.
+     * @hide
+     */
+    public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT = 1;  // see InputDispatcher.h
+
+    /**
+     * Input Event Injection Synchronization Mode: Wait for finish.
+     * Waits for the event to be delivered to the application and handled.
+     * @hide
+     */
+    public static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2;  // see InputDispatcher.h
+
+    static {
+        IBinder b = ServiceManager.getService(Context.INPUT_SERVICE);
+        sIm = IInputManager.Stub.asInterface(b);
+    }
+
     /** @hide */
     public InputManager(Context context) {
         mContext = context;
@@ -296,6 +352,160 @@
         return null;
     }
 
+    /**
+     * Gets the mouse pointer speed.
+     * <p>
+     * Only returns the permanent mouse pointer speed.  Ignores any temporary pointer
+     * speed set by {@link #tryPointerSpeed}.
+     * </p>
+     *
+     * @return The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
+     * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
+     *
+     * @hide
+     */
+    public int getPointerSpeed() {
+        int speed = DEFAULT_POINTER_SPEED;
+        try {
+            speed = Settings.System.getInt(mContext.getContentResolver(),
+                    Settings.System.POINTER_SPEED);
+        } catch (SettingNotFoundException snfe) {
+        }
+        return speed;
+    }
+
+    /**
+     * Sets the mouse pointer speed.
+     * <p>
+     * Requires {@link android.Manifest.permissions.WRITE_SETTINGS}.
+     * </p>
+     *
+     * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
+     * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
+     *
+     * @hide
+     */
+    public void setPointerSpeed(int speed) {
+        if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) {
+            throw new IllegalArgumentException("speed out of range");
+        }
+
+        Settings.System.putInt(mContext.getContentResolver(),
+                Settings.System.POINTER_SPEED, speed);
+    }
+
+    /**
+     * Changes the mouse pointer speed temporarily, but does not save the setting.
+     * <p>
+     * Requires {@link android.Manifest.permission.SET_POINTER_SPEED}.
+     * </p>
+     *
+     * @param speed The pointer speed as a value between {@link #MIN_POINTER_SPEED} and
+     * {@link #MAX_POINTER_SPEED}, or the default value {@link #DEFAULT_POINTER_SPEED}.
+     *
+     * @hide
+     */
+    public void tryPointerSpeed(int speed) {
+        if (speed < MIN_POINTER_SPEED || speed > MAX_POINTER_SPEED) {
+            throw new IllegalArgumentException("speed out of range");
+        }
+
+        try {
+            sIm.tryPointerSpeed(speed);
+        } catch (RemoteException ex) {
+            Log.w(TAG, "Could not set temporary pointer speed.", ex);
+        }
+    }
+
+    /**
+     * Gets information about the input device with the specified id.
+     * @param id The device id.
+     * @return The input device or null if not found.
+     *
+     * @hide
+     */
+    public static InputDevice getInputDevice(int id) {
+        try {
+            return sIm.getInputDevice(id);
+        } catch (RemoteException ex) {
+            throw new RuntimeException("Could not get input device information.", ex);
+        }
+    }
+
+    /**
+     * Gets the ids of all input devices in the system.
+     * @return The input device ids.
+     *
+     * @hide
+     */
+    public static int[] getInputDeviceIds() {
+        try {
+            return sIm.getInputDeviceIds();
+        } catch (RemoteException ex) {
+            throw new RuntimeException("Could not get input device ids.", ex);
+        }
+    }
+
+    /**
+     * Queries the framework about whether any physical keys exist on the
+     * any keyboard attached to the device that are capable of producing the given
+     * array of key codes.
+     *
+     * @param keyCodes The array of key codes to query.
+     * @return A new array of the same size as the key codes array whose elements
+     * are set to true if at least one attached keyboard supports the corresponding key code
+     * at the same index in the key codes array.
+     *
+     * @hide
+     */
+    public static boolean[] deviceHasKeys(int[] keyCodes) {
+        boolean[] ret = new boolean[keyCodes.length];
+        try {
+            sIm.hasKeys(-1, InputDevice.SOURCE_ANY, keyCodes, ret);
+        } catch (RemoteException e) {
+            // no fallback; just return the empty array
+        }
+        return ret;
+    }
+
+    /**
+     * Injects an input event into the event system on behalf of an application.
+     * The synchronization mode determines whether the method blocks while waiting for
+     * input injection to proceed.
+     * <p>
+     * Requires {@link android.Manifest.permission.INJECT_EVENTS} to inject into
+     * windows that are owned by other applications.
+     * </p><p>
+     * Make sure you correctly set the event time and input source of the event
+     * before calling this method.
+     * </p>
+     *
+     * @param event The event to inject.
+     * @param mode The synchronization mode.  One of:
+     * {@link #INJECT_INPUT_EVENT_MODE_ASYNC},
+     * {@link #INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT}, or
+     * {@link #INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH}.
+     * @return True if input event injection succeeded.
+     *
+     * @hide
+     */
+    public static boolean injectInputEvent(InputEvent event, int mode) {
+        if (event == null) {
+            throw new IllegalArgumentException("event must not be null");
+        }
+        if (mode != INJECT_INPUT_EVENT_MODE_ASYNC
+                && mode != INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH
+                && mode != INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) {
+            throw new IllegalArgumentException("mode is invalid");
+        }
+
+        try {
+            return sIm.injectInputEvent(event, mode);
+        } catch (RemoteException ex) {
+            return false;
+        }
+    }
+
     private static String makeKeyboardLayoutDescriptor(String packageName,
             String receiverName, String keyboardName) {
         return packageName + "/" + receiverName + "/" + keyboardName;
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 93f93c7..c40504a7 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -66,6 +66,8 @@
      * PTP function is enabled
      * <li> {@link #USB_FUNCTION_PTP} boolean extra indicating whether the
      * accessory function is enabled
+     * <li> {@link #USB_FUNCTION_AUDIO_SOURCE} boolean extra indicating whether the
+     * audio source function is enabled
      * </ul>
      *
      * {@hide}
@@ -178,6 +180,14 @@
     public static final String USB_FUNCTION_PTP = "ptp";
 
     /**
+     * Name of the audio source USB function.
+     * Used in extras for the {@link #ACTION_USB_STATE} broadcast
+     *
+     * {@hide}
+     */
+    public static final String USB_FUNCTION_AUDIO_SOURCE = "audio_source";
+
+    /**
      * Name of the Accessory USB function.
      * Used in extras for the {@link #ACTION_USB_STATE} broadcast
      *
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index 0e883cf..b4f6367 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.net.INetworkStatsSession;
 import android.net.NetworkStats;
 import android.net.NetworkStatsHistory;
 import android.net.NetworkTemplate;
@@ -23,15 +24,11 @@
 /** {@hide} */
 interface INetworkStatsService {
 
-    /** Return historical network layer stats for traffic that matches template. */
-    NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template, int fields);
-    /** Return historical network layer stats for specific UID traffic that matches template. */
-    NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid, int set, int tag, int fields);
+    /** Start a statistics query session. */
+    INetworkStatsSession openSession();
 
-    /** Return network layer usage summary for traffic that matches template. */
-    NetworkStats getSummaryForNetwork(in NetworkTemplate template, long start, long end);
-    /** Return network layer usage summary per UID for traffic that matches template. */
-    NetworkStats getSummaryForAllUid(in NetworkTemplate template, long start, long end, boolean includeTags);
+    /** Return network layer usage total for traffic that matches template. */
+    long getNetworkTotalBytes(in NetworkTemplate template, long start, long end);
 
     /** Return data layer snapshot of UID network usage. */
     NetworkStats getDataLayerSnapshotForUid(int uid);
diff --git a/core/java/android/net/INetworkStatsSession.aidl b/core/java/android/net/INetworkStatsSession.aidl
new file mode 100644
index 0000000..1596fa2
--- /dev/null
+++ b/core/java/android/net/INetworkStatsSession.aidl
@@ -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 android.net;
+
+import android.net.NetworkStats;
+import android.net.NetworkStatsHistory;
+import android.net.NetworkTemplate;
+
+/** {@hide} */
+interface INetworkStatsSession {
+
+    /** Return network layer usage summary for traffic that matches template. */
+    NetworkStats getSummaryForNetwork(in NetworkTemplate template, long start, long end);
+    /** Return historical network layer stats for traffic that matches template. */
+    NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template, int fields);
+
+    /** Return network layer usage summary per UID for traffic that matches template. */
+    NetworkStats getSummaryForAllUid(in NetworkTemplate template, long start, long end, boolean includeTags);
+    /** Return historical network layer stats for specific UID traffic that matches template. */
+    NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid, int set, int tag, int fields);
+
+    void close();
+
+}
diff --git a/core/java/android/net/NetworkQuotaInfo.java b/core/java/android/net/NetworkQuotaInfo.java
index 6535256..1725ed7 100644
--- a/core/java/android/net/NetworkQuotaInfo.java
+++ b/core/java/android/net/NetworkQuotaInfo.java
@@ -57,12 +57,12 @@
         return mHardLimitBytes;
     }
 
-    /** {@inheritDoc} */
+    @Override
     public int describeContents() {
         return 0;
     }
 
-    /** {@inheritDoc} */
+    @Override
     public void writeToParcel(Parcel out, int flags) {
         out.writeLong(mEstimatedBytes);
         out.writeLong(mSoftLimitBytes);
@@ -70,10 +70,12 @@
     }
 
     public static final Creator<NetworkQuotaInfo> CREATOR = new Creator<NetworkQuotaInfo>() {
+        @Override
         public NetworkQuotaInfo createFromParcel(Parcel in) {
             return new NetworkQuotaInfo(in);
         }
 
+        @Override
         public NetworkQuotaInfo[] newArray(int size) {
             return new NetworkQuotaInfo[size];
         }
diff --git a/core/java/android/net/NetworkState.java b/core/java/android/net/NetworkState.java
index 704111b..2fc69ad 100644
--- a/core/java/android/net/NetworkState.java
+++ b/core/java/android/net/NetworkState.java
@@ -52,12 +52,12 @@
         subscriberId = in.readString();
     }
 
-    /** {@inheritDoc} */
+    @Override
     public int describeContents() {
         return 0;
     }
 
-    /** {@inheritDoc} */
+    @Override
     public void writeToParcel(Parcel out, int flags) {
         out.writeParcelable(networkInfo, flags);
         out.writeParcelable(linkProperties, flags);
@@ -66,10 +66,12 @@
     }
 
     public static final Creator<NetworkState> CREATOR = new Creator<NetworkState>() {
+        @Override
         public NetworkState createFromParcel(Parcel in) {
             return new NetworkState(in);
         }
 
+        @Override
         public NetworkState[] newArray(int size) {
             return new NetworkState[size];
         }
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 7a1ef66..844d055 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -155,7 +155,7 @@
         operations = parcel.createLongArray();
     }
 
-    /** {@inheritDoc} */
+    @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeLong(elapsedRealtime);
         dest.writeInt(size);
@@ -352,10 +352,9 @@
      * on matching {@link #uid} and {@link #tag} rows. Ignores {@link #iface},
      * since operation counts are at data layer.
      */
-    @Deprecated
     public void spliceOperationsFrom(NetworkStats stats) {
         for (int i = 0; i < size; i++) {
-            final int j = stats.findIndex(IFACE_ALL, uid[i], set[i], tag[i]);
+            final int j = stats.findIndex(iface[i], uid[i], set[i], tag[i]);
             if (j == -1) {
                 operations[i] = 0;
             } else {
@@ -663,16 +662,18 @@
         return writer.toString();
     }
 
-    /** {@inheritDoc} */
+    @Override
     public int describeContents() {
         return 0;
     }
 
     public static final Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() {
+        @Override
         public NetworkStats createFromParcel(Parcel in) {
             return new NetworkStats(in);
         }
 
+        @Override
         public NetworkStats[] newArray(int size) {
             return new NetworkStats[size];
         }
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index faf8a3f..0003c6e 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -130,7 +130,7 @@
         totalBytes = in.readLong();
     }
 
-    /** {@inheritDoc} */
+    @Override
     public void writeToParcel(Parcel out, int flags) {
         out.writeLong(bucketDuration);
         writeLongArray(out, bucketStart, bucketCount);
@@ -191,7 +191,7 @@
         writeVarLongArray(out, operations, bucketCount);
     }
 
-    /** {@inheritDoc} */
+    @Override
     public int describeContents() {
         return 0;
     }
@@ -586,10 +586,12 @@
     }
 
     public static final Creator<NetworkStatsHistory> CREATOR = new Creator<NetworkStatsHistory>() {
+        @Override
         public NetworkStatsHistory createFromParcel(Parcel in) {
             return new NetworkStatsHistory(in);
         }
 
+        @Override
         public NetworkStatsHistory[] newArray(int size) {
             return new NetworkStatsHistory[size];
         }
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index 973fac1..ee3e165 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -238,6 +238,19 @@
         }
     }
 
+    /** {@hide} */
+    public static void closeQuietly(INetworkStatsSession session) {
+        // TODO: move to NetworkStatsService once it exists
+        if (session != null) {
+            try {
+                session.close();
+            } catch (RuntimeException rethrown) {
+                throw rethrown;
+            } catch (Exception ignored) {
+            }
+        }
+    }
+
     /**
      * Get the total number of packets transmitted through the mobile interface.
      *
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index d724d56..0e9306b 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -4531,8 +4531,6 @@
         /**
          * The phone number's E164 representation.
          * <P>Type: TEXT</P>
-         *
-         * @hide
          */
         public static final String NORMALIZED_NUMBER = "normalized_number";
     }
@@ -5408,10 +5406,10 @@
             public static final String NUMBER = DATA;
 
             /**
-             * The phone number's E164 representation.
+             * The phone number's E164 representation. This value can be omitted in which
+             * case the provider will try to automatically infer it. If present, {@link #NUMBER}
+             * has to be set as well (it will be ignored otherwise).
              * <P>Type: TEXT</P>
-             *
-             * @hide
              */
             public static final String NORMALIZED_NUMBER = DATA4;
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 371e2a1..2aaf548 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -37,6 +37,7 @@
 import android.os.BatteryManager;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
@@ -2260,6 +2261,7 @@
 
         private static ILockSettings sLockSettings = null;
 
+        private static boolean sIsSystemProcess;
         private static final HashSet<String> MOVED_TO_LOCK_SETTINGS;
         static {
             MOVED_TO_LOCK_SETTINGS = new HashSet<String>(3);
@@ -2283,8 +2285,10 @@
             if (sLockSettings == null) {
                 sLockSettings = ILockSettings.Stub.asInterface(
                         (IBinder) ServiceManager.getService("lock_settings"));
+                sIsSystemProcess = Process.myUid() == Process.SYSTEM_UID;
             }
-            if (sLockSettings != null && MOVED_TO_LOCK_SETTINGS.contains(name)) {
+            if (sLockSettings != null && !sIsSystemProcess
+                    && MOVED_TO_LOCK_SETTINGS.contains(name)) {
                 try {
                     return sLockSettings.getString(name, "0", UserId.getCallingUserId());
                 } catch (RemoteException re) {
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index bb4b282..ae9042c 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -50,8 +50,6 @@
     public SpannableStringBuilder(CharSequence text, int start, int end) {
         int srclen = end - start;
 
-        if (srclen < 0) throw new StringIndexOutOfBoundsException();
-
         int len = ArrayUtils.idealCharArraySize(srclen + 1);
         mText = new char[len];
         mGapStart = srclen;
@@ -127,46 +125,38 @@
     }
 
     private void resizeFor(int size) {
-        int newlen = ArrayUtils.idealCharArraySize(size + 1);
-        char[] newtext = new char[newlen];
+        final int oldLength = mText.length;
+        final int newLength = ArrayUtils.idealCharArraySize(size + 1);
+        final int after = oldLength - (mGapStart + mGapLength);
 
-        int after = mText.length - (mGapStart + mGapLength);
+        char[] newText = new char[newLength];
+        System.arraycopy(mText, 0, newText, 0, mGapStart);
+        System.arraycopy(mText, oldLength - after, newText, newLength - after, after);
+        mText = newText;
 
-        System.arraycopy(mText, 0, newtext, 0, mGapStart);
-        System.arraycopy(mText, mText.length - after,
-                         newtext, newlen - after, after);
-
-        for (int i = 0; i < mSpanCount; i++) {
-            if (mSpanStarts[i] > mGapStart)
-                mSpanStarts[i] += newlen - mText.length;
-            if (mSpanEnds[i] > mGapStart)
-                mSpanEnds[i] += newlen - mText.length;
-        }
-
-        int oldlen = mText.length;
-        mText = newtext;
-        mGapLength += mText.length - oldlen;
-
+        final int delta = newLength - oldLength;
+        mGapLength += delta;
         if (mGapLength < 1)
             new Exception("mGapLength < 1").printStackTrace();
+
+        for (int i = 0; i < mSpanCount; i++) {
+            if (mSpanStarts[i] > mGapStart) mSpanStarts[i] += delta;
+            if (mSpanEnds[i] > mGapStart) mSpanEnds[i] += delta;
+        }
     }
 
     private void moveGapTo(int where) {
         if (where == mGapStart)
             return;
 
-        boolean atEnd = (where == length());
+        boolean atend = (where == length());
 
         if (where < mGapStart) {
             int overlap = mGapStart - where;
-
-            System.arraycopy(mText, where,
-                             mText, mGapStart + mGapLength - overlap, overlap);
+            System.arraycopy(mText, where, mText, mGapStart + mGapLength - overlap, overlap);
         } else /* where > mGapStart */ {
             int overlap = where - mGapStart;
-
-            System.arraycopy(mText, where + mGapLength - overlap,
-                             mText, mGapStart, overlap);
+            System.arraycopy(mText, where + mGapLength - overlap, mText, mGapStart, overlap);
         }
 
         // XXX be more clever
@@ -181,7 +171,7 @@
             else if (start == where) {
                 int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT;
 
-                if (flag == POINT || (atEnd && flag == PARAGRAPH))
+                if (flag == POINT || (atend && flag == PARAGRAPH))
                     start += mGapLength;
             }
 
@@ -192,7 +182,7 @@
             else if (end == where) {
                 int flag = (mSpanFlags[i] & END_MASK);
 
-                if (flag == POINT || (atEnd && flag == PARAGRAPH))
+                if (flag == POINT || (atend && flag == PARAGRAPH))
                     end += mGapLength;
             }
 
@@ -342,18 +332,17 @@
             boolean atEnd = (mGapStart + mGapLength == mText.length);
 
             for (int i = mSpanCount - 1; i >= 0; i--) {
-                if (mSpanStarts[i] >= start &&
-                        mSpanStarts[i] < mGapStart + mGapLength) {
+                if (mSpanStarts[i] >= start && mSpanStarts[i] < mGapStart + mGapLength) {
                     int flag = (mSpanFlags[i] & START_MASK) >> START_SHIFT;
 
-                if (flag == POINT || (flag == PARAGRAPH && atEnd))
-                    mSpanStarts[i] = mGapStart + mGapLength;
-                else
-                    mSpanStarts[i] = start;
+                    if (flag == POINT || (flag == PARAGRAPH && atEnd)) {
+                        mSpanStarts[i] = mGapStart + mGapLength;
+                    } else {
+                        mSpanStarts[i] = start;
+                    }
                 }
 
-                if (mSpanEnds[i] >= start &&
-                        mSpanEnds[i] < mGapStart + mGapLength) {
+                if (mSpanEnds[i] >= start && mSpanEnds[i] < mGapStart + mGapLength) {
                     int flag = (mSpanFlags[i] & END_MASK);
 
                     if (flag == POINT || (flag == PARAGRAPH && atEnd))
@@ -362,7 +351,8 @@
                         mSpanEnds[i] = start;
                 }
 
-                // remove 0-length SPAN_EXCLUSIVE_EXCLUSIVE
+                // remove 0-length SPAN_EXCLUSIVE_EXCLUSIVE, which are POINT_MARK and could
+                // get their boundaries swapped by the above code
                 if (mSpanEnds[i] < mSpanStarts[i]) {
                     removeSpan(i);
                 }
@@ -399,7 +389,7 @@
 
     // Documentation from interface
     public SpannableStringBuilder replace(final int start, final int end,
-            CharSequence tb, int tbstart, int tbend) {
+                        CharSequence tb, int tbstart, int tbend) {
         int filtercount = mFilters.length;
         for (int i = 0; i < filtercount; i++) {
             CharSequence repl = mFilters[i].filter(tb, tbstart, tbend, this, start, end);
@@ -421,26 +411,53 @@
         TextWatcher[] textWatchers = getSpans(start, start + origLen, TextWatcher.class);
         sendBeforeTextChanged(textWatchers, start, origLen, newLen);
 
-        // Try to keep the cursor / selection at the same relative position during
-        // a text replacement. If replaced or replacement text length is zero, this
-        // is already taken care of.
-        boolean adjustSelection = origLen != 0 && newLen != 0;
-        int selstart = 0;
-        int selend = 0;
-        if (adjustSelection) {
-            selstart = Selection.getSelectionStart(this);
-            selend = Selection.getSelectionEnd(this);
-        }
+        if (origLen == 0 || newLen == 0) {
+            change(start, end, tb, tbstart, tbend);
+        } else {
+            int selstart = Selection.getSelectionStart(this);
+            int selend = Selection.getSelectionEnd(this);
 
-        checkRange("replace", start, end);
+            // XXX just make the span fixups in change() do the right thing
+            // instead of this madness!
 
-        change(start, end, tb, tbstart, tbend);
+            checkRange("replace", start, end);
+            moveGapTo(end);
 
-        if (adjustSelection) {
+            if (mGapLength < 2)
+                resizeFor(length() + 1);
+
+            for (int i = mSpanCount - 1; i >= 0; i--) {
+                if (mSpanStarts[i] == mGapStart)
+                    mSpanStarts[i]++;
+
+                if (mSpanEnds[i] == mGapStart)
+                    mSpanEnds[i]++;
+            }
+
+            mText[mGapStart] = ' ';
+            mGapStart++;
+            mGapLength--;
+
+            if (mGapLength < 1) {
+                new Exception("mGapLength < 1").printStackTrace();
+            }
+
+            change(start + 1, start + 1, tb, tbstart, tbend);
+            change(start, start + 1, "", 0, 0);
+            change(start + newLen, start + newLen + origLen, "", 0, 0);
+
+            /*
+             * Special case to keep the cursor in the same position
+             * if it was somewhere in the middle of the replaced region.
+             * If it was at the start or the end or crossing the whole
+             * replacement, it should already be where it belongs.
+             * TODO: Is there some more general mechanism that could
+             * accomplish this?
+             */
             if (selstart > start && selstart < end) {
                 long off = selstart - start;
 
-                off = off * newLen / origLen;
+                off = off * newLen / (end - start);
                 selstart = (int) off + start;
 
                 setSpan(false, Selection.SELECTION_START, selstart, selstart,
@@ -449,7 +466,7 @@
             if (selend > start && selend < end) {
                 long off = selend - start;
 
-                off = off * newLen / origLen;
+                off = off * newLen / (end - start);
                 selend = (int) off + start;
 
                 setSpan(false, Selection.SELECTION_END, selend, selend, Spanned.SPAN_POINT_POINT);
@@ -495,6 +512,11 @@
             }
         }
 
+        if (flags == Spanned.SPAN_EXCLUSIVE_EXCLUSIVE && start == end) {
+            throw new IllegalArgumentException(
+                    "SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length");
+        }
+
         if (start > mGapStart) {
             start += mGapLength;
         } else if (start == mGapStart) {
diff --git a/core/java/android/view/GLES20TextureLayer.java b/core/java/android/view/GLES20TextureLayer.java
index cbb908b..16a13cf 100644
--- a/core/java/android/view/GLES20TextureLayer.java
+++ b/core/java/android/view/GLES20TextureLayer.java
@@ -42,6 +42,12 @@
         }        
     }
 
+    GLES20TextureLayer(SurfaceTexture surface, boolean isOpaque) {
+        this(isOpaque);
+        mSurface = surface;
+        mSurface.attachToGLContext(mTexture);
+    }
+
     @Override
     boolean isValid() {
         return mLayer != 0 && mTexture != 0;
@@ -72,6 +78,14 @@
         return mSurface;
     }
 
+    void setSurfaceTexture(SurfaceTexture surfaceTexture) {
+        if (mSurface != null) {
+            mSurface.release();
+        }
+        mSurface = surfaceTexture;
+        mSurface.attachToGLContext(mTexture);
+    }
+
     @Override
     void update(int width, int height, boolean isOpaque) {
         super.update(width, height, isOpaque);
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 346a933..aa0ac74 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -391,9 +391,9 @@
      * @param isOpaque Whether the layer should be opaque or not
      * 
      * @return A hardware layer
-     */    
+     */
     abstract HardwareLayer createHardwareLayer(boolean isOpaque);
-    
+
     /**
      * Creates a new hardware layer.
      * 
@@ -417,6 +417,15 @@
     abstract SurfaceTexture createSurfaceTexture(HardwareLayer layer);
 
     /**
+     * Sets the {@link android.graphics.SurfaceTexture} that will be used to
+     * render into the specified hardware layer.
+     *
+     * @param layer The layer to render into using a {@link android.graphics.SurfaceTexture}
+     * @param surfaceTexture The {@link android.graphics.SurfaceTexture} to use for the layer
+     */
+    abstract void setSurfaceTexture(HardwareLayer layer, SurfaceTexture surfaceTexture);
+
+    /**
      * Initializes the hardware renderer for the specified surface and setup the
      * renderer for drawing, if needed. This is invoked when the ViewAncestor has
      * potentially lost the hardware renderer. The hardware renderer should be
@@ -517,7 +526,7 @@
         static final int SURFACE_STATE_SUCCESS = 1;
         static final int SURFACE_STATE_UPDATED = 2;
 
-        static final int FUNCTOR_PROCESS_DELAY = 2;
+        static final int FUNCTOR_PROCESS_DELAY = 4;
 
         static EGL10 sEgl;
         static EGLDisplay sEglDisplay;
@@ -1345,6 +1354,11 @@
         }
 
         @Override
+        void setSurfaceTexture(HardwareLayer layer, SurfaceTexture surfaceTexture) {
+            ((GLES20TextureLayer) layer).setSurfaceTexture(surfaceTexture);
+        }
+
+        @Override
         void destroyLayers(View view) {
             if (view != null && isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) {
                 destroyHardwareLayer(view);
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index eb030de..8fe8e40 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -65,15 +65,6 @@
     // 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
-    // until pending input events are finished being dispatched even when 'sync' is false.
-    // Avoid calling these methods on your UI thread or use the 'NoWait' version instead.
-    boolean injectKeyEvent(in KeyEvent ev, boolean sync);
-    boolean injectPointerEvent(in MotionEvent ev, boolean sync);
-    boolean injectTrackballEvent(in MotionEvent ev, boolean sync);
-    boolean injectInputEventNoWait(in InputEvent ev);
-    
     // These can only be called when holding the MANAGE_APP_TOKENS permission.
     void pauseKeyDispatching(IBinder token);
     void resumeKeyDispatching(IBinder token);
@@ -128,26 +119,6 @@
     void setAnimationScale(int which, float scale);
     void setAnimationScales(in float[] scales);
     
-    // These require the READ_INPUT_STATE permission.
-    int getSwitchState(int sw);
-    int getSwitchStateForDevice(int devid, int sw);
-    int getScancodeState(int sw);
-    int getScancodeStateForDevice(int devid, int sw);
-    int getTrackballScancodeState(int sw);
-    int getDPadScancodeState(int sw);
-    int getKeycodeState(int sw);
-    int getKeycodeStateForDevice(int devid, int sw);
-    int getTrackballKeycodeState(int sw);
-    int getDPadKeycodeState(int sw);
-    InputChannel monitorInput(String inputChannelName);
-
-    // Report whether the hardware supports the given keys; returns true if successful
-    boolean hasKeys(in int[] keycodes, inout boolean[] keyExists);
-    
-    // Get input device information.
-    InputDevice getInputDevice(int deviceId);
-    int[] getInputDeviceIds();
-    
     // For testing
     void setInTouchMode(boolean showFocus);
 
@@ -220,11 +191,6 @@
     void statusBarVisibilityChanged(int visibility);
 
     /**
-     * Called by the settings application to temporarily set the pointer speed.
-     */
-    void setPointerSpeed(int speed);
-
-    /**
      * Block until the given window has been drawn to the screen.
      */
     void waitForWindowDrawn(IBinder token, in IRemoteCallback callback);
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 91e47e6..6f8d09b7 100755
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -16,9 +16,9 @@
 
 package android.view;
 
+import android.hardware.input.InputManager;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.os.RemoteException;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -41,6 +41,7 @@
 public final class InputDevice implements Parcelable {
     private int mId;
     private String mName;
+    private String mDescriptor;
     private int mSources;
     private int mKeyboardType;
     private String mKeyCharacterMapFile;
@@ -301,13 +302,7 @@
      * @return The input device or null if not found.
      */
     public static InputDevice getDevice(int id) {
-        IWindowManager wm = Display.getWindowManager();
-        try {
-            return wm.getInputDevice(id);
-        } catch (RemoteException ex) {
-            throw new RuntimeException(
-                    "Could not get input device information from Window Manager.", ex);
-        }
+        return InputManager.getInputDevice(id);
     }
     
     /**
@@ -315,13 +310,7 @@
      * @return The input device ids.
      */
     public static int[] getDeviceIds() {
-        IWindowManager wm = Display.getWindowManager();
-        try {
-            return wm.getInputDeviceIds();
-        } catch (RemoteException ex) {
-            throw new RuntimeException(
-                    "Could not get input device ids from Window Manager.", ex);
-        }
+        return InputManager.getInputDeviceIds();
     }
 
     /**
@@ -346,12 +335,24 @@
      * 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><p>
+     * It is possible for there to be multiple {@link InputDevice} instances that have the
+     * same input device descriptor.  This might happen in situations where a single
+     * human input device registers multiple {@link InputDevice} instances (HID collections)
+     * that describe separate features of the device, such as a keyboard that also
+     * has a trackpad.  Alternately, it may be that the input devices are simply
+     * indistinguishable, such as two keyboards made by the same manufacturer.
+     * </p><p>
+     * The input device descriptor returned by {@link #getDescriptor} should only bt
+     * used when an application needs to remember settings associated with a particular
+     * input device.  For all other purposes when referring to a logical
+     * {@link InputDevice} instance at runtime use the id returned by {@link #getId()}.
      * </p>
      *
      * @return The input device descriptor.
      */
     public String getDescriptor() {
-        return "PLACEHOLDER"; // TODO: implement for real
+        return mDescriptor;
     }
 
     /**
@@ -560,6 +561,7 @@
     private void readFromParcel(Parcel in) {
         mId = in.readInt();
         mName = in.readString();
+        mDescriptor = in.readString();
         mSources = in.readInt();
         mKeyboardType = in.readInt();
         mKeyCharacterMapFile = in.readString();
@@ -578,6 +580,7 @@
     public void writeToParcel(Parcel out, int flags) {
         out.writeInt(mId);
         out.writeString(mName);
+        out.writeString(mDescriptor);
         out.writeInt(mSources);
         out.writeInt(mKeyboardType);
         out.writeString(mKeyCharacterMapFile);
@@ -604,7 +607,8 @@
     public String toString() {
         StringBuilder description = new StringBuilder();
         description.append("Input Device ").append(mId).append(": ").append(mName).append("\n");
-        
+        description.append("  Descriptor: ").append(mDescriptor).append("\n");
+
         description.append("  Keyboard Type: ");
         switch (mKeyboardType) {
             case KEYBOARD_TYPE_NONE:
diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java
index 98cce5efe..b03f086 100644
--- a/core/java/android/view/KeyCharacterMap.java
+++ b/core/java/android/view/KeyCharacterMap.java
@@ -19,10 +19,9 @@
 import android.text.method.MetaKeyKeyListener;
 import android.util.AndroidRuntimeException;
 import android.util.SparseIntArray;
-import android.os.RemoteException;
+import android.hardware.input.InputManager;
 import android.util.SparseArray;
 
-import java.io.Reader;
 import java.lang.Character;
 
 /**
@@ -528,10 +527,7 @@
      * @return True if at least one attached keyboard supports the specified key code.
      */
     public static boolean deviceHasKey(int keyCode) {
-        int[] codeArray = new int[1];
-        codeArray[0] = keyCode;
-        boolean[] ret = deviceHasKeys(codeArray);
-        return ret[0];
+        return InputManager.deviceHasKeys(new int[] { keyCode })[0];
     }
 
     /**
@@ -545,14 +541,7 @@
      * at the same index in the key codes array.
      */
     public static boolean[] deviceHasKeys(int[] keyCodes) {
-        boolean[] ret = new boolean[keyCodes.length];
-        IWindowManager wm = Display.getWindowManager();
-        try {
-            wm.hasKeys(keyCodes, ret);
-        } catch (RemoteException e) {
-            // no fallback; just return the empty array
-        }
-        return ret;
+        return InputManager.deviceHasKeys(keyCodes);
     }
 
     /**
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 83999a1..3cd8b71 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -115,6 +115,7 @@
 
     private final Object[] mLock = new Object[0];
     private boolean mUpdateLayer;
+    private boolean mUpdateSurface;
 
     private SurfaceTexture.OnFrameAvailableListener mUpdateListener;
 
@@ -208,6 +209,8 @@
 
     private void destroySurface() {
         if (mLayer != null) {
+            mSurface.detachFromGLContext();
+
             boolean shouldRelease = true;
             if (mListener != null) {
                 shouldRelease = mListener.onSurfaceTextureDestroyed(mSurface);
@@ -322,9 +325,13 @@
             }
 
             mLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(mOpaque);
-            mSurface = mAttachInfo.mHardwareRenderer.createSurfaceTexture(mLayer);
+            if (!mUpdateSurface) {
+                // We already have a SurfaceTexture to use, and we will pass it
+                // to mLayer below.
+                mSurface = mAttachInfo.mHardwareRenderer.createSurfaceTexture(mLayer);
+            }
             nSetDefaultBufferSize(mSurface, getWidth(), getHeight());
-            nCreateNativeWindow(mSurface);            
+            nCreateNativeWindow(mSurface);
 
             mUpdateListener = new SurfaceTexture.OnFrameAvailableListener() {
                 @Override
@@ -344,6 +351,15 @@
             }
         }
 
+        if (mUpdateSurface) {
+            // Someone has requested that we use a specific SurfaceTexture, so
+            // tell mLayer about it and set the SurfaceTexture to use the
+            // current view size.
+            mUpdateSurface = false;
+            mAttachInfo.mHardwareRenderer.setSurfaceTexture(mLayer, mSurface);
+            nSetDefaultBufferSize(mSurface, getWidth(), getHeight());
+        }
+
         applyUpdate();
         applyTransformMatrix();
 
@@ -371,7 +387,7 @@
         mUpdateLayer = true;
         invalidate();
     }
-    
+
     private void applyUpdate() {
         if (mLayer == null) {
             return;
@@ -636,6 +652,32 @@
     }
 
     /**
+     * Set the {@link SurfaceTexture} for this view to use. If a {@link
+     * SurfaceTexture} is already being used by this view, it is immediately
+     * released and not be usable any more.  The {@link
+     * SurfaceTextureListener#onSurfaceTextureDestroyed} callback is <b>not</b>
+     * called.
+     *
+     * The {@link SurfaceTexture} object must be detached from all OpenGL ES
+     * contexts prior to calling this method.
+     *
+     * @param surfaceTexture The {@link SurfaceTexture} that the view should use.
+     * @see SurfaceTexture#detachFromGLContext()
+     * @hide
+     */
+    public void setSurfaceTexture(SurfaceTexture surfaceTexture) {
+        if (surfaceTexture == null) {
+            throw new NullPointerException("surfaceTexture must not be null");
+        }
+        if (mSurface != null) {
+            mSurface.release();
+        }
+        mSurface = surfaceTexture;
+        mUpdateSurface = true;
+        invalidateParentIfNeeded();
+    }
+
+    /**
      * Returns the {@link SurfaceTextureListener} currently associated with this
      * texture view.
      * 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 3c4b866..d62e32f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -14414,9 +14414,48 @@
     }
 
     /**
-     * Request that the visibility of the status bar be changed.
-     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or
-     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.
+     * Request that the visibility of the status bar or other screen/window
+     * decorations be changed.
+     *
+     * <p>This method is used to put the over device UI into temporary modes
+     * where the user's attention is focused more on the application content,
+     * by dimming or hiding surrounding system affordances.  This is typically
+     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
+     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
+     * to be placed behind the action bar (and with these flags other system
+     * affordances) so that smooth transitions between hiding and showing them
+     * can be done.
+     *
+     * <p>Two representative examples of the use of system UI visibility is
+     * implementing a content browsing application (like a magazine reader)
+     * and a video playing application.
+     *
+     * <p>The first code shows a typical implementation of a View in a content
+     * browsing application.  In this implementation, the application goes
+     * into a content-oriented mode by hiding the status bar and action bar,
+     * and putting the navigation elements into lights out mode.  The user can
+     * then interact with content while in this mode.  Such an application should
+     * provide an easy way for the user to toggle out of the mode (such as to
+     * check information in the status bar or access notifications).  In the
+     * implementation here, this is done simply by tapping on the content.
+     *
+     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
+     *      content}
+     *
+     * <p>This second code sample shows a typical implementation of a View
+     * in a video playing application.  In this situation, while the video is
+     * playing the application would like to go into a complete full-screen mode,
+     * to use as much of the display as possible for the video.  When in this state
+     * the user can not interact with the application; the system intercepts
+     * touching on the screen to pop the UI out of full screen mode.
+     *
+     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
+     *      content}
+     *
+     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
+     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
+     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
+     * and {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
      */
     public void setSystemUiVisibility(int visibility) {
         if (visibility != mSystemUiVisibility) {
@@ -14428,9 +14467,11 @@
     }
 
     /**
-     * Returns the status bar visibility that this view has requested.
-     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or
-     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.
+     * Returns the last {@link #setSystemUiVisibility(int) that this view has requested.
+     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
+     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
+     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
+     * and {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
      */
     public int getSystemUiVisibility() {
         return mSystemUiVisibility;
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index cf9cafc..491cd67 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -349,6 +349,10 @@
      * between it and the policy.
      */
     public interface WindowManagerFuncs {
+        public static final int LID_ABSENT = -1;
+        public static final int LID_CLOSED = 0;
+        public static final int LID_OPEN = 1;
+
         /**
          * Ask the window manager to re-evaluate the system UI flags.
          */
@@ -362,6 +366,16 @@
                 InputEventReceiver.Factory inputEventReceiverFactory,
                 String name, int windowType, int layoutParamsFlags, boolean canReceiveKeys,
                 boolean hasFocus, boolean touchFullscreen);
+
+        /**
+         * Returns a code that describes the current state of the lid switch.
+         */
+        public int getLidState();
+
+        /**
+         * Creates an input channel that will receive all input from the input dispatcher.
+         */
+        public InputChannel monitorInput(String name);
     }
 
     /**
@@ -943,10 +957,10 @@
     public void setRotationLw(int rotation);
 
     /**
-     * Called when the system is mostly done booting to determine whether
+     * Called when the system is mostly done booting to set whether
      * the system should go into safe mode.
      */
-    public boolean detectSafeMode();
+    public void setSafeMode(boolean safeMode);
     
     /**
      * Called when the system is mostly done booting.
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 17dbde8..067be39 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -405,7 +405,9 @@
                             }
                             // Check focus again in case that "onWindowFocus" is called before
                             // handling this message.
-                            checkFocus(mHasBeenInactive);
+                            if (mServedView != null && mServedView.hasWindowFocus()) {
+                                checkFocus(mHasBeenInactive);
+                            }
                         }
                     }
                     return;
@@ -1202,7 +1204,9 @@
             }
             if (DEBUG) Log.v(TAG, "checkFocus: view=" + mServedView
                     + " next=" + mNextServedView
-                    + " forceNewFocus=" + forceNewFocus);
+                    + " forceNewFocus=" + forceNewFocus
+                    + " package="
+                    + (mServedView != null ? mServedView.getContext().getPackageName() : "<none>"));
 
             if (mNextServedView == null) {
                 finishInputLocked();
diff --git a/core/java/android/view/textservice/SpellCheckerInfo.java b/core/java/android/view/textservice/SpellCheckerInfo.java
index 137743a..d05c1af 100644
--- a/core/java/android/view/textservice/SpellCheckerInfo.java
+++ b/core/java/android/view/textservice/SpellCheckerInfo.java
@@ -45,6 +45,7 @@
     private final ResolveInfo mService;
     private final String mId;
     private final int mLabel;
+    private final boolean mSupportsSentenceSpellCheck;
 
     /**
      * The spell checker setting activity's name, used by the system settings to
@@ -97,6 +98,9 @@
             label = sa.getResourceId(com.android.internal.R.styleable.SpellChecker_label, 0);
             settingsActivityComponent = sa.getString(
                     com.android.internal.R.styleable.SpellChecker_settingsActivity);
+            mSupportsSentenceSpellCheck = sa.getBoolean(
+                    com.android.internal.R.styleable.SpellChecker_supportsSentenceSpellCheck,
+                    false);
             sa.recycle();
 
             final int depth = parser.getDepth();
@@ -138,6 +142,7 @@
      */
     public SpellCheckerInfo(Parcel source) {
         mLabel = source.readInt();
+        mSupportsSentenceSpellCheck = source.readInt() != 0;
         mId = source.readString();
         mSettingsActivityName = source.readString();
         mService = ResolveInfo.CREATOR.createFromParcel(source);
@@ -152,6 +157,12 @@
         return mId;
     }
 
+    /**
+     * @hide
+     */
+    public boolean isSentenceSpellCheckSupported() {
+        return mSupportsSentenceSpellCheck;
+    }
 
     /**
      * Return the component of the service that implements.
@@ -177,6 +188,7 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(mLabel);
+        dest.writeInt(mSupportsSentenceSpellCheck ? 1 : 0);
         dest.writeString(mId);
         dest.writeString(mSettingsActivityName);
         mService.writeToParcel(dest, flags);
diff --git a/core/java/android/view/textservice/SpellCheckerSession.java b/core/java/android/view/textservice/SpellCheckerSession.java
index 35940ba..9dc05e4 100644
--- a/core/java/android/view/textservice/SpellCheckerSession.java
+++ b/core/java/android/view/textservice/SpellCheckerSession.java
@@ -436,15 +436,15 @@
      */
     public interface SpellCheckerSessionListener {
         /**
-         * Callback for {@link SpellCheckerSession#getSuggestions(TextInfo[], int, boolean)}
+         * Callback for {@link SpellCheckerSession#getSuggestions(TextInfo, int)}
+         * and {@link SpellCheckerSession#getSuggestions(TextInfo[], int, boolean)}
          * @param results an array of {@link SuggestionsInfo}s.
          * These results are suggestions for {@link TextInfo}s queried by
-         * {@link SpellCheckerSession#getSuggestions(TextInfo[], int, boolean)}.
+         * {@link SpellCheckerSession#getSuggestions(TextInfo, int)} or
+         * {@link SpellCheckerSession#getSuggestions(TextInfo[], int, boolean)}
          */
         public void onGetSuggestions(SuggestionsInfo[] results);
-        // TODO: Remove @hide as soon as the sample spell checker client gets fixed.
         /**
-         * @hide
          * Callback for {@link SpellCheckerSession#getSentenceSuggestions(TextInfo[], int)}
          * @param results an array of {@link SentenceSuggestionsInfo}s.
          * These results are suggestions for {@link TextInfo}s
@@ -494,7 +494,7 @@
     }
 
     /**
-     * @hide
+     * @return true if the spell checker supports sentence level spell checking APIs
      */
     public boolean isSentenceSpellCheckSupported() {
         return mSubtype.containsExtraValueKey(SUPPORT_SENTENCE_SPELL_CHECK);
diff --git a/core/java/android/webkit/FindActionModeCallback.java b/core/java/android/webkit/FindActionModeCallback.java
index 6c331ac..6b7263c 100644
--- a/core/java/android/webkit/FindActionModeCallback.java
+++ b/core/java/android/webkit/FindActionModeCallback.java
@@ -148,8 +148,8 @@
         mInput.showSoftInput(mEditText, 0);
     }
 
-    public void updateMatchCount(int matchIndex, int matchCount, boolean isNewFind) {
-        if (!isNewFind) {
+    public void updateMatchCount(int matchIndex, int matchCount, boolean isEmptyFind) {
+        if (!isEmptyFind) {
             mNumberOfMatches = matchCount;
             mActiveMatchIndex = matchIndex;
             updateMatchesString();
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 9492e38..84632c6 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -313,7 +313,6 @@
 
     /**
      * Interface to listen for find results.
-     * @hide
      */
     public interface FindListener {
         /**
@@ -1249,8 +1248,7 @@
      * Register the listener to be notified as find-on-page operations progress.
      * This will replace the current listener.
      *
-     * @param listener An implementation of {@link WebView#FindListener}.
-     * @hide
+     * @param listener An implementation of {@link FindListener}.
      */
     public void setFindListener(FindListener listener) {
         checkThread();
@@ -1258,11 +1256,15 @@
     }
 
     /**
-     * Highlight and scroll to the next occurance of String in findAll.
-     * Wraps the page infinitely, and scrolls.  Must be called after
-     * calling findAll.
+     * Highlight and scroll to the next match found by {@link #findAll} or
+     * {@link #findAllAsync}, wrapping around page boundaries as necessary.
+     * Notifies any registered {@link FindListener}. If neither
+     * {@link #findAll} nor {@link #findAllAsync(String)} has been called yet,
+     * or if {@link #clearMatches} has been called since the last find
+     * operation, this function does nothing.
      *
      * @param forward Direction to search.
+     * @see #setFindListener
      */
     public void findNext(boolean forward) {
         checkThread();
@@ -1271,10 +1273,13 @@
 
     /**
      * Find all instances of find on the page and highlight them.
+     * Notifies any registered {@link FindListener}.
      *
      * @param find  String to find.
      * @return int  The number of occurances of the String "find"
      *              that were found.
+     * @deprecated {@link #findAllAsync} is preferred.
+     * @see #setFindListener
      */
     public int findAll(String find) {
         checkThread();
@@ -1283,10 +1288,12 @@
 
     /**
      * Find all instances of find on the page and highlight them,
-     * asynchronously.
+     * asynchronously. Notifies any registered {@link FindListener}.
+     * Successive calls to this or {@link #findAll} will cancel any
+     * pending searches.
      *
      * @param find  String to find.
-     * @hide
+     * @see #setFindListener
      */
     public void findAllAsync(String find) {
         checkThread();
@@ -1333,8 +1340,9 @@
         return getFactory().getStatics().findAddress(addr);
     }
 
-    /*
-     * Clear the highlighting surrounding text matches created by findAll.
+    /**
+     * Clear the highlighting surrounding text matches created by
+     * {@link #findAll} or {@link #findAllAsync}.
      */
     public void clearMatches() {
         checkThread();
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 4c118ac..8dc3b7e 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -461,6 +461,7 @@
             selectionStart = Math.min(selectionStart, editable.length());
             selectionEnd = Math.min(selectionEnd, editable.length());
             setSelection(selectionStart, selectionEnd);
+            finishComposingText();
         }
 
         public void replaceSelection(CharSequence text) {
@@ -3588,7 +3589,9 @@
     @Override
     public void findNext(boolean forward) {
         if (0 == mNativeClass) return; // client isn't initialized
-        mWebViewCore.sendMessage(EventHub.FIND_NEXT, forward ? 1 : 0);
+        if (mFindRequest != null) {
+            mWebViewCore.sendMessage(EventHub.FIND_NEXT, forward ? 1 : 0, mFindRequest);
+        }
     }
 
     /**
@@ -3605,28 +3608,26 @@
 
     private int findAllBody(String find, boolean isAsync) {
         if (0 == mNativeClass) return 0; // client isn't initialized
-        mLastFind = find;
+        mFindRequest = null;
         if (find == null) return 0;
         mWebViewCore.removeMessages(EventHub.FIND_ALL);
-        WebViewCore.FindAllRequest request = new
-            WebViewCore.FindAllRequest(find);
+        mFindRequest = new WebViewCore.FindAllRequest(find);
         if (isAsync) {
-            mWebViewCore.sendMessage(EventHub.FIND_ALL, request);
+            mWebViewCore.sendMessage(EventHub.FIND_ALL, mFindRequest);
             return 0; // no need to wait for response
         }
-        synchronized(request) {
+        synchronized(mFindRequest) {
             try {
-                mWebViewCore.sendMessageAtFrontOfQueue(EventHub.FIND_ALL,
-                    request);
-                while (request.mMatchCount == -1) {
-                    request.wait();
+                mWebViewCore.sendMessageAtFrontOfQueue(EventHub.FIND_ALL, mFindRequest);
+                while (mFindRequest.mMatchCount == -1) {
+                    mFindRequest.wait();
                 }
             }
             catch (InterruptedException e) {
                 return 0;
             }
+            return mFindRequest.mMatchCount;
         }
-        return request.mMatchCount;
     }
 
     /**
@@ -3657,7 +3658,7 @@
             return true;
         }
         if (text == null) {
-            text = mLastFind;
+            text = mFindRequest == null ? null : mFindRequest.mSearchText;
         }
         if (text != null) {
             mFindCallback.setText(text);
@@ -3683,9 +3684,8 @@
     // or not we draw the highlights for matches.
     private boolean mFindIsUp;
 
-    // Keep track of the last string sent, so we can search again when find is
-    // reopened.
-    private String mLastFind;
+    // Keep track of the last find request sent.
+    private WebViewCore.FindAllRequest mFindRequest = null;
 
     /**
      * Return the first substring consisting of the address of a physical
@@ -8476,13 +8476,27 @@
                 }
 
                 case UPDATE_MATCH_COUNT: {
-                    boolean isNewFind = mLastFind == null || !mLastFind.equals(msg.obj);
-                    if (mFindCallback != null)
-                        mFindCallback.updateMatchCount(msg.arg1, msg.arg2, isNewFind);
-                    if (mFindListener != null)
-                        mFindListener.onFindResultReceived(msg.arg1, msg.arg2, true);
+                    WebViewCore.FindAllRequest request = (WebViewCore.FindAllRequest)msg.obj;
+                    if (request == null) {
+                        if (mFindCallback != null) {
+                            mFindCallback.updateMatchCount(0, 0, true);
+                        }
+                    } else if (request == mFindRequest) {
+                        int matchCount, matchIndex;
+                        synchronized (mFindRequest) {
+                            matchCount = request.mMatchCount;
+                            matchIndex = request.mMatchIndex;
+                        }
+                        if (mFindCallback != null) {
+                            mFindCallback.updateMatchCount(matchIndex, matchCount, false);
+                        }
+                        if (mFindListener != null) {
+                            mFindListener.onFindResultReceived(matchIndex, matchCount, true);
+                        }
+                    }
                     break;
                 }
+
                 case CLEAR_CARET_HANDLE:
                     selectionDone();
                     break;
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index b4ebc09..5549d89 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1041,9 +1041,11 @@
         public FindAllRequest(String text) {
             mSearchText = text;
             mMatchCount = -1;
+            mMatchIndex = -1;
         }
-        public String mSearchText;
+        public final String mSearchText;
         public int mMatchCount;
+        public int mMatchIndex;
     }
 
     /**
@@ -1777,21 +1779,32 @@
                             nativeSelectAll(mNativeClass);
                             break;
                         case FIND_ALL: {
-                            FindAllRequest request = (FindAllRequest) msg.obj;
-                            if (request == null) {
-                                nativeFindAll(mNativeClass, null);
-                            } else {
-                                request.mMatchCount = nativeFindAll(
-                                    mNativeClass, request.mSearchText);
-                                synchronized(request) {
+                            FindAllRequest request = (FindAllRequest)msg.obj;
+                            if (request != null) {
+                                int matchCount = nativeFindAll(mNativeClass, request.mSearchText);
+                                int matchIndex = nativeFindNext(mNativeClass, true);
+                                synchronized (request) {
+                                    request.mMatchCount = matchCount;
+                                    request.mMatchIndex = matchIndex;
                                     request.notify();
                                 }
+                            } else {
+                                nativeFindAll(mNativeClass, null);
                             }
+                            Message.obtain(mWebViewClassic.mPrivateHandler,
+                                    WebViewClassic.UPDATE_MATCH_COUNT, request).sendToTarget();
                             break;
                         }
-                        case FIND_NEXT:
-                            nativeFindNext(mNativeClass, msg.arg1 != 0);
+                        case FIND_NEXT: {
+                            FindAllRequest request = (FindAllRequest)msg.obj;
+                            int matchIndex = nativeFindNext(mNativeClass, msg.arg1 != 0);
+                            synchronized (request) {
+                                request.mMatchIndex = matchIndex;
+                            }
+                            Message.obtain(mWebViewClassic.mPrivateHandler,
+                                    WebViewClassic.UPDATE_MATCH_COUNT, request).sendToTarget();
                             break;
+                        }
                     }
                 }
             };
@@ -2825,17 +2838,6 @@
                 .sendToTarget();
     }
 
-    // called by JNI
-    private void updateMatchCount(int matchIndex, int matchCount,
-        String findText) {
-        if (mWebViewClassic == null) {
-            return;
-        }
-        Message.obtain(mWebViewClassic.mPrivateHandler,
-                WebViewClassic.UPDATE_MATCH_COUNT, matchIndex, matchCount,
-                findText).sendToTarget();
-    }
-
     private native void nativeRevealSelection(int nativeClass);
     private native String nativeRequestLabel(int nativeClass, int framePtr,
             int nodePtr);
@@ -3086,7 +3088,7 @@
     private native void nativeAutoFillForm(int nativeClass, int queryId);
     private native void nativeScrollLayer(int nativeClass, int layer, Rect rect);
     private native int nativeFindAll(int nativeClass, String text);
-    private native void nativeFindNext(int nativeClass, boolean forward);
+    private native int nativeFindNext(int nativeClass, boolean forward);
 
     /**
      * Deletes editable text between two points. Note that the selection may
diff --git a/core/java/android/widget/Chronometer.java b/core/java/android/widget/Chronometer.java
index 9c9eb4b..b7a126e 100644
--- a/core/java/android/widget/Chronometer.java
+++ b/core/java/android/widget/Chronometer.java
@@ -248,7 +248,6 @@
             }
         }
         setText(text);
-        Slog.v("Chronometer", "updateText: sec=" + seconds + " mFormat=" + mFormat + " text=" + text);
     }
 
     private void updateRunning() {
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index e00fe9f..af67d55 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -340,8 +340,12 @@
         final int childHeightMode = MeasureSpec.getMode(parentHeightMeasureSpec);
         final int childHeightSpec = MeasureSpec.makeMeasureSpec(childHeightSize, childHeightMode);
 
+        final ActionMenuItemView itemView = child instanceof ActionMenuItemView ?
+                (ActionMenuItemView) child : null;
+        final boolean hasText = itemView != null && itemView.hasText();
+
         int cellsUsed = 0;
-        if (cellsRemaining > 0) {
+        if (cellsRemaining > 0 && (!hasText || cellsRemaining >= 2)) {
             final int childWidthSpec = MeasureSpec.makeMeasureSpec(
                     cellSize * cellsRemaining, MeasureSpec.AT_MOST);
             child.measure(childWidthSpec, childHeightSpec);
@@ -349,11 +353,10 @@
             final int measuredWidth = child.getMeasuredWidth();
             cellsUsed = measuredWidth / cellSize;
             if (measuredWidth % cellSize != 0) cellsUsed++;
+            if (hasText && cellsUsed < 2) cellsUsed = 2;
         }
 
-        final ActionMenuItemView itemView = child instanceof ActionMenuItemView ?
-                (ActionMenuItemView) child : null;
-        final boolean expandable = !lp.isOverflowButton && itemView != null && itemView.hasText();
+        final boolean expandable = !lp.isOverflowButton && hasText;
         lp.expandable = expandable;
 
         lp.cellsUsed = cellsUsed;
diff --git a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
index 8521481..d1652df 100644
--- a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
+++ b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
@@ -18,14 +18,11 @@
 
 import com.android.internal.app.ActionBarImpl;
 
-import android.animation.LayoutTransition;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Rect;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.View;
-import android.view.ViewTreeObserver;
 import android.widget.FrameLayout;
 
 /**
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index 3d350ed..244b166 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -218,6 +218,18 @@
     return surfaceTexture->updateTexImage();
 }
 
+static jint SurfaceTexture_detachFromGLContext(JNIEnv* env, jobject thiz)
+{
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    return surfaceTexture->detachFromContext();
+}
+
+static jint SurfaceTexture_attachToGLContext(JNIEnv* env, jobject thiz, jint tex)
+{
+    sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+    return surfaceTexture->attachToContext((GLuint)tex);
+}
+
 static void SurfaceTexture_getTransformMatrix(JNIEnv* env, jobject thiz,
         jfloatArray jmtx)
 {
@@ -242,14 +254,16 @@
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gSurfaceTextureMethods[] = {
-    {"nativeClassInit",          "()V",   (void*)SurfaceTexture_classInit },
-    {"nativeInit",               "(ILjava/lang/Object;Z)V", (void*)SurfaceTexture_init },
-    {"nativeFinalize",           "()V",   (void*)SurfaceTexture_finalize },
+    {"nativeClassInit",            "()V",   (void*)SurfaceTexture_classInit },
+    {"nativeInit",                 "(ILjava/lang/Object;Z)V", (void*)SurfaceTexture_init },
+    {"nativeFinalize",             "()V",   (void*)SurfaceTexture_finalize },
     {"nativeSetDefaultBufferSize", "(II)V", (void*)SurfaceTexture_setDefaultBufferSize },
-    {"nativeUpdateTexImage",     "()I",   (void*)SurfaceTexture_updateTexImage },
-    {"nativeGetTransformMatrix", "([F)V", (void*)SurfaceTexture_getTransformMatrix },
-    {"nativeGetTimestamp",       "()J",   (void*)SurfaceTexture_getTimestamp },
-    {"nativeRelease",            "()V",   (void*)SurfaceTexture_release },
+    {"nativeUpdateTexImage",       "()I",   (void*)SurfaceTexture_updateTexImage },
+    {"nativeDetachFromGLContext",  "()I",   (void*)SurfaceTexture_detachFromGLContext },
+    {"nativeAttachToGLContext",    "(I)I",   (void*)SurfaceTexture_attachToGLContext },
+    {"nativeGetTransformMatrix",   "([F)V", (void*)SurfaceTexture_getTransformMatrix },
+    {"nativeGetTimestamp",         "()J",   (void*)SurfaceTexture_getTimestamp },
+    {"nativeRelease",              "()V",   (void*)SurfaceTexture_release },
 };
 
 int register_android_graphics_SurfaceTexture(JNIEnv* env)
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index 655a834..19bc154 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -416,8 +416,8 @@
         if (env != NULL && clazz != NULL) {
             env->DeleteGlobalRef(clazz);
         }
-        if (looper != NULL && mainWorkRead >= 0) {
-            looper->removeFd(mainWorkRead);
+        if (messageQueue != NULL && mainWorkRead >= 0) {
+            messageQueue->getLooper()->removeFd(mainWorkRead);
         }
         if (nativeInputQueue != NULL) {
             nativeInputQueue->mWorkWrite = -1;
@@ -481,7 +481,7 @@
     // These are used to wake up the main thread to process work.
     int mainWorkRead;
     int mainWorkWrite;
-    sp<Looper> looper;
+    sp<MessageQueue> messageQueue;
 };
 
 void android_NativeActivity_finish(ANativeActivity* activity) {
@@ -515,16 +515,6 @@
 
 // ------------------------------------------------------------------------
 
-static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
-   if (env->ExceptionCheck()) {
-       ALOGE("An exception was thrown by callback '%s'.", methodName);
-       LOGE_EX(env);
-       env->ExceptionClear();
-       return true;
-   }
-   return false;
-}
-
 /*
  * Callback for handling native events on the application's main thread.
  */
@@ -551,7 +541,8 @@
                 if (inputEventObj) {
                     handled = code->env->CallBooleanMethod(code->clazz,
                             gNativeActivityClassInfo.dispatchUnhandledKeyEvent, inputEventObj);
-                    checkAndClearExceptionFromCallback(code->env, "dispatchUnhandledKeyEvent");
+                    code->messageQueue->raiseAndClearException(
+                            code->env, "dispatchUnhandledKeyEvent");
                     code->env->DeleteLocalRef(inputEventObj);
                 } else {
                     ALOGE("Failed to obtain key event for dispatchUnhandledKeyEvent.");
@@ -566,7 +557,7 @@
                 if (inputEventObj) {
                     code->env->CallVoidMethod(code->clazz,
                             gNativeActivityClassInfo.preDispatchKeyEvent, inputEventObj, seq);
-                    checkAndClearExceptionFromCallback(code->env, "preDispatchKeyEvent");
+                    code->messageQueue->raiseAndClearException(code->env, "preDispatchKeyEvent");
                     code->env->DeleteLocalRef(inputEventObj);
                 } else {
                     ALOGE("Failed to obtain key event for preDispatchKeyEvent.");
@@ -575,27 +566,27 @@
         } break;
         case CMD_FINISH: {
             code->env->CallVoidMethod(code->clazz, gNativeActivityClassInfo.finish);
-            checkAndClearExceptionFromCallback(code->env, "finish");
+            code->messageQueue->raiseAndClearException(code->env, "finish");
         } break;
         case CMD_SET_WINDOW_FORMAT: {
             code->env->CallVoidMethod(code->clazz,
                     gNativeActivityClassInfo.setWindowFormat, work.arg1);
-            checkAndClearExceptionFromCallback(code->env, "setWindowFormat");
+            code->messageQueue->raiseAndClearException(code->env, "setWindowFormat");
         } break;
         case CMD_SET_WINDOW_FLAGS: {
             code->env->CallVoidMethod(code->clazz,
                     gNativeActivityClassInfo.setWindowFlags, work.arg1, work.arg2);
-            checkAndClearExceptionFromCallback(code->env, "setWindowFlags");
+            code->messageQueue->raiseAndClearException(code->env, "setWindowFlags");
         } break;
         case CMD_SHOW_SOFT_INPUT: {
             code->env->CallVoidMethod(code->clazz,
                     gNativeActivityClassInfo.showIme, work.arg1);
-            checkAndClearExceptionFromCallback(code->env, "showIme");
+            code->messageQueue->raiseAndClearException(code->env, "showIme");
         } break;
         case CMD_HIDE_SOFT_INPUT: {
             code->env->CallVoidMethod(code->clazz,
                     gNativeActivityClassInfo.hideIme, work.arg1);
-            checkAndClearExceptionFromCallback(code->env, "hideIme");
+            code->messageQueue->raiseAndClearException(code->env, "hideIme");
         } break;
         default:
             ALOGW("Unknown work command: %d", work.cmd);
@@ -634,9 +625,9 @@
             return 0;
         }
         
-        code->looper = android_os_MessageQueue_getLooper(env, messageQueue);
-        if (code->looper == NULL) {
-            ALOGW("Unable to retrieve MessageQueue's Looper");
+        code->messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueue);
+        if (code->messageQueue == NULL) {
+            ALOGW("Unable to retrieve native MessageQueue");
             delete code;
             return 0;
         }
@@ -655,7 +646,8 @@
         result = fcntl(code->mainWorkWrite, F_SETFL, O_NONBLOCK);
         SLOGW_IF(result != 0, "Could not make main work write pipe "
                 "non-blocking: %s", strerror(errno));
-        code->looper->addFd(code->mainWorkRead, 0, ALOOPER_EVENT_INPUT, mainWorkCallback, code);
+        code->messageQueue->getLooper()->addFd(
+                code->mainWorkRead, 0, ALOOPER_EVENT_INPUT, mainWorkCallback, code);
         
         code->ANativeActivity::callbacks = &code->callbacks;
         if (env->GetJavaVM(&code->vm) < 0) {
diff --git a/core/jni/android_os_MessageQueue.cpp b/core/jni/android_os_MessageQueue.cpp
index 12a77d5..a4dcac6 100644
--- a/core/jni/android_os_MessageQueue.cpp
+++ b/core/jni/android_os_MessageQueue.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "MessageQueue-JNI"
 
 #include "JNIHelp.h"
+#include <android_runtime/AndroidRuntime.h>
 
 #include <utils/Looper.h>
 #include <utils/Log.h>
@@ -24,31 +25,46 @@
 
 namespace android {
 
-// ----------------------------------------------------------------------------
-
 static struct {
     jfieldID mPtr;   // native object attached to the DVM MessageQueue
 } gMessageQueueClassInfo;
 
-// ----------------------------------------------------------------------------
 
-class NativeMessageQueue {
+class NativeMessageQueue : public MessageQueue {
 public:
     NativeMessageQueue();
-    ~NativeMessageQueue();
+    virtual ~NativeMessageQueue();
 
-    inline sp<Looper> getLooper() { return mLooper; }
+    virtual void raiseException(JNIEnv* env, const char* msg, jthrowable exceptionObj);
 
-    void pollOnce(int timeoutMillis);
+    void pollOnce(JNIEnv* env, int timeoutMillis);
+
     void wake();
 
 private:
-    sp<Looper> mLooper;
+    bool mInCallback;
+    jthrowable mExceptionObj;
 };
 
-// ----------------------------------------------------------------------------
 
-NativeMessageQueue::NativeMessageQueue() {
+MessageQueue::MessageQueue() {
+}
+
+MessageQueue::~MessageQueue() {
+}
+
+bool MessageQueue::raiseAndClearException(JNIEnv* env, const char* msg) {
+    jthrowable exceptionObj = env->ExceptionOccurred();
+    if (exceptionObj) {
+        env->ExceptionClear();
+        raiseException(env, msg, exceptionObj);
+        env->DeleteLocalRef(exceptionObj);
+        return true;
+    }
+    return false;
+}
+
+NativeMessageQueue::NativeMessageQueue() : mInCallback(false), mExceptionObj(NULL) {
     mLooper = Looper::getForThread();
     if (mLooper == NULL) {
         mLooper = new Looper(false);
@@ -59,8 +75,32 @@
 NativeMessageQueue::~NativeMessageQueue() {
 }
 
-void NativeMessageQueue::pollOnce(int timeoutMillis) {
+void NativeMessageQueue::raiseException(JNIEnv* env, const char* msg, jthrowable exceptionObj) {
+    if (exceptionObj) {
+        if (mInCallback) {
+            if (mExceptionObj) {
+                env->DeleteLocalRef(mExceptionObj);
+            }
+            mExceptionObj = jthrowable(env->NewLocalRef(exceptionObj));
+            ALOGE("Exception in MessageQueue callback: %s", msg);
+            jniLogException(env, ANDROID_LOG_ERROR, LOG_TAG, exceptionObj);
+        } else {
+            ALOGE("Exception: %s", msg);
+            jniLogException(env, ANDROID_LOG_ERROR, LOG_TAG, exceptionObj);
+            LOG_ALWAYS_FATAL("raiseException() was called when not in a callback, exiting.");
+        }
+    }
+}
+
+void NativeMessageQueue::pollOnce(JNIEnv* env, int timeoutMillis) {
+    mInCallback = true;
     mLooper->pollOnce(timeoutMillis);
+    mInCallback = false;
+    if (mExceptionObj) {
+        env->Throw(mExceptionObj);
+        env->DeleteLocalRef(mExceptionObj);
+        mExceptionObj = NULL;
+    }
 }
 
 void NativeMessageQueue::wake() {
@@ -81,19 +121,20 @@
              reinterpret_cast<jint>(nativeMessageQueue));
 }
 
-sp<Looper> android_os_MessageQueue_getLooper(JNIEnv* env, jobject messageQueueObj) {
+sp<MessageQueue> android_os_MessageQueue_getMessageQueue(JNIEnv* env, jobject messageQueueObj) {
     NativeMessageQueue* nativeMessageQueue =
             android_os_MessageQueue_getNativeMessageQueue(env, messageQueueObj);
-    return nativeMessageQueue != NULL ? nativeMessageQueue->getLooper() : NULL;
+    return nativeMessageQueue;
 }
 
 static void android_os_MessageQueue_nativeInit(JNIEnv* env, jobject obj) {
     NativeMessageQueue* nativeMessageQueue = new NativeMessageQueue();
-    if (! nativeMessageQueue) {
+    if (!nativeMessageQueue) {
         jniThrowRuntimeException(env, "Unable to allocate native queue");
         return;
     }
 
+    nativeMessageQueue->incStrong(env);
     android_os_MessageQueue_setNativeMessageQueue(env, obj, nativeMessageQueue);
 }
 
@@ -102,7 +143,7 @@
             android_os_MessageQueue_getNativeMessageQueue(env, obj);
     if (nativeMessageQueue) {
         android_os_MessageQueue_setNativeMessageQueue(env, obj, NULL);
-        delete nativeMessageQueue;
+        nativeMessageQueue->decStrong(env);
     }
 }
 
@@ -113,7 +154,7 @@
 static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
         jint ptr, jint timeoutMillis) {
     NativeMessageQueue* nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
-    nativeMessageQueue->pollOnce(timeoutMillis);
+    nativeMessageQueue->pollOnce(env, timeoutMillis);
 }
 
 static void android_os_MessageQueue_nativeWake(JNIEnv* env, jobject obj, jint ptr) {
diff --git a/core/jni/android_os_MessageQueue.h b/core/jni/android_os_MessageQueue.h
index f961d8f..49d2aa0 100644
--- a/core/jni/android_os_MessageQueue.h
+++ b/core/jni/android_os_MessageQueue.h
@@ -18,12 +18,53 @@
 #define _ANDROID_OS_MESSAGEQUEUE_H
 
 #include "jni.h"
+#include <utils/Looper.h>
 
 namespace android {
 
-class Looper;
+class MessageQueue : public RefBase {
+public:
+    /* Gets the message queue's looper. */
+    inline sp<Looper> getLooper() const {
+        return mLooper;
+    }
 
-extern sp<Looper> android_os_MessageQueue_getLooper(JNIEnv* env, jobject messageQueueObj);
+    /* Checks whether the JNI environment has a pending exception.
+     *
+     * If an exception occurred, logs it together with the specified message,
+     * and calls raiseException() to ensure the exception will be raised when
+     * the callback returns, clears the pending exception from the environment,
+     * then returns true.
+     *
+     * If no exception occurred, returns false.
+     */
+    bool raiseAndClearException(JNIEnv* env, const char* msg);
+
+    /* Raises an exception from within a callback function.
+     * The exception will be rethrown when control returns to the message queue which
+     * will typically cause the application to crash.
+     *
+     * This message can only be called from within a callback function.  If it is called
+     * at any other time, the process will simply be killed.
+     *
+     * Does nothing if exception is NULL.
+     *
+     * (This method does not take ownership of the exception object reference.
+     * The caller is responsible for releasing its reference when it is done.)
+     */
+    virtual void raiseException(JNIEnv* env, const char* msg, jthrowable exceptionObj) = 0;
+
+protected:
+    MessageQueue();
+    virtual ~MessageQueue();
+
+protected:
+    sp<Looper> mLooper;
+};
+
+/* Gets the native object associated with a MessageQueue. */
+extern sp<MessageQueue> android_os_MessageQueue_getMessageQueue(
+        JNIEnv* env, jobject messageQueueObj);
 
 } // namespace android
 
diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp
index 72c171c..d80bfb3 100644
--- a/core/jni/android_view_DisplayEventReceiver.cpp
+++ b/core/jni/android_view_DisplayEventReceiver.cpp
@@ -45,7 +45,7 @@
 class NativeDisplayEventReceiver : public RefBase {
 public:
     NativeDisplayEventReceiver(JNIEnv* env,
-            jobject receiverObj, const sp<Looper>& looper);
+            jobject receiverObj, const sp<MessageQueue>& messageQueue);
 
     status_t initialize();
     status_t scheduleVsync();
@@ -55,7 +55,7 @@
 
 private:
     jobject mReceiverObjGlobal;
-    sp<Looper> mLooper;
+    sp<MessageQueue> mMessageQueue;
     DisplayEventReceiver mReceiver;
     bool mWaitingForVsync;
 
@@ -65,9 +65,9 @@
 
 
 NativeDisplayEventReceiver::NativeDisplayEventReceiver(JNIEnv* env,
-        jobject receiverObj, const sp<Looper>& looper) :
+        jobject receiverObj, const sp<MessageQueue>& messageQueue) :
         mReceiverObjGlobal(env->NewGlobalRef(receiverObj)),
-        mLooper(looper), mWaitingForVsync(false) {
+        mMessageQueue(messageQueue), mWaitingForVsync(false) {
     ALOGV("receiver %p ~ Initializing input event receiver.", this);
 }
 
@@ -75,7 +75,7 @@
     ALOGV("receiver %p ~ Disposing display event receiver.", this);
 
     if (!mReceiver.initCheck()) {
-        mLooper->removeFd(mReceiver.getFd());
+        mMessageQueue->getLooper()->removeFd(mReceiver.getFd());
     }
 
     JNIEnv* env = AndroidRuntime::getJNIEnv();
@@ -89,7 +89,7 @@
         return result;
     }
 
-    int rc = mLooper->addFd(mReceiver.getFd(), 0, ALOOPER_EVENT_INPUT,
+    int rc = mMessageQueue->getLooper()->addFd(mReceiver.getFd(), 0, ALOOPER_EVENT_INPUT,
             handleReceiveCallback, this);
     if (rc < 0) {
         return UNKNOWN_ERROR;
@@ -151,12 +151,7 @@
             gDisplayEventReceiverClassInfo.dispatchVsync, vsyncTimestamp, vsyncCount);
     ALOGV("receiver %p ~ Returned from vsync handler.", data);
 
-    if (env->ExceptionCheck()) {
-        ALOGE("An exception occurred while dispatching a vsync event.");
-        LOGE_EX(env);
-        env->ExceptionClear();
-    }
-
+    r->mMessageQueue->raiseAndClearException(env, "dispatchVsync");
     return 1; // keep the callback
 }
 
@@ -183,14 +178,14 @@
 
 static jint nativeInit(JNIEnv* env, jclass clazz, jobject receiverObj,
         jobject messageQueueObj) {
-    sp<Looper> looper = android_os_MessageQueue_getLooper(env, messageQueueObj);
-    if (looper == NULL) {
+    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
+    if (messageQueue == NULL) {
         jniThrowRuntimeException(env, "MessageQueue is not initialized.");
         return 0;
     }
 
     sp<NativeDisplayEventReceiver> receiver = new NativeDisplayEventReceiver(env,
-            receiverObj, looper);
+            receiverObj, messageQueue);
     status_t status = receiver->initialize();
     if (status) {
         String8 message;
diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp
index e7d4244..348437d 100644
--- a/core/jni/android_view_InputEventReceiver.cpp
+++ b/core/jni/android_view_InputEventReceiver.cpp
@@ -48,7 +48,7 @@
 public:
     NativeInputEventReceiver(JNIEnv* env,
             jobject receiverObj, const sp<InputChannel>& inputChannel,
-            const sp<Looper>& looper);
+            const sp<MessageQueue>& messageQueue);
 
     status_t initialize();
     status_t finishInputEvent(uint32_t seq, bool handled);
@@ -61,7 +61,7 @@
 private:
     jobject mReceiverObjGlobal;
     InputConsumer mInputConsumer;
-    sp<Looper> mLooper;
+    sp<MessageQueue> mMessageQueue;
     PreallocatedInputEventFactory mInputEventFactory;
     bool mBatchedInputEventPending;
 
@@ -72,9 +72,10 @@
 
 
 NativeInputEventReceiver::NativeInputEventReceiver(JNIEnv* env,
-        jobject receiverObj, const sp<InputChannel>& inputChannel, const sp<Looper>& looper) :
+        jobject receiverObj, const sp<InputChannel>& inputChannel,
+        const sp<MessageQueue>& messageQueue) :
         mReceiverObjGlobal(env->NewGlobalRef(receiverObj)),
-        mInputConsumer(inputChannel), mLooper(looper),
+        mInputConsumer(inputChannel), mMessageQueue(messageQueue),
         mBatchedInputEventPending(false) {
 #if DEBUG_DISPATCH_CYCLE
     ALOGD("channel '%s' ~ Initializing input event receiver.", getInputChannelName());
@@ -86,7 +87,7 @@
     ALOGD("channel '%s' ~ Disposing input event receiver.", getInputChannelName());
 #endif
 
-    mLooper->removeFd(mInputConsumer.getChannel()->getFd());
+    mMessageQueue->getLooper()->removeFd(mInputConsumer.getChannel()->getFd());
 
     JNIEnv* env = AndroidRuntime::getJNIEnv();
     env->DeleteGlobalRef(mReceiverObjGlobal);
@@ -94,7 +95,8 @@
 
 status_t NativeInputEventReceiver::initialize() {
     int receiveFd = mInputConsumer.getChannel()->getFd();
-    mLooper->addFd(receiveFd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
+    mMessageQueue->getLooper()->addFd(
+            receiveFd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
     return OK;
 }
 
@@ -157,12 +159,8 @@
 #endif
                     env->CallVoidMethod(mReceiverObjGlobal,
                             gInputEventReceiverClassInfo.dispatchBatchedInputEventPending);
-
-                    if (env->ExceptionCheck()) {
-                        ALOGE("channel '%s' ~ An exception occurred while dispatching that "
-                                "batched input events are pending.", getInputChannelName());
-                        LOGE_EX(env);
-                        env->ExceptionClear();
+                    if (mMessageQueue->raiseAndClearException(
+                            env, "dispatchBatchedInputEventPending")) {
                         mBatchedInputEventPending = false; // try again later
                     }
                 }
@@ -182,6 +180,7 @@
 #endif
             inputEventObj = android_view_KeyEvent_fromNative(env,
                     static_cast<KeyEvent*>(inputEvent));
+            mMessageQueue->raiseAndClearException(env, "new KeyEvent");
             break;
 
         case AINPUT_EVENT_TYPE_MOTION:
@@ -190,6 +189,7 @@
 #endif
             inputEventObj = android_view_MotionEvent_obtainAsCopy(env,
                     static_cast<MotionEvent*>(inputEvent));
+            mMessageQueue->raiseAndClearException(env, "new MotionEvent");
             break;
 
         default:
@@ -200,7 +200,7 @@
         if (!inputEventObj) {
             ALOGW("channel '%s' ~ Failed to obtain event object.", getInputChannelName());
             mInputConsumer.sendFinishedSignal(seq, false);
-            return NO_MEMORY;
+            continue;
         }
 
 #if DEBUG_DISPATCH_CYCLE
@@ -211,14 +211,8 @@
 
         env->DeleteLocalRef(inputEventObj);
 
-        if (env->ExceptionCheck()) {
-            ALOGE("channel '%s' ~ An exception occurred while dispatching an event.",
-                    getInputChannelName());
-            LOGE_EX(env);
-            env->ExceptionClear();
-
+        if (mMessageQueue->raiseAndClearException(env, "dispatchInputEvent")) {
             mInputConsumer.sendFinishedSignal(seq, false);
-            return OK;
         }
     }
 }
@@ -233,14 +227,14 @@
         return 0;
     }
 
-    sp<Looper> looper = android_os_MessageQueue_getLooper(env, messageQueueObj);
-    if (looper == NULL) {
+    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
+    if (messageQueue == NULL) {
         jniThrowRuntimeException(env, "MessageQueue is not initialized.");
         return 0;
     }
 
     sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
-            receiverObj, inputChannel, looper);
+            receiverObj, inputChannel, messageQueue);
     status_t status = receiver->initialize();
     if (status) {
         String8 message;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 5ae12b6..00faa41 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1200,7 +1200,8 @@
         android:protectionLevel="signature|system" />
 
     <!-- Allows an application to retrieve the current state of keys and
-         switches.  This is only for use by the system.-->
+         switches.  This is only for use by the system.
+         @deprecated The API that used this permission has been removed. -->
     <permission android:name="android.permission.READ_INPUT_STATE"
         android:label="@string/permlab_readInputState"
         android:description="@string/permdesc_readInputState"
diff --git a/core/res/res/layout/action_mode_close_item.xml b/core/res/res/layout/action_mode_close_item.xml
index ac5af70..8cd0cdd 100644
--- a/core/res/res/layout/action_mode_close_item.xml
+++ b/core/res/res/layout/action_mode_close_item.xml
@@ -19,6 +19,7 @@
         android:focusable="true"
         android:clickable="true"
         android:paddingLeft="8dip"
+        android:contentDescription="@string/action_mode_done"
         style="?android:attr/actionModeCloseButtonStyle"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
diff --git a/core/res/res/layout/notification_action.xml b/core/res/res/layout/notification_action.xml
index 54fde70..785da7c 100644
--- a/core/res/res/layout/notification_action.xml
+++ b/core/res/res/layout/notification_action.xml
@@ -19,5 +19,5 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     style="@android:style/Widget.Holo.Button.Small"
-    android:gravity="left"
+    android:gravity="left|center_vertical"
     />
\ No newline at end of file
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index d6073e3..f23c7e2 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1019,8 +1019,7 @@
     <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="date_time_done" msgid="2507683751759308828">"Klaar"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Vermeerder"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Verminder"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> raak en hou."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Gly op om te vermeeder en af om te verminder."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Vermeerder minuut"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Verminder minute"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Vermeerder uur"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Verminder uur"</string>
     <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>
-    <!-- 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="date_picker_increment_month_button" msgid="5369998479067934110">"Vermeerder maand"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Verminder maand"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Vermeerder dag"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Verminder dag"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Vermeerder jaar"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Verminder jaar"</string>
     <string name="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>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"Gly op vir <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"Gly af vir <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"Gly links vir <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"Gly regs vir <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <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>
     <string name="description_target_soundon" msgid="30052466675500172">"Klank aan"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Soek"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Sleep om te ontsluit."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Prop \'n kopfoon in om te hoor hoe wagwoordsleutels hardop gesê word."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punt."</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 2b98607..b0218dd 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1019,8 +1019,7 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"ጊዜ አዘጋጅ"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"ውሂብ አዘጋጅ"</string>
     <string name="date_time_set" msgid="5777075614321087758">"አዘጋጅ"</string>
-    <!-- no translation found for date_time_done (2507683751759308828) -->
-    <skip />
+    <string name="date_time_done" msgid="2507683751759308828">"ተጠናቋል"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"ጨምር"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"ቀንስ"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> ንካ እና ያዝ።"</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"ለመጨመር ወደ ላይ አንሸራትት እና ለመቀነስ ወደ ታች አንሸራትት።"</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"ደቂቃ ጨምር"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"ደቂቃ ቀንስ"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"ሰዓት ጨምር"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"ሰዓት ቀንስ"</string>
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"PM አዘጋጅ"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"AM አዘጋጅ"</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="date_picker_increment_month_button" msgid="5369998479067934110">"ወር ጨምር"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"ወር ቀንስ"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"ቀን ጨምር"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"ቀን ቀንስ"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"ዓመት ጨምር"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"ዓመት ቀንስ"</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"ታይቷል"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"አልተፈተሸም"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"የተመረጠ"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"ለ<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ወደ ላይ አንሸራትት።"</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"ለ<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ወደ ታች አንሸራትት።"</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"ለ<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ወደ ግራ አንሸራትት።"</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"ለ<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ወደ ቀኝ አንሸራትት።"</string>
     <string name="description_target_unlock" msgid="2228524900439801453">"ክፈት"</string>
     <string name="description_target_camera" msgid="969071997552486814">"ካሜራ"</string>
     <string name="description_target_silent" msgid="893551287746522182">"ፀጥታ"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"ድምፅ አብራ"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"ፈልግ"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"ላለመቆለፍ አንሸራት፡፡"</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"የይለፍ ቃል ቁልፎች  ሲነገሩ ለመስማት የጆሮ ማዳመጫ ሰካ።"</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"ነጥብ."</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 9c3ef5e..9c3d658 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1019,8 +1019,7 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"تعيين الوقت"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"تعيين التاريخ"</string>
     <string name="date_time_set" msgid="5777075614321087758">"تعيين"</string>
-    <!-- no translation found for date_time_done (2507683751759308828) -->
-    <skip />
+    <string name="date_time_done" msgid="2507683751759308828">"تم"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"زيادة"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"تقليل"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> المس مع الاستمرار."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"مرر لأعلى للزيادة ولأسفل للتقليل."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"زيادة الدقائق"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"تقليل الدقائق"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"زيادة الساعات"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"تقليل الساعات"</string>
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"تعيين المساء"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"تعيين الصباح"</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="date_picker_increment_month_button" msgid="5369998479067934110">"زيادة الشهور"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"تقليل الشهور"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"زيادة الأيام"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"تقليل الأيام"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"زيادة الأعوام"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"تقليل الأعوام"</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"تم التحديد"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"لم يتم التحديد"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"محدد"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"تمرير لأعلى لـ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"تمرير لأسفل لـ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"تمرير لليسار لـ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"تمرير لليمين لـ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_target_unlock" msgid="2228524900439801453">"إلغاء تأمين"</string>
     <string name="description_target_camera" msgid="969071997552486814">"الكاميرا"</string>
     <string name="description_target_silent" msgid="893551287746522182">"صامت"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"تشغيل الصوت"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"بحث"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"مرر بسرعة لإلغاء التأمين."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"يمكنك توصيل سماعة رأس لسماع مفاتيح كلمة المرور عندما يتم نطقها."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"نقطة"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index dcb8f05..9aab752 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -1019,8 +1019,7 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Усталяваць час"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Усталяваць дату"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Задаць"</string>
-    <!-- no translation found for date_time_done (2507683751759308828) -->
-    <skip />
+    <string name="date_time_done" msgid="2507683751759308828">"Гатова"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Павялічыць"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Паменшыць"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Націсніце і ўтрымлівайце <xliff:g id="VALUE">%s</xliff:g>."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Правядзіце пальцам уверх, каб павялічыць, або ўніз, каб паменшыць."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Павялічыць лічбу хвілін."</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Паменшыць лічбу хвілін."</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Павялічыць лічбу гадзін."</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Паменшыць лічбу гадзін."</string>
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Усталяваць час пасля паўдня"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Усталяваць час да паўдня"</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="date_picker_increment_month_button" msgid="5369998479067934110">"Павялічыць лічбу месяца"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Паменшыць лічбу месяца"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Павялічыць лічбу дня"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Паменшыць лічбу дня"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Павялічыць лічбу года"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Паменшыць лічбу года"</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"пастаўлены"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"не пастаўлены"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"абрана"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"Правядзіце пальцам уверх, каб атрымаць <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"Правядзіце пальцам уніз, каб атрымаць <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"Правядзіце пальцам улева, каб атрымаць <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"Правядзіце пальцам управа, каб атрымаць <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_target_unlock" msgid="2228524900439801453">"Разблакаваць"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Камера"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Ціхі рэжым"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Гук уключаны"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Пошук"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Прагартайце, каб разблакаваць."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Каб праслухаць паролi, падключыце гарнiтуру."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Кропка."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index cee54b4..81a75bd 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1230,6 +1230,8 @@
     <string name="description_target_camera" msgid="969071997552486814">"Камера"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Тих режим"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Включване на звука"</string>
+    <!-- no translation found for description_target_search (3091587249776033139) -->
+    <skip />
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Прокарайте пръст, за да отключите."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Включете слушалки, за да чуете изговарянето на клавишите за паролата."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Точка."</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index e360af1..6c6030c 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1019,8 +1019,7 @@
     <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="date_time_done" msgid="2507683751759308828">"Fet"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Incrementa"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Redueix"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Mantén premut <xliff:g id="VALUE">%s</xliff:g>."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Fes lliscar el dit cap amunt per incrementar i cap avall per disminuir."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Fes augmentar el minut"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Fes disminuir el minut"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Fes augmentar l\'hora"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Fes disminuir l\'hora"</string>
     <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>
-    <!-- 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="date_picker_increment_month_button" msgid="5369998479067934110">"Fes augmentar el mes"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Fes disminuir el mes"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Fes augmentar el dia"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Fes disminuir el dia"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Fes augmentar l\'any"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Fes disminuir l\'any"</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"marcat"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"no marcat"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"seleccionat"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"Fes lliscar el dit cap amunt per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"Fes lliscar el dit cap avall per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"Fes lliscar el dit cap a l\'esquerra per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"Fes lliscar el dit cap a la dreta per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <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>
     <string name="description_target_soundon" msgid="30052466675500172">"Activa el so"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Cerca"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Llisca el dit per desbloquejar."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Connecta un auricular per escoltar les claus de la contrasenya en veu alta."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punt."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index ea206b0..d95feaa 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1230,6 +1230,8 @@
     <string name="description_target_camera" msgid="969071997552486814">"Fotoaparát"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Tichý"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Zapnout zvuk"</string>
+    <!-- no translation found for description_target_search (3091587249776033139) -->
+    <skip />
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Odemknete posunutím prstu."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Chcete-li slyšet, které klávesy jste při zadávání hesla stiskli, připojte sluchátka."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Tečka."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 94c2999..2c7f1306 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1019,8 +1019,7 @@
     <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="date_time_done" msgid="2507683751759308828">"Udført"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Højere"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Lavere"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Tryk <xliff:g id="VALUE">%s</xliff:g> gange, og hold inde."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Glid op for at øge og ned for at mindske."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Forøg minuttal"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Sænk minuttal"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Forøg timetal"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Sænk timetal"</string>
     <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>
-    <!-- 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="date_picker_increment_month_button" msgid="5369998479067934110">"Senere måned"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Tidligere måned"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Senere dag"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Tidligere dag"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Senere år"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Tidligere år"</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"markeret"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"ikke markeret"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"udvalgt"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"Glid op for at <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"Glid ned for at <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"Glid til venstre for at <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"Glid til højre for at <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <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>
     <string name="description_target_soundon" msgid="30052466675500172">"Lyd slået til"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Søgning"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Glid hurtigt henover for at låse op."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Tilslut et headset for at høre tasterne blive læst højt ved angivelse af adgangskode."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punktum."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 82a60d2..aa44b87 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1019,8 +1019,7 @@
     <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="date_time_done" msgid="2507683751759308828">"Fertig"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Erhöhen"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Verringern"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> berühren und gedrückt halten"</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Zum Erhöhen nach oben und zum Verringern nach unten schieben"</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Minuten verlängern"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Minuten verringern"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Stunden verlängern"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Stunden verringern"</string>
     <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>
-    <!-- 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="date_picker_increment_month_button" msgid="5369998479067934110">"Monat verlängern"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Monat verringern"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Tag verlängern"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Tag verringern"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Jahr verlängern"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Jahr verringern"</string>
     <string name="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>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"Zum <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> nach oben schieben"</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"Zum <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> nach unten schieben"</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"Zum <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> nach links schieben"</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"Zum <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> nach rechts schieben"</string>
     <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>
     <string name="description_target_soundon" msgid="30052466675500172">"Ton ein"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Suche"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Zum Entsperren den Finger über den Bildschirm ziehen"</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Schließen Sie ein Headset an, um das Passwort gesprochen zu hören."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punkt."</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index b9710e5..d85d639 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1019,8 +1019,7 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Ρύθμιση ώρας"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Ορισμός ημερομηνίας"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Ορισμός"</string>
-    <!-- no translation found for date_time_done (2507683751759308828) -->
-    <skip />
+    <string name="date_time_done" msgid="2507683751759308828">"Τέλος"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Αύξηση"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Μείωση"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Πατήστε παρατεταμένα το <xliff:g id="VALUE">%s</xliff:g>."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Πραγματοποιήστε κύλιση προς τα πάνω για αύξηση και προς τα κάτω για μείωση."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Αύξηση λεπτού"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Μείωση λεπτού"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Αύξηση ώρας"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Μείωση ώρας"</string>
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Ορισμός ΜΜ"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Ορισμός ΠΜ"</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="date_picker_increment_month_button" msgid="5369998479067934110">"Αύξηση μήνα"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Μείωση μήνα"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Αύξηση ημέρας"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Μείωση ημέρας"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Αύξηση έτους"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Μείωση έτους"</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"ελέγχθηκε"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"δεν επιλέχθηκε"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"επιλεγμένο"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"Κύλιση προς τα επάνω για <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"Κύλιση προς τα κάτω για <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"Κύλιση προς τα αριστερά για <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"Κύλιση προς τα δεξιά για <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_target_unlock" msgid="2228524900439801453">"Ξεκλείδωμα"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Φωτογραφική μηχανή"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Αθόρυβο"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Ενεργοποίηση ήχου"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Αναζήτηση"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Σύρετε για ξεκλείδωμα."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Συνδέστε ακουστικά για να ακούσετε τα πλήκτρα του κωδικού πρόσβασης να εκφωνούνται."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Τελεία."</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index c41f2be..fa767ff 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1230,6 +1230,8 @@
     <string name="description_target_camera" msgid="969071997552486814">"Camera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Silent"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Sound on"</string>
+    <!-- no translation found for description_target_search (3091587249776033139) -->
+    <skip />
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Swipe to unlock."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Plug in a headset to hear password keys spoken."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Dot"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 19e8e25..5c7b782 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1230,6 +1230,8 @@
     <string name="description_target_camera" msgid="969071997552486814">"Cámara"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Silencioso"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Sonido activado"</string>
+    <!-- no translation found for description_target_search (3091587249776033139) -->
+    <skip />
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Desliza el dedo para desbloquear."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Conecta un auricular para escuchar las contraseñas."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punto"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index c732ab9..8ade0e0 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1019,8 +1019,7 @@
     <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="date_time_done" msgid="2507683751759308828">"Listo"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Aumentar"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Reducir"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Mantén pulsado <xliff:g id="VALUE">%s</xliff:g>."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Desliza el dedo hacia arriba para aumentar y hacia abajo para disminuir."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Aumentar minutos"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Reducir minutos"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Aumentar horas"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Reducir horas"</string>
     <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>
-    <!-- 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="date_picker_increment_month_button" msgid="5369998479067934110">"Aumentar mes"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Reducir mes"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Aumentar días"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Reducir días"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Aumentar año"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Reducir año"</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"seleccionado"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"no seleccionado"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"seleccionado"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"Desliza el dedo hacia arriba para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"Desliza el dedo hacia abajo para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"Desliza el dedo hacia la izquierda para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"Desliza el dedo hacia la derecha para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <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>
     <string name="description_target_soundon" msgid="30052466675500172">"Sonido activado"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Buscar"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Desliza el dedo para desbloquear."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Conecta un auricular para escuchar las contraseñas."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punto"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 890dd7b..0a8faed 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -1019,8 +1019,7 @@
     <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="date_time_done" msgid="2507683751759308828">"Valmis"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Suurendamine"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Vähendamine"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> puudutage ja hoidke."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Suurendamiseks lohistage üles, vähendamiseks alla."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Minutite suurendamine"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Minutite vähendamine"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Tundide suurendamine"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Tundide vähendamine"</string>
     <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>
-    <!-- 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="date_picker_increment_month_button" msgid="5369998479067934110">"Kuu suurendamine"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Kuu vähendamine"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Päeva suurendamine"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Päeva vähendamine"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Aasta suurendamine"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Aasta vähendamine"</string>
     <string name="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>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"Lohistage üles: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"Lohistage alla: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"Lohistage vasakule: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"Lohistage paremale: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <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>
     <string name="description_target_soundon" msgid="30052466675500172">"Heli on sees"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Otsing"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Avamiseks tõmmake sõrmega."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Paroolide kuulamiseks ühendage peakomplekt."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punkt."</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index ce26f1e..c9329bb 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1019,8 +1019,7 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"تنظیم زمان"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"تاریخ تنظیم"</string>
     <string name="date_time_set" msgid="5777075614321087758">"تنظیم"</string>
-    <!-- no translation found for date_time_done (2507683751759308828) -->
-    <skip />
+    <string name="date_time_done" msgid="2507683751759308828">"انجام شد"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"افزایش"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"کاهش"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> لمس کرده و نگه دارید."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"برای افزایش به بالا بلغزانید و برای کاهش به پایین بلغزانید."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"افزایش دقیقه"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"کاهش دقیقه"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"افزایش ساعت"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"کاهش ساعت"</string>
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"تنظیم ب.ظ"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"تنظیم ق.ظ"</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="date_picker_increment_month_button" msgid="5369998479067934110">"افزایش ماه"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"کاهش ماه"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"افزایش روز"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"کاهش روز"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"افزایش سال"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"کاهش سال"</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"علامت زده"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"بدون علامت"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"انتخاب شد"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"لغزاندن به بالا برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"لغزاندن به پایین برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"لغزاندن به چپ برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"لغزاندن به راست برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_target_unlock" msgid="2228524900439801453">"بازکردن قفل"</string>
     <string name="description_target_camera" msgid="969071997552486814">"دوربین"</string>
     <string name="description_target_silent" msgid="893551287746522182">"ساکت"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"صدا روشن"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"جستجو"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"برای بازگشایی قفل، بلغزانید."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"برای شنیدن کلیدهای گذرواژه که با صدای بلند خوانده می‌شوند، هدست را وصل کنید."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"نقطه."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 54e1a1b..8a1079b 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1019,8 +1019,7 @@
     <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="date_time_done" msgid="2507683751759308828">"Valmis"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Lisää"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Vähennä"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> kosketa pitkää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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Lisää tai vähennä arvoa liu\'uttamalla ylös tai alas."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Lisää minuuttien määrää."</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Vähennä minuuttien määrää."</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Lisää tuntien määrää."</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Vähennä tuntien määrää."</string>
     <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>
-    <!-- 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="date_picker_increment_month_button" msgid="5369998479067934110">"Lisää kuukausien määrää."</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Vähennä kuukausien määrää."</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Lisää päivien määrää."</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Vähennä päivien määrää."</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Lisää vuosien määrää."</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Vähennä vuosien määrää."</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"valittu"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"ei valittu"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"valittu"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"Liu\'uta ylös ja <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"Liu\'uta alas ja <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"Liu\'uta vasemmalle ja <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"Liu\'uta oikealle ja <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <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>
     <string name="description_target_soundon" msgid="30052466675500172">"Ääni käytössä"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Haku"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Poista lukitus liu\'uttamalla."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Liitä kuulokkeet kuullaksesi, mitä näppäimiä painat kirjoittaessasi salasanaa."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Piste."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index d4a6f5b..f05e564c 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1019,8 +1019,7 @@
     <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="date_time_done" msgid="2507683751759308828">"OK"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Augmenter"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Diminuer"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> appuyez de manière prolongée."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Faites glisser vers le haut pour augmenter et vers le bas pour diminuer."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Minute suivante"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Minute précédente"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Heure suivante"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Heure précédente"</string>
     <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>
-    <!-- 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="date_picker_increment_month_button" msgid="5369998479067934110">"Mois suivant"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Mois précédent"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Jour suivant"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Jour précédent"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Année suivante"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Année précédente"</string>
     <string name="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>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"Faites glisser vers le haut pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"Faites glisser vers le bas pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"Faites glisser vers la gauche pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"Faites glisser vers la droite pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <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>
     <string name="description_target_soundon" msgid="30052466675500172">"Son activé"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Rechercher"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Faites glisser votre doigt pour déverrouiller l\'appareil."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Branchez des écouteurs pour entendre l\'énoncé des touches lors de la saisie du mot de passe."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Point."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index d84915e..9a742c4 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1019,8 +1019,7 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"समय सेट करें"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"दिनांक सेट करें"</string>
     <string name="date_time_set" msgid="5777075614321087758">"सेट करें"</string>
-    <!-- no translation found for date_time_done (2507683751759308828) -->
-    <skip />
+    <string name="date_time_done" msgid="2507683751759308828">"पूर्ण"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"बढ़ाएं"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"कम करें"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> को स्‍पर्श करके रखें."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"बढ़ाने के लिए ऊपर और कम करने के लिए नीचे स्‍लाइड करें."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"मिनट बढ़ाएं"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"मिनट कम करें"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"घंटे बढ़ाएं"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"घंटे कम करें"</string>
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"सायं सेट करें"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"प्रात: सेट करें"</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="date_picker_increment_month_button" msgid="5369998479067934110">"माह बढ़ाएं"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"माह कम करें"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"दिन बढ़ाएं"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"दिन कम करें"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"वर्ष बढ़ाएं"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"वर्ष कम करें"</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"चेक किया गया"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"चेक नहीं किया गया"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"चयनित"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए ऊपर स्‍लाइड करें."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए नीचे स्‍लाइड करें."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए बाएं स्‍लाइड करें."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए दाएं स्‍लाइड करें."</string>
     <string name="description_target_unlock" msgid="2228524900439801453">"अनलॉक करें"</string>
     <string name="description_target_camera" msgid="969071997552486814">"कैमरा"</string>
     <string name="description_target_silent" msgid="893551287746522182">"मौन"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"ध्‍वनि चालू करें"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"खोजें"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"अनलॉक करने के लिए स्‍वाइप करें."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"बोली गईं पासवर्ड कुंजियां सुनने के लिए हेडसेट प्‍लग इन करें."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"बिंदु."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index b0ebc8a..ba0fb7a 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1019,8 +1019,7 @@
     <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="date_time_done" msgid="2507683751759308828">"Gotovo"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Povećavanje"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Smanjivanje"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> pritisnite i držite."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Kliznite prema gore za povećavanje i prema dolje za smanjivanje."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Povećanje minuta"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Smanjenje minuta"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Povećanje sati"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Smanjenje sati"</string>
     <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>
-    <!-- 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="date_picker_increment_month_button" msgid="5369998479067934110">"Povećanje mjeseca"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Smanjenje mjeseca"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Povećanje dana"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Smanjenje dana"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Povećanje godine"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Smanjenje godine"</string>
     <string name="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>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"Kliznite prema gore za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"Kliznite prema dolje za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"Kliznite lijevo za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"Kliznite desno za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <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>
     <string name="description_target_soundon" msgid="30052466675500172">"Zvuk je uključen"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Pretraživanje"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Prijeđite prstima da biste otključali."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Priključite slušalice kako biste čuli izgovaranje tipki zaporke."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Točka."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 5e3464d..25a8d2a 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1230,6 +1230,8 @@
     <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Némítás"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Hang bekapcsolása"</string>
+    <!-- no translation found for description_target_search (3091587249776033139) -->
+    <skip />
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"A feloldásához húzza végig az ujját."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Csatlakoztasson egy fülhallgatót, ha hallani szeretné a jelszó betűit felolvasva."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Pont."</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 4fb25c1..944f429 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1019,8 +1019,7 @@
     <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="date_time_done" msgid="2507683751759308828">"Selesai"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Menambah"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Mengurangi"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> sentuh dan tahan."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Geser ke atas untuk menambah dan ke bawah untuk mengurangi."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Menambah menit"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Mengurangi menit"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Menambah jam"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Mengurangi jam"</string>
     <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>
-    <!-- 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="date_picker_increment_month_button" msgid="5369998479067934110">"Menambah bulan"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Mengurangi bulan"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Menambah hari"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Mengurangi hari"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Menambah tahun"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Mengurangi tahun"</string>
     <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>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"Geser ke atas untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"Geser ke bawah untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"Geser ke kiri untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"Geser ke kanan untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <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>
     <string name="description_target_soundon" msgid="30052466675500172">"Suara hidup"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Penelusuran"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Gesek untuk membuka kunci."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Pasang headset untuk mendengar tombol sandi yang diucapkan."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Titik."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 7f399be..03cf404 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1019,8 +1019,7 @@
     <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="date_time_done" msgid="2507683751759308828">"Fine"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Aumenta"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Riduci"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Tocca e tieni premuto il numero <xliff:g id="VALUE">%s</xliff:g>."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Scorri verso l\'alto per aumentare il valore e verso il basso per diminuirlo."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Aumenta minuti"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Riduci minuti"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Aumenta ore"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Riduci ore"</string>
     <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>
-    <!-- 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="date_picker_increment_month_button" msgid="5369998479067934110">"Aumenta mese"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Riduci mese"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Aumenta giorno"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Riduci giorno"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Aumenta anno"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Riduci anno"</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"selezionata"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"non selezionato"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"selezionato"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"Su per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"Giù per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"A sinistra per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"A destra per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <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>
     <string name="description_target_soundon" msgid="30052466675500172">"Audio attivato"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Ricerca"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Fai scorrere per sbloccare."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Collega gli auricolari per ascoltare la pronuncia dei tasti premuti per la password."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punto."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index b03207d..3c6e0c2 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1019,8 +1019,7 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"הגדרת שעה"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"הגדר תאריך"</string>
     <string name="date_time_set" msgid="5777075614321087758">"הגדר"</string>
-    <!-- no translation found for date_time_done (2507683751759308828) -->
-    <skip />
+    <string name="date_time_done" msgid="2507683751759308828">"בוצע"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"הוסף"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"הפחת"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> גע והחזק."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"הסט למעלה כדי להוסיף ולמטה כדי להפחית."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"הוסף דקה"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"הפחת דקה"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"הוסף שעה"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"הפחת שעה"</string>
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"הגדר PM"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"הגדר AM"</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="date_picker_increment_month_button" msgid="5369998479067934110">"הוסף חודש"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"הפחת חודש"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"הוסף יום"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"הפחת יום"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"הוסף שנה"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"הפחת שנה"</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"מסומן"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"לא מסומן"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"נבחר"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"הסט למעלה כדי להציג <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"הסט למטה כדי להציג <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"הסט שמאלה כדי להציג <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"הסט ימינה כדי להציג <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_target_unlock" msgid="2228524900439801453">"בטל נעילה"</string>
     <string name="description_target_camera" msgid="969071997552486814">"מצלמה"</string>
     <string name="description_target_silent" msgid="893551287746522182">"שקט"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"הקול פועל"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"חיפוש"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"החלק לביטול נעילה."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"חבר אוזניות כדי לשמוע הקראה של מפתחות סיסמה."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"נקודה."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 526535f..9e21085 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1019,8 +1019,7 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"時刻設定"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"日付設定"</string>
     <string name="date_time_set" msgid="5777075614321087758">"設定"</string>
-    <!-- no translation found for date_time_done (2507683751759308828) -->
-    <skip />
+    <string name="date_time_done" msgid="2507683751759308828">"完了"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"進めます"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"戻します"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g>回タップして押し続けます。"</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"上にスライドで進み、下にスライドで戻ります。"</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"1分進めます"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"1分戻します"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"1時間進めます"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"1時間戻します"</string>
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"午後に設定"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"午前に設定"</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="date_picker_increment_month_button" msgid="5369998479067934110">"1か月進めます"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"1か月戻します"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"1日進めます"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"1日戻します"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"1年進めます"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"1年戻します"</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"ON"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"OFF"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"ON"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"上にスライドして<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>を行います。"</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"下にスライドして<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>を行います。"</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"左にスライドして<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>を行います。"</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"右にスライドして<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>を行います。"</string>
     <string name="description_target_unlock" msgid="2228524900439801453">"ロックを解除"</string>
     <string name="description_target_camera" msgid="969071997552486814">"カメラ"</string>
     <string name="description_target_silent" msgid="893551287746522182">"マナーモード"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"サウンドON"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"検索します"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"ロック解除するにはスワイプします。"</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"パスワードのキーが音声出力されるのでヘッドセットを接続してください。"</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"ドット。"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index b38b988..8dc3fa6 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1019,8 +1019,7 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"시간 설정"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"날짜 설정"</string>
     <string name="date_time_set" msgid="5777075614321087758">"설정"</string>
-    <!-- no translation found for date_time_done (2507683751759308828) -->
-    <skip />
+    <string name="date_time_done" msgid="2507683751759308828">"완료"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"늘리기"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"줄이기"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> 길게 터치하세요."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"늘리려면 위로 슬라이드하고 줄이려면 아래로 슬라이드합니다."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"\'분\'을 늘립니다."</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"\'분\'을 줄입니다."</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"\'시간\'을 늘립니다."</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"\'시간\'을 줄입니다."</string>
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"PM 설정"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"AM 설정"</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="date_picker_increment_month_button" msgid="5369998479067934110">"\'월\'을 늘립니다."</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"\'월\'을 줄입니다."</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"\'일\'을 늘립니다."</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"\'일\'을 줄입니다."</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"\'연도\'를 늘립니다."</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"\'연도\'를 줄입니다."</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"확인"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"선택 안함"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"선택됨"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 위로 슬라이드"</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 아래로 슬라이드"</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 왼쪽으로 슬라이드"</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 오른쪽으로 슬라이드"</string>
     <string name="description_target_unlock" msgid="2228524900439801453">"잠금 해제"</string>
     <string name="description_target_camera" msgid="969071997552486814">"카메라"</string>
     <string name="description_target_silent" msgid="893551287746522182">"무음"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"사운드 켜기"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"검색"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"스와이프하여 잠급니다."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"비밀번호 키를 음성으로 들으려면 헤드셋을 연결하세요."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"점"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 4d67940..fa13981 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1019,8 +1019,7 @@
     <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="date_time_done" msgid="2507683751759308828">"Baigta"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Padidinti"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Sumažinti"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Palieskite <xliff:g id="VALUE">%s</xliff:g> ir laikykite."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Slinkite aukštyn, kad padidintumėte, ir žemyn, kad sumažintumėte."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Padidinti minučių skaičių"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Sumažinti minučių skaičių"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Padidinti valandų skaičių"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Sumažinti valandų skaičių"</string>
     <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>
-    <!-- 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="date_picker_increment_month_button" msgid="5369998479067934110">"Padidinti mėnesių skaičių"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Sumažinti mėnesių skaičių"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Padidinti dienų skaičių"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Sumažinti dienų skaičių"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Padidinti metų skaičių"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Sumažinti metų skaičių"</string>
     <string name="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>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"Slyskite aukštyn link <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"Slyskite žemyn link <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"Slyskite į kairę link <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"Slyskite į dešinę link <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <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>
     <string name="description_target_soundon" msgid="30052466675500172">"Garsas įjungtas"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Paieška"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Perbraukite pirštu, kad atrakintumėte."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Prijunkite ausines, kad išgirstumėte sakomus slaptažodžio klavišus."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Taškas."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 12a0e58..1fe5316 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1019,8 +1019,7 @@
     <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="date_time_done" msgid="2507683751759308828">"Gatavs"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Palielināt"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Samazināt"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g>: pieskarieties un turiet nospiestu."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Velciet 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="8865885114028614321">"Norādīt vēlākas minūtes"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Norādīt agrākas minūtes"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Norādīt vēlāku stundu"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Norādīt agrāku stundu"</string>
     <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>
-    <!-- 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="date_picker_increment_month_button" msgid="5369998479067934110">"Norādīt vēlāku mēnesi"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Norādīt agrāku mēnesi"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Norādīt vēlāku dienu"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Norādīt agrāku dienu"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Norādīt vēlāku gadu"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Norādīt agrāku gadu"</string>
     <string name="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>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"Velciet uz augšu, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"Velciet uz leju, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"Velciet pa kreisi, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"Velciet pa labi, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <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>
     <string name="description_target_soundon" msgid="30052466675500172">"Skaņa ieslēgta"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Meklēt"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Velciet ar pirkstu, lai atbloķētu."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Pievienojiet austiņas, lai dzirdētu paroles taustiņu nosaukumus."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punkts."</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index f725896..da9ca41 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -1230,6 +1230,8 @@
     <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Senyap"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Bunyi dihidupkan"</string>
+    <!-- no translation found for description_target_search (3091587249776033139) -->
+    <skip />
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Leret untuk membuka kunci."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Pasangkan set kepala untuk mendengar kekunci kata laluan disebutkan."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Titik."</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 8bc9dab..ec580ad 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1019,8 +1019,7 @@
     <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="date_time_done" msgid="2507683751759308828">"Ferdig"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Øk"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Reduser"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> – trykk og hold inne."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Dra opp for å øke og ned for å redusere."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Øk minutter"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Reduser minutter"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Øk timer"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Reduser timer"</string>
     <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>
-    <!-- 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="date_picker_increment_month_button" msgid="5369998479067934110">"Øk måneder"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Reduser måneder"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Øk dager"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Reduser dager"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Øk år"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Reduser år"</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"valgt"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"ikke valgt"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"valgt"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"Dra opp for å <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"Dra ned for å <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"Dra til venstre for å <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"Dra til høyre for å <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <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>
     <string name="description_target_soundon" msgid="30052466675500172">"Lyd på"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Søk"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Sveip for å låse opp."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Koble til hodetelefoner for å høre opplesing av bokstavene i passordet."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punktum."</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 61f08e0..94d9712 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1019,8 +1019,7 @@
     <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="date_time_done" msgid="2507683751759308828">"Gereed"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Verhogen"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Verlagen"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> blijven aanraken."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Veeg omhoog om te verhogen en omlaag om te verlagen."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Hogere waarde voor minuten"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Lagere waarde voor minuten"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Hogere waarde voor uren"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Lagere waarde voor uren"</string>
     <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>
-    <!-- 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="date_picker_increment_month_button" msgid="5369998479067934110">"Hogere waarde voor maand"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Lagere waarde voor maand"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Hogere waarde voor dag"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Lagere waarde voor dag"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Hogere waarde voor jaar"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Lagere waarde voor jaar"</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"aangevinkt"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"niet aangevinkt"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"geselecteerd"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"Veeg omhoog voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"Veeg omlaag voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"Veeg naar links voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"Veeg naar rechts voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <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>
     <string name="description_target_soundon" msgid="30052466675500172">"Geluid aan"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Zoeken"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Vegen om te ontgrendelen"</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Sluit een headset aan om wachtwoordtoetsen te laten voorlezen."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Stip."</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 77f8adc..ee10502 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1230,6 +1230,8 @@
     <string name="description_target_camera" msgid="969071997552486814">"Aparat"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Wyciszenie"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Włącz dźwięk"</string>
+    <!-- no translation found for description_target_search (3091587249776033139) -->
+    <skip />
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Przesuń, aby odblokować."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Podłącz zestaw słuchawkowy, aby wysłuchać znaków hasła wypowiadanych na głos."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Kropka"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 2a3e2b9..290ae19 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1230,6 +1230,8 @@
     <string name="description_target_camera" msgid="969071997552486814">"Câmara"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Silencioso"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Som ativado"</string>
+    <!-- no translation found for description_target_search (3091587249776033139) -->
+    <skip />
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Deslizar rapidamente para desbloquear."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Ligue os auscultadores com microfone integrado para ouvir as teclas da palavra-passe."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Ponto."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 88b7a57..09fe685 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1230,6 +1230,8 @@
     <string name="description_target_camera" msgid="969071997552486814">"Câmera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Silencioso"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Som ativado"</string>
+    <!-- no translation found for description_target_search (3091587249776033139) -->
+    <skip />
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Deslize para desbloquear."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Conecte um fone de ouvido para ouvir as teclas da senha."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Ponto final."</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 75c5c7e..f4bc105 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -1834,6 +1834,8 @@
     <skip />
     <!-- no translation found for description_target_soundon (30052466675500172) -->
     <skip />
+    <!-- no translation found for description_target_search (3091587249776033139) -->
+    <skip />
     <!-- no translation found for description_target_unlock_tablet (3833195335629795055) -->
     <skip />
     <!-- no translation found for keyboard_headset_required_to_hear_password (7011927352267668657) -->
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 5409290..9dee72d 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1230,6 +1230,8 @@
     <string name="description_target_camera" msgid="969071997552486814">"Cameră foto"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Silenţios"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Sunet activat"</string>
+    <!-- no translation found for description_target_search (3091587249776033139) -->
+    <skip />
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Glisaţi pentru a debloca."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Conectaţi un set căşti-microfon pentru a auzi tastele apăsate când introduceţi parola."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punct."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 9d8e4a6..041133cd 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1019,8 +1019,7 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Настройка времени"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Настройка даты"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Установить"</string>
-    <!-- no translation found for date_time_done (2507683751759308828) -->
-    <skip />
+    <string name="date_time_done" msgid="2507683751759308828">"Готово"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Увеличить"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Уменьшить"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Нажмите и удерживайте <xliff:g id="VALUE">%s</xliff:g>."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Проведите вверх, чтобы увеличить значение, и вниз, чтобы уменьшить его."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"На минуту вперед"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"На минуту назад"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"На час вперед"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"На час назад"</string>
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Установить время после полудня"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Установить время до полудня"</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="date_picker_increment_month_button" msgid="5369998479067934110">"На месяц вперед"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"На месяц назад"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"На день вперед"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"На день назад"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"На год вперед"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"На год назад"</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"установлено"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"не установлено"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"выбрано"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"Проведите вверх, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"Проведите вниз, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"Проведите влево, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"Проведите вправо, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_target_unlock" msgid="2228524900439801453">"Разблокировать"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Камера"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Без звука"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Включить звук"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Поиск"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Проведите по экрану, чтобы разблокировать устройство."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Подключите гарнитуру, чтобы услышать пароль."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Точка"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index ca80f6b..c7c7b4f 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1230,6 +1230,8 @@
     <string name="description_target_camera" msgid="969071997552486814">"Fotoaparát"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Tichý"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Zapnúť zvuk"</string>
+    <!-- no translation found for description_target_search (3091587249776033139) -->
+    <skip />
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Posunom odomknúť."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Ak si chcete vypočuť vyslovené klávesy hesla, pripojte náhlavnú súpravu."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Bodka."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index e664d9c..4dc425b 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1230,6 +1230,8 @@
     <string name="description_target_camera" msgid="969071997552486814">"Fotoaparat"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Tiho"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Vklopljen zvok"</string>
+    <!-- no translation found for description_target_search (3091587249776033139) -->
+    <skip />
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Povlecite, če želite odkleniti."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Priključite slušalke, če želite slišati izgovorjene tipke gesla."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Pika."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 4a3839b..94024b8 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1019,8 +1019,7 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Подешавање времена"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Подешавање датума"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Подеси"</string>
-    <!-- no translation found for date_time_done (2507683751759308828) -->
-    <skip />
+    <string name="date_time_done" msgid="2507683751759308828">"Готово"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Повећавање"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Смањивање"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> додирните и задржите."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Превуците нагоре да бисте повећали, а надоле да бисте смањили."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Повећавање минута"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Смањивање минута"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Повећавање сати"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Смањивање сати"</string>
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Подеси по подне"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Подеси пре подне"</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="date_picker_increment_month_button" msgid="5369998479067934110">"Повећавање месеца"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Смањивање месеца"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Повећавање дана"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Смањивање дана"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Повећавање године"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Смањивање године"</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"изабрано"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"није потврђено"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"изабрано"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"Превуците нагоре за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"Превуците надоле за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"Превуците улево за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"Превуците удесно за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_target_unlock" msgid="2228524900439801453">"Откључај"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Камера"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Нечујно"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Укључи звук"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Претрага"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Превуците да бисте откључали."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Прикључите слушалице да бисте чули изговорене тастере за лозинку."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Тачка."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 7ba32ce..ec77eb1 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1019,8 +1019,7 @@
     <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="date_time_done" msgid="2507683751759308828">"Klar"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Öka"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Minska"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> tryck länge."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Dra uppåt för att öka och nedåt för att minska."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Öka minuter"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Minska minuter"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Öka timmar"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Minska timmar"</string>
     <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>
-    <!-- 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="date_picker_increment_month_button" msgid="5369998479067934110">"Öka månader"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Minska månader"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Öka dagar"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Minska dagar"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Öka år"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Minska år"</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"markerat"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"inte markerat"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"markerade"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"Dra uppåt för <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"Dra nedåt för <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"Dra åt vänster för <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"Dra åt höger för <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
     <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>
     <string name="description_target_soundon" msgid="30052466675500172">"Ljud på"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Sök"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Lås upp genom att dra."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Anslut mikrofonlurar om du vill att lösenordet ska läsas upp."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Punkt."</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 1744095..6b64163 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1230,6 +1230,8 @@
     <string name="description_target_camera" msgid="969071997552486814">"Kamera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Kimya"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Sauti imewashwa"</string>
+    <!-- no translation found for description_target_search (3091587249776033139) -->
+    <skip />
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Pitisha ili kufungua."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Chomeka kifaa cha sauti ili kusikiliza vibonye vya nenosiri vikizungumzwa."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Nukta."</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 32281b5..a9313b7 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1019,8 +1019,7 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"ตั้งเวลา"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"ตั้งวันที่"</string>
     <string name="date_time_set" msgid="5777075614321087758">"ตั้งค่า"</string>
-    <!-- no translation found for date_time_done (2507683751759308828) -->
-    <skip />
+    <string name="date_time_done" msgid="2507683751759308828">"เสร็จสิ้น"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"เพิ่ม"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"ลด"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"แตะ <xliff:g id="VALUE">%s</xliff:g> ค้างไว้"</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"เลื่อนขึ้นเพื่อเพิ่มและเลื่อนลงเพื่อลด"</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"เพิ่มนาที"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"ลดนาที"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"เพิ่มชั่วโมง"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"ลดชั่วโมง"</string>
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"ตั้งค่า PM"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"ตั้งค่า AM"</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="date_picker_increment_month_button" msgid="5369998479067934110">"เพิ่มเดือน"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"ลดเดือน"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"เพิ่มวัน"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"ลดวัน"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"เพิ่มปี"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"ลดปี"</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"เลือกไว้"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"ไม่ได้ตรวจสอบ"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"เลือกแล้ว"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"เลื่อนขึ้นเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"เลื่อนลงเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"เลื่อนไปทางซ้ายเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"เลื่อนไปทางขวาเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
     <string name="description_target_unlock" msgid="2228524900439801453">"ปลดล็อก"</string>
     <string name="description_target_camera" msgid="969071997552486814">"กล้องถ่ายรูป"</string>
     <string name="description_target_silent" msgid="893551287746522182">"ปิดเสียง"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"เปิดเสียง"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"ค้นหา"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"กวาดเพื่อปลดล็อก"</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"เสียบชุดหูฟังเพื่อฟังเสียงเมื่อพิมพ์รหัสผ่าน"</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"เครื่องหมายจุด"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index fd88fc1..2addf86b 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1230,6 +1230,8 @@
     <string name="description_target_camera" msgid="969071997552486814">"Camera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Tahimik"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"I-on ang tunog"</string>
+    <!-- no translation found for description_target_search (3091587249776033139) -->
+    <skip />
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Mag-swipe upang i-unlock."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Mag-plug in ng isang headset upang marinig ang mga password key na binabanggit."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Dot."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 251e47c..29cde7d 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1019,8 +1019,7 @@
     <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="date_time_done" msgid="2507683751759308828">"Tamamlandı"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Artır"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Azalt"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> rakamına dokunun ve basılı tutun."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Artırmak için yukarı, azaltmak için aşağı kaydırın."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Dakikayı artır"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Dakikayı azalt"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Saati artır"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Saati azalt"</string>
     <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>
-    <!-- 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="date_picker_increment_month_button" msgid="5369998479067934110">"Ayı artır"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Ayı azalt"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Günü artır"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Günü azalt"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Yılı artır"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Yılı azalt"</string>
     <string name="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>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için yukarı kaydırın."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için aşağı kaydırın."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için sola kaydırın."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için sağa kaydırın."</string>
     <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>
     <string name="description_target_soundon" msgid="30052466675500172">"Ses açık"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Ara"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Kilidi açmak için kaydırın."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Şifre tuşlarının sesli okunmasını dinlemek için mikrofonlu kulaklık takın."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Nokta."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 9054295..f2ef429 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1019,8 +1019,7 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Установити час"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Установити дату"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Застосувати"</string>
-    <!-- no translation found for date_time_done (2507683751759308828) -->
-    <skip />
+    <string name="date_time_done" msgid="2507683751759308828">"Готово"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Збільшити"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Зменшити"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> – торкніться й утримуйте."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Проведіть пальцем угору, щоб збільшити, і вниз, щоб зменшити."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Вибрати хвилину в майбутньому"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Вибрати хвилину в минулому"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Вибрати годину в майбутньому"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Вибрати годину в минулому"</string>
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"Установити час \"пп\""</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"Установити час \"дп\""</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="date_picker_increment_month_button" msgid="5369998479067934110">"Вибрати місяць у майбутньому"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Вибрати місяць у минулому"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Вибрати день у майбутньому"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Вибрати день у минулому"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Вибрати рік у майбутньому"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Вибрати рік у минулому"</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"перевірено"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"не перевірено"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"вибрано"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"Проведіть пальцем угору, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"Проведіть пальцем униз, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"Проведіть пальцем ліворуч, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"Проведіть пальцем праворуч, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_target_unlock" msgid="2228524900439801453">"Розблокувати"</string>
     <string name="description_target_camera" msgid="969071997552486814">"Камера"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Без звуку"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Увімкнути звук"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Пошук"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Гортайте, щоб розблокувати."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Підключіть гарнітуру, щоб прослухати відтворені вголос символи пароля."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Крапка."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 609452d..94ce574 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1019,8 +1019,7 @@
     <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="date_time_done" msgid="2507683751759308828">"Xong"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"Tăng"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"Giảm"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"Chạm và giữ <xliff:g id="VALUE">%s</xliff:g>."</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"Trượt lên để tăng và trượt xuống để giảm."</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"Tăng phút"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"Giảm phút"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"Tăng giờ"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"Giảm giờ"</string>
     <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>
-    <!-- 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="date_picker_increment_month_button" msgid="5369998479067934110">"Tăng tháng"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"Giảm tháng"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"Tăng ngày"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"Giảm ngày"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"Tăng năm"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"Giảm năm"</string>
     <string name="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>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"Trượt lên để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"Trượt xuống để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"Trượt sang trái để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"Trượt sang phải để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <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>
     <string name="description_target_soundon" msgid="30052466675500172">"Bật âm thanh"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"Tìm kiếm"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Trượt để mở khóa."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Cắm tai nghe để nghe các khóa mật khẩu được đọc."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Dấu chấm."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 5a9cadc..fd69a3e 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1019,8 +1019,7 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"设置时间"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"设置日期"</string>
     <string name="date_time_set" msgid="5777075614321087758">"设置"</string>
-    <!-- no translation found for date_time_done (2507683751759308828) -->
-    <skip />
+    <string name="date_time_done" msgid="2507683751759308828">"完成"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"增大"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"减小"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"触摸 <xliff:g id="VALUE">%s</xliff:g> 次并按住。"</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"向上滑动可增大值,向下滑动可减小值。"</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"增大分钟值"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"减小分钟值"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"增大小时值"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"减小小时值"</string>
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"设置下午时间"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"设置上午时间"</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="date_picker_increment_month_button" msgid="5369998479067934110">"增大月份值"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"减小月份值"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"增大日的值"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"减小日的值"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"增大年份值"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"减小年份值"</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"已选中"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"未选中"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"已选择"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"向上滑动以<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"向下滑动以<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"向左滑动以<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"向右滑动以<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
     <string name="description_target_unlock" msgid="2228524900439801453">"解锁"</string>
     <string name="description_target_camera" msgid="969071997552486814">"相机"</string>
     <string name="description_target_silent" msgid="893551287746522182">"静音"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"打开声音"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"搜索"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"滑动解锁。"</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"需要插入耳机才能听到密码的按键声。"</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"点。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index aa8eda1..9283fa9 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1019,8 +1019,7 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"設定時間"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"日期設定"</string>
     <string name="date_time_set" msgid="5777075614321087758">"設定"</string>
-    <!-- no translation found for date_time_done (2507683751759308828) -->
-    <skip />
+    <string name="date_time_done" msgid="2507683751759308828">"完成"</string>
     <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,35 +1169,22 @@
     <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>
-    <!-- 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_button" msgid="2412072272832284313">"增加"</string>
+    <string name="number_picker_decrement_button" msgid="476050778386779067">"減少"</string>
     <string name="number_picker_increment_scroll_mode" msgid="3073101067441638428">"<xliff:g id="VALUE">%s</xliff:g> 輕觸並按住。"</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="number_picker_increment_scroll_action" msgid="9101473045891835490">"向上滑動即可增加,向下滑動即可減少。"</string>
+    <string name="time_picker_increment_minute_button" msgid="8865885114028614321">"增加分鐘數"</string>
+    <string name="time_picker_decrement_minute_button" msgid="6246834937080684791">"減少分鐘數"</string>
+    <string name="time_picker_increment_hour_button" msgid="3652056055810223139">"增加小時數"</string>
+    <string name="time_picker_decrement_hour_button" msgid="1377479863429214792">"減少小時數"</string>
     <string name="time_picker_increment_set_pm_button" msgid="4147590696151230863">"設定 PM 值"</string>
     <string name="time_picker_decrement_set_am_button" msgid="8302140353539486752">"設定 AM 值"</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="date_picker_increment_month_button" msgid="5369998479067934110">"增加月數"</string>
+    <string name="date_picker_decrement_month_button" msgid="1832698995541726019">"減少月數"</string>
+    <string name="date_picker_increment_day_button" msgid="7130465412308173903">"增加日數"</string>
+    <string name="date_picker_decrement_day_button" msgid="4131881521818750031">"減少日數"</string>
+    <string name="date_picker_increment_year_button" msgid="6318697384310808899">"增加年數"</string>
+    <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"減少年數"</string>
     <string name="checkbox_checked" msgid="7222044992652711167">"已勾選"</string>
     <string name="checkbox_not_checked" msgid="5174639551134444056">"尚未勾選"</string>
     <string name="radiobutton_selected" msgid="8603599808486581511">"已選取"</string>
@@ -1218,18 +1204,15 @@
     <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>
-    <!-- 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_direction_up" msgid="7169032478259485180">"向上滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
+    <string name="description_direction_down" msgid="5087739728639014595">"向下滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
+    <string name="description_direction_left" msgid="7207478719805562165">"向左滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
+    <string name="description_direction_right" msgid="8034433242579600980">"向右滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
     <string name="description_target_unlock" msgid="2228524900439801453">"解除鎖定"</string>
     <string name="description_target_camera" msgid="969071997552486814">"相機"</string>
     <string name="description_target_silent" msgid="893551287746522182">"靜音"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"開啟音效"</string>
+    <string name="description_target_search" msgid="3091587249776033139">"搜尋"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"滑動即可解鎖。"</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"連接耳機即可聽取系統朗讀密碼按鍵。"</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"點。"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 200bbea..6fe919d 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1230,6 +1230,8 @@
     <string name="description_target_camera" msgid="969071997552486814">"Ikhamera"</string>
     <string name="description_target_silent" msgid="893551287746522182">"Thulile"</string>
     <string name="description_target_soundon" msgid="30052466675500172">"Umsindo uvuliwe"</string>
+    <!-- no translation found for description_target_search (3091587249776033139) -->
+    <skip />
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"Swayipha ukuze uvule."</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"Plaka ku-headset ukuze uzwe okhiye bephasiwedi ezindlebeni zakho bezwakala kakhulu."</string>
     <string name="keyboard_password_character_no_headset" msgid="2859873770886153678">"Icashazi."</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 5b6b35a..aabe407 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2349,6 +2349,8 @@
         <!-- Component name of an activity that allows the user to modify
              the settings for this service. -->
         <attr name="settingsActivity"/>
+        <!-- Set true when the spell checker supports sentence level spell checking. -->
+        <attr name="supportsSentenceSpellCheck" format="boolean" />
     </declare-styleable>
 
     <!-- This is the subtype of the spell checker. Subtype can describe locales (e.g. en_US, fr_FR...) -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 195c2e1..ca0e913 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3578,4 +3578,5 @@
 
   <public type="attr" name="parentActivityName" />
 
+  <public type="attr" name="supportsSentenceSpellCheck" />
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index baeb9cc..bc5b1bc 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1158,6 +1158,7 @@
         <item name="android:minWidth">@android:dimen/action_button_min_width</item>
         <item name="android:minHeight">?android:attr/actionBarSize</item>
         <item name="android:gravity">center</item>
+        <item name="android:maxLines">2</item>
     </style>
 
     <style name="Widget.ActionButton.Overflow">
@@ -1861,6 +1862,7 @@
         <item name="android:paddingLeft">12dip</item>
         <item name="android:paddingRight">12dip</item>
         <item name="android:scaleType">center</item>
+        <item name="android:maxLines">2</item>
     </style>
 
     <style name="Widget.Holo.ActionButton.Overflow">
diff --git a/docs/html/guide/topics/ui/accessibility/apps.jd b/docs/html/guide/topics/ui/accessibility/apps.jd
index ff34be6..dc91638 100644
--- a/docs/html/guide/topics/ui/accessibility/apps.jd
+++ b/docs/html/guide/topics/ui/accessibility/apps.jd
@@ -111,7 +111,7 @@
 <p>By including the description, speech-based accessibility services can announce "Add note" when a
 user moves focus to this button or hovers over it.</p>
 
-<p class="note">Note: For {@link android.widget.EditText} fields, provide an
+<p class="note"><strong>Note:</strong> For {@link android.widget.EditText} fields, provide an
 <a href="{@docRoot}reference/android/widget/TextView.html#attr_android:hint">android:hint</a>
 attribute to help users understand what content is expected.</p>
 
@@ -119,8 +119,10 @@
 
 <p>Focus navigation allows users with disabilities to step through user interface controls using a
 directional controller. Directional controllers can be physical, such as a clickable trackball,
-directional pad (D-Pad) or arrow keys, tab key navigation with an attached keyboard or a software
-application that provides an on-screen directional control.</p>
+directional pad (D-pad) or arrow keys, tab key navigation with an attached keyboard or a software
+application, such as the
+<a href="https://play.google.com/store/apps/details?id=com.googlecode.eyesfree.inputmethod.latin">
+Eyes-Free Keyboard</a>, that provides an on-screen directional control.</p>
 
 <p>A directional controller is a primary means of navigation for many users.
 Verify that all user interface (UI) controls in your application are accessible
@@ -566,5 +568,7 @@
 <p>As part of your accessibility testing, you can test navigation of your application using focus,
 even if your test devices does not have a directional controller. The <a
 href="{@docRoot}guide/developing/tools/emulator.html">Android Emulator</a> provides a
-simulated directional controller that you can easily use to test navigation. You can also use the
-arrow keys and Enter key on your keyboard with the Emulator to simulate use of a D-pad.</p>
+simulated directional controller that you can easily use to test navigation. You can also use a
+software-based directional controller, such as the one provided by the
+<a href="https://play.google.com/store/apps/details?id=com.googlecode.eyesfree.inputmethod.latin">
+Eyes-Free Keyboard</a> to simulate use of a D-pad.</p>
diff --git a/docs/html/guide/topics/ui/declaring-layout.jd b/docs/html/guide/topics/ui/declaring-layout.jd
index 4dc915f..8af4a1c 100644
--- a/docs/html/guide/topics/ui/declaring-layout.jd
+++ b/docs/html/guide/topics/ui/declaring-layout.jd
@@ -194,7 +194,7 @@
 appropriate for the view group. As you can see in figure 1, the parent
 view group defines layout parameters for each child view (including the child view group).</p>
 
-<img src="{@docRoot}images/layoutparams.png" alt="" height="300" align="center"/>
+<img src="{@docRoot}images/layoutparams.png" alt="" />
 <p class="img-caption"><strong>Figure 1.</strong> Visualization of a view hierarchy with layout
 parameters associated with each view.</p>
 
diff --git a/docs/html/guide/topics/ui/index.jd b/docs/html/guide/topics/ui/index.jd
index 83c8150..45c9ac9 100644
--- a/docs/html/guide/topics/ui/index.jd
+++ b/docs/html/guide/topics/ui/index.jd
@@ -51,7 +51,7 @@
 can build it up using Android's set of predefined widgets and layouts, or with custom Views that you 
 create yourself.</p>
 
-<img src="{@docRoot}images/viewgroup.png" alt="" width="312" height="211" align="center"/>
+<img src="{@docRoot}images/viewgroup.png" alt="" />
 
 <p>
 In order to attach the view hierarchy tree to the screen for rendering, your Activity must call the
diff --git a/docs/html/images/layoutparams.png b/docs/html/images/layoutparams.png
index 7473dcc..d99625e 100644
--- a/docs/html/images/layoutparams.png
+++ b/docs/html/images/layoutparams.png
Binary files differ
diff --git a/docs/html/images/training/firstapp/adt-firstapp-setup.png b/docs/html/images/training/firstapp/adt-firstapp-setup.png
new file mode 100644
index 0000000..c092562
--- /dev/null
+++ b/docs/html/images/training/firstapp/adt-firstapp-setup.png
Binary files differ
diff --git a/docs/html/images/training/firstapp/edittext_gravity.png b/docs/html/images/training/firstapp/edittext_gravity.png
new file mode 100644
index 0000000..f78e676
--- /dev/null
+++ b/docs/html/images/training/firstapp/edittext_gravity.png
Binary files differ
diff --git a/docs/html/images/training/firstapp/edittext_wrap.png b/docs/html/images/training/firstapp/edittext_wrap.png
new file mode 100644
index 0000000..156776d
--- /dev/null
+++ b/docs/html/images/training/firstapp/edittext_wrap.png
Binary files differ
diff --git a/docs/html/images/training/firstapp/firstapp.png b/docs/html/images/training/firstapp/firstapp.png
new file mode 100644
index 0000000..d69cd20
--- /dev/null
+++ b/docs/html/images/training/firstapp/firstapp.png
Binary files differ
diff --git a/docs/html/images/viewgroup.png b/docs/html/images/viewgroup.png
index a4c2518..2c86ddb 100644
--- a/docs/html/images/viewgroup.png
+++ b/docs/html/images/viewgroup.png
Binary files differ
diff --git a/docs/html/sdk/ndk/index.jd b/docs/html/sdk/ndk/index.jd
index 6f06de3..fddbcc7 100644
--- a/docs/html/sdk/ndk/index.jd
+++ b/docs/html/sdk/ndk/index.jd
@@ -62,7 +62,7 @@
 <div class="toggleable open">
   <a href="#" onclick="return toggleDiv(this)"><img src=
   "{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px">
-  Android NDK, Revision 7c</a> <em>(March 2012)</em>
+  Android NDK, Revision 7c</a> <em>(April 2012)</em>
 
   <div class="toggleme">
     <p>This release of the NDK includes an important fix for Tegra2-based devices, and a few
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index 3aafea9e..a70b0f3 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -191,9 +191,7 @@
       <span style="display:none" class="zh-TW"></span>
     </span>
     <ul>
-      <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r7c</a>
-        <span class="new">new!</span>
-        </li>
+      <li><a href="<?cs var:toroot ?>sdk/ndk/index.html">Android NDK, r7c</a></li>
       <li><a href="<?cs var:toroot ?>sdk/ndk/overview.html">What is the NDK?</a></li>
     </ul>
   </li>
diff --git a/docs/html/training/basics/firstapp/building-ui.jd b/docs/html/training/basics/firstapp/building-ui.jd
new file mode 100644
index 0000000..847163a
--- /dev/null
+++ b/docs/html/training/basics/firstapp/building-ui.jd
@@ -0,0 +1,363 @@
+page.title=Building a Simple User Interface
+parent.title=Building Your First App
+parent.link=index.html
+
+trainingnavtop=true
+previous.title=Running Your App
+previous.link=running-app.html
+next.title=Starting Another Activity
+next.link=starting-activity.html
+
+@jd:body
+
+
+<!-- This is the training bar -->
+<div id="tb-wrapper"> 
+<div id="tb"> 
+ 
+<h2>This lesson teaches you to</h2>
+
+<ol>
+  <li><a href="#LinearLayout">Use a Linear Layout</a></li>
+  <li><a href="#TextInput">Add a Text Input Box</a></li>
+  <li><a href="#Strings">Add String Resources</a></li>
+  <li><a href="#Button">Add a Button</a></li>
+  <li><a href="#Weight">Make the Input Box Fill in the Screen Width</a></li>
+</ol>
+
+
+<h2>You should also read</h2>
+<ul>
+  <li><a href="{@docRoot}guide/topics/ui/declaring-layout.html">XML Layouts</a></li>
+</ul>
+ 
+ 
+</div> 
+</div> 
+
+
+
+<p>The graphical user interface for an Android app is built using a hierarchy of {@link
+android.view.View} and {@link android.view.ViewGroup} objects. {@link android.view.View} objects are
+usually UI widgets such as a button or text field and {@link android.view.ViewGroup} objects are
+invisible view containers that define how the child views are laid out, such as in a
+grid or a vertical list.</p>
+
+<p>Android provides an XML vocabulary that corresponds to the subclasses of {@link
+android.view.View} and {@link android.view.ViewGroup} so you can define your UI in XML with a
+hierarchy of view elements.</p>
+
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+  <h2>Alternative Layouts</h2>
+  <p>Separating the UI layout into XML files is important for several reasons,
+but it's especially important on Android because it allows you to define alternative layouts for
+different screen sizes. For example, you can create two versions of a layout and tell
+the system to use one on "small" screens and the other on "large" screens. For more information,
+see the class about <a
+href="{@docRoot}training/supporting-hardware/index.html">Supporting Various Hardware</a>.</p>
+</div>
+</div>
+
+<img src="{@docRoot}images/viewgroup.png" alt="" />
+<p class="img-caption"><strong>Figure 1.</strong> Illustration of how {@link
+android.view.ViewGroup} objects form branches in the layout and contain {@link
+android.view.View} objects.</p>
+
+<p>In this lesson, you'll create a layout in XML that includes a text input field and a
+button. In the following lesson, you'll respond when the button is pressed by sending the
+content of the text field to another activity.</p>
+
+
+
+<h2 id="LinearLayout">Use a Linear Layout</h2>
+
+<p>Open the <code>main.xml</code> file from the <code>res/layout/</code>
+directory (every new Android project includes this file by default).</p>
+
+<p class="note"><strong>Note:</strong> In Eclipse, when you open a layout file, you’re first shown
+the ADT Layout Editor. This is an editor that helps you build layouts using WYSIWYG tools. For this
+lesson, you’re going to work directly with the XML, so click the <em>main.xml</em> tab at
+the bottom of the screen to open the XML editor.</p>
+
+<p>By default, the <code>main.xml</code> file includes a layout with a {@link
+android.widget.LinearLayout} root view group and a {@link android.widget.TextView} child view.
+You’re going to re-use the {@link android.widget.LinearLayout} in this lesson, but change its
+contents and layout orientation.</p>
+
+<p>First, delete the {@link android.widget.TextView} element and change the value
+<a href="{@docRoot}reference/android/widget/LinearLayout.html#attr_android:orientation">{@code
+android:orientation}</a> to be <code>"horizontal"</code>. The result looks like this:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="horizontal" >
+&lt;/LinearLayout>
+</pre>
+
+<p>{@link android.widget.LinearLayout} is a view group (a subclass of {@link
+android.view.ViewGroup}) that lays out child views in either a vertical or horizontal orientation,
+as specified by the <a
+href="{@docRoot}reference/android/widget/LinearLayout.html#attr_android:orientation">{@code
+android:orientation}</a> attribute. Each child of a {@link android.widget.LinearLayout} appears on
+the screen in the order in which it appears in the XML.</p> 
+
+<p>The other two attributes, <a
+href="{@docRoot}reference/android/view/View.html#attr_android:layout_width">{@code
+android:layout_width}</a> and <a
+href="{@docRoot}reference/android/view/View.html#attr_android:layout_height">{@code
+android:layout_height}</a>, are required for all views in order to specify their size.</p>
+
+<p>Because the {@link android.widget.LinearLayout} is the root view in the layout, it should fill
+the entire screen area that's
+available to the app by setting the width and height to
+<code>"fill_parent"</code>.</p>
+
+<p class="note"><strong>Note:</strong> Beginning with Android 2.2 (API level 8),
+<code>"fill_parent"</code> has been renamed <code>"match_parent"</code> to better reflect the
+behavior. The reason is that if you set a view to <code>"fill_parent"</code> it does not expand to
+fill the remaining space after sibling views are considered, but instead expands to
+<em>match</em> the size of the parent view no matter what&mdash;it will overlap any sibling
+views.</p>
+
+<p>For more information about layout properties, see the <a
+href="{@docRoot}guide/topics/ui/declaring-layout.html">XML Layout</a> guide.</p>
+
+
+
+<h2 id="TextInput">Add a Text Input Box</h2>
+
+<p>To create a user-editable text box, add an {@link android.widget.EditText
+&lt;EditText>} element inside the {@link android.widget.LinearLayout &lt;LinearLayout>}. The {@link
+android.widget.EditText} class is a subclass of {@link android.view.View} that displays an editable
+text box.</p>
+
+<p>Like every {@link android.view.View} object, you must define certain XML attributes to specify
+the {@link android.widget.EditText} object's properties. Here’s how you should declare it
+inside the {@link android.widget.LinearLayout &lt;LinearLayout>} element:</p>
+
+<pre>
+    &lt;EditText android:id="@+id/edit_message"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:hint="@string/edit_message" />
+</pre>
+
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+  <h3>About resource objects</h3>
+  <p>A resource object is simply a unique integer name that's associated with an app resource,
+such as a bitmap, layout file, or string.</p>
+  <p>Every resource has a
+corresponding resource object defined in your project's {@code gen/R.java} file. You can use the
+object names in the {@code R} class to refer to your resources, such as when you need to specify a
+string value for the <a
+href="{@docRoot}reference/android/widget/TextView.html#attr_android:hint">{@code android:hint}</a>
+attribute. You can also create arbitrary resource IDs that you associate with a view using the <a
+href="{@docRoot}reference/android/view/View.html#attr_android:id">{@code android:id}</a> attribute,
+which allows you to reference that view from other code.</p>
+  <p>The SDK tools generate the {@code R.java} each time you compile your app. You should never
+modify this file by hand.</p>
+</div>
+</div>
+
+<p>About these attributes:</p>
+
+<dl>
+<dt><a href="{@docRoot}reference/android/view/View.html#attr_android:id">{@code android:id}</a></dt>
+<dd>This provides a unique identifier for the view, which you can use to reference the object
+from your app code, such as to read and manipulate the object (you'll see this in the next
+lesson).
+
+<p>The at-symbol (<code>&#64;</code>) is required when you want to refer to a resource object from
+XML, followed by the resource type ({@code id} in this case), then the resource name ({@code
+edit_message}). (Other resources can use the same name as long as they are not the same
+resource type&mdash;for example, the string resource uses the same name.)</p>
+
+<p>The plus-symbol (<code>+</code>) is needed only when you're defining a resource ID for the
+first time. It tells the SDK tools that the resource ID needs to be created. Thus, when the app is
+compiled, the SDK tools use the ID value, <code>edit_message</code>, to create a new identifier in
+your project's {@code gen/R.java} file that is now assiciated with the {@link
+android.widget.EditText} element. Once the resource ID is created, other references to the ID do not
+need the plus symbol. See the sidebox for more information about resource objects.</p></dd>
+
+<dt><a
+href="{@docRoot}reference/android/view/View.html#attr_android:layout_width">{@code
+android:layout_width}</a> and <a
+href="{@docRoot}reference/android/view/View.html#attr_android:layout_height">{@code
+android:layout_height}</a></dt>
+<dd>Instead of using specific sizes for the width and height, the <code>"wrap_content"</code> value
+specifies that the view should be only as big as needed to fit the contents of the view. If you
+were to instead use <code>"fill_parent"</code>, then the {@link android.widget.EditText}
+element would fill the screen, because it'd match the size of the parent {@link
+android.widget.LinearLayout}. For more information, see the <a
+href="{@docRoot}guide/topics/ui/declaring-layout.html">XML Layouts</a> guide.</dd>
+
+<dt><a
+href="{@docRoot}reference/android/widget/TextView.html#attr_android:hint">{@code
+android:hint}</a></dt>
+<dd>This is a default string to display when the text box is empty. Instead of using a hard-coded
+string as the value, the value given in this example refers to a string resource. When you add the
+{@code
+"@string/edit_message"} value, you’ll see a compiler error because there’s no matching string
+resource by that name. You'll fix this in the next section by defining the string
+resource.</dd>
+</dl>
+
+
+
+<h2 id="Strings">Add String Resources</h2>
+
+<p>When you need to add text in the user interface, you should always specify each string of text in
+a resource file. String resources allow you to maintain a single location for all string
+values, which makes it easier to find and update text. Externalizing the strings also allows you to
+localize your app to different languages by providing alternative definitions for each
+string.</p>
+
+<p>By default, your Android project includes a string resource file at
+<code>res/values/strings.xml</code>. Open this file, delete the existing <code>"hello"</code>
+string, and add one for the
+<code>"edit_message"</code> string used by the {@link android.widget.EditText &lt;EditText>}
+element.</p>
+
+<p>While you’re in this file, also add a string for the button you’ll soon add, called
+<code>"button_send"</code>.</p>
+
+<p>The result for <code>strings.xml</code> looks like this:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;resources>
+    &lt;string name="app_name">My First App&lt;/string>
+    &lt;string name="edit_message">Enter a message&lt;/string>
+    &lt;string name="button_send">Send&lt;/string>
+&lt;/resources>
+</pre>
+
+<p>For more information about using string resources to localize your app for several languages,
+see the <a
+href="{@docRoot}training/basics/supporting-devices/index.html">Supporting Various Devices</a>
+class.</p>
+
+
+
+
+<h2 id="Button">Add a Button</h2>
+
+<p>Now add a {@link android.widget.Button &lt;Button>} to the layout, immediately following the
+{@link android.widget.EditText &lt;EditText>} element:</p>
+
+<pre>
+    &lt;Button
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/button_send" />
+</pre>
+
+<p>The height and width are set to <code>"wrap_content"</code> so the button is only as big as
+necessary to fit the button's text.</p>
+
+
+
+<h2 id="Weight">Make the Input Box Fill in the Screen Width</h2>
+
+<p>The layout is currently designed so that both the {@link android.widget.EditText} and {@link
+android.widget.Button} widgets are only as big as necessary to fit their content, as shown in
+figure 2.</p>
+
+<img src="{@docRoot}images/training/firstapp/edittext_wrap.png" />
+<p class="img-caption"><strong>Figure 2.</strong> The {@link android.widget.EditText} and {@link
+android.widget.Button} widgets have their widths set to
+<code>"wrap_content"</code>.</p>
+
+<p>This works fine for the button, but not as well for the text box, because the user might type
+something longer and there's extra space left on the screen. So, it'd be nice to fill that width
+using the text box.
+{@link android.widget.LinearLayout} enables such a design with the <em>weight</em> property, which
+you can specify using the <a
+href="{@docRoot}reference/android/widget/LinearLayout.LayoutParams.html#weight">{@code
+android:layout_weight}</a> attribute.</p>
+
+<p>The weight value allows you to specify the amount of remaining space each view should consume,
+relative to the amount consumed by sibling views, just like the ingredients in a drink recipe: "2
+parts vodka, 1 part coffee liquer" means two-thirds of the drink is vodka. For example, if you give
+one view a weight of 2 and another one a weight of 1, the sum is 3, so the first view gets 2/3 of
+the remaining space and the second view gets the rest. If you give a third view a weight of 1,
+then the first view now gets 1/2 the remaining space, while the remaining two each get 1/4.</p>
+
+<p>The default weight for all views is 0, so if you specify any weight value
+greater than 0 to only one view, then that view fills whatever space remains after each view is
+given the space it requires. So, to fill the remaining space with the {@link
+android.widget.EditText} element, give it a weight of 1 and leave the button with no weight.</p>
+
+<pre>
+    &lt;EditText
+        android:layout_weight="1"
+        ... />
+</pre>
+
+<p>In order to improve the layout efficiency when you specify the weight, you should change the
+width of the {@link android.widget.EditText} to be
+zero (0dp). Setting the width to zero improves layout performance because using
+<code>"wrap_content"</code> as the width requires the system to calculate a width that is
+ultimately irrelevant because the weight value requires another width calculation to fill the
+remaining space.</p>
+<pre>
+    &lt;EditText
+        android:layout_weight="1"
+        android:layout_width="0dp"
+        ... />
+</pre>
+
+<p>Figure 3
+shows the result when you assign all weight to the {@link android.widget.EditText} element.</p>
+
+<img src="{@docRoot}images/training/firstapp/edittext_gravity.png" />
+<p class="img-caption"><strong>Figure 3.</strong> The {@link android.widget.EditText} widget is
+given all the layout weight, so fills the remaining space in the {@link
+android.widget.LinearLayout}.</p>
+
+<p>Here’s how your complete layout file should now look:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="horizontal">
+    &lt;EditText android:id="@+id/edit_message"
+        android:layout_weight="1"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:hint="@string/edit_message" />
+    &lt;Button android:id="@+id/button_send"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/button_send" />
+&lt;/LinearLayout>
+</pre>
+
+<p>This layout is applied by the default {@link android.app.Activity} class
+that the SDK tools generated when you created the project, so you can now run the app to see the
+results:</p>
+
+<ul>
+  <li>In Eclipse, click <strong>Run</strong> from the toolbar.</li>
+  <li>Or from a command line, change directories to the root of your Android project and
+execute:
+<pre>
+ant debug
+adb install bin/MyFirstApp-debug.apk
+</pre></li>
+</ul>
+
+<p>Continue to the next lesson to learn how you can respond to button presses, read content
+from the text field, start another activity, and more.</p>
+
+
+
diff --git a/docs/html/training/basics/firstapp/creating-project.jd b/docs/html/training/basics/firstapp/creating-project.jd
new file mode 100644
index 0000000..5a89f2e
--- /dev/null
+++ b/docs/html/training/basics/firstapp/creating-project.jd
@@ -0,0 +1,142 @@
+page.title=Creating an Android Project
+parent.title=Building Your First App
+parent.link=index.html
+
+trainingnavtop=true
+next.title=Running Your App
+next.link=running-app.html
+
+@jd:body
+
+
+<!-- This is the training bar -->
+<div id="tb-wrapper"> 
+<div id="tb"> 
+ 
+<h2>This lesson teaches you to</h2>
+
+<ol>
+  <li><a href="#Eclipse">Create a Project with Eclipse</a></li>
+  <li><a href="#CommandLine">Create a Project with Command Line Tools</a></li>
+</ol>
+
+<h2>You should also read</h2>
+
+<ul>
+  <li><a href="{@docRoot}sdk/installing.html">Installing the
+SDK</a></li>
+  <li><a href="{@docRoot}guide/developing/projects/index.html">Managing Projects</a></li>
+</ul>
+ 
+ 
+</div> 
+</div> 
+
+<p>An Android project contains all the files that comprise the source code for your Android
+app. The Android SDK tools make it easy to start a new Android project with a set of
+default project directories and files.</p> 
+
+<p>This lesson
+shows how to create a new project either using Eclipse (with the ADT plugin) or using the
+SDK tools from a command line.</p>
+
+<p class="note"><strong>Note:</strong> You should already have the Android SDK installed, and if
+you're using Eclipse, you should have installed the <a
+href="{@docRoot}sdk/eclipse-adt.html">ADT plugin</a> as well. If you have not installed
+these, see <a href="{@docRoot}sdk/installing.html">Installing the Android SDK</a> and return here
+when you've completed the installation.</p>
+
+
+<h2 id="Eclipse">Create a Project with Eclipse</h2>
+
+<div class="figure" style="width:416px">
+<img src="{@docRoot}images/training/firstapp/adt-firstapp-setup.png" alt="" />
+<p class="img-caption"><strong>Figure 1.</strong> The new project wizard in Eclipse.</p>
+</div>
+
+<ol>
+  <li>In Eclipse, select <strong>File &gt; New &gt; Project</strong>.
+The resulting dialog should have a folder labeled <em>Android</em>.  (If you don’t see the
+<em>Android</em> folder,
+then you have not installed the ADT plugin&mdash;see <a
+href="{@docRoot}sdk/eclipse-adt.html#installing">Installing the ADT Plugin</a>).</li>
+  <li>Open the <em>Android</em> folder, select <em>Android Project</em> and click
+<strong>Next</strong>.</li>
+  <li>Enter a project name (such as "MyFirstApp") and click <strong>Next</strong>.</li>
+  <li>Select a build target. This is the platform version against which you will compile your app.
+<p>We recommend that you select the latest version possible. You can still build your app to
+support older versions, but setting the build target to the latest version allows you to
+easily optimize your app for a great user experience on the latest Android-powered devices.</p>
+<p>If you don't see any built targets listed, you need to install some using the Android SDK
+Manager tool. See <a href="{@docRoot}sdk/installing.html#AddingComponents">step 4 in the
+installing guide</a>.</p>
+<p>Click <strong>Next</strong>.</p></li>
+  <li>Specify other app details, such as the:
+    <ul>
+      <li><em>Application Name</em>: The app name that appears to the user. Enter "My First
+App".</li>
+      <li><em>Package Name</em>: The package namespace for your app (following the same
+rules as packages in the Java programming language). Your package name
+must be unique across all packages installed on the Android system. For this reason, it's important
+that you use a standard domain-style package name that’s appropriate to your company or
+publisher entity. For
+your first app, you can use something like "com.example.myapp." However, you cannot publish your
+app using the "com.example" namespace.</li>
+      <li><em>Create Activity</em>: This is the class name for the primary user activity in your
+app (an activity represents a single screen in your app). Enter "MyFirstActivity".</li>
+      <li><em>Minimum SDK</em>: Select <em>4 (Android 1.6)</em>.
+        <p>Because this version is lower than the build target selected for the app, a warning
+appears, but that's alright. You simply need to be sure that you don't use any APIs that require an
+<a href="{@docRoot}guide/appendix/api-levels.html">API level</a> greater than the minimum SDK
+version without first using some code to verify the device's system version (you'll see this in some
+other classes).</p>
+      </li>
+    </ul>
+    <p>Click <strong>Finish</strong>.</p>
+  </li>
+</ol>
+
+<p>Your Android project is now set up with some default files and you’re ready to begin
+building the app. Continue to the <a href="running-app.html">next lesson</a>.</p>
+
+
+
+<h2 id="CommandLine">Create a Project with Command Line Tools</h2>
+
+<p>If you're not using the Eclipse IDE with the ADT plugin, you can instead create your project
+using the SDK tools in a command line:</p>
+
+<ol>
+  <li>Change directories into the Android SDK’s <code>tools/</code> path.</li>
+  <li>Execute:
+<pre class="no-pretty-print">android list targets</pre>
+<p>This prints a list of the available Android platforms that you’ve downloaded for your SDK. Find
+the platform against which you want to compile your app. Make a note of the target id. We
+recommend that you select the highest version possible. You can still build your app to
+support older versions, but setting the build target to the latest version allows you to optimize
+your app for the latest devices.</p>
+<p>If you don't see any targets listed, you need to
+install some using the Android SDK
+Manager tool. See <a href="{@docRoot}sdk/installing.html#AddingComponents">step 4 in the
+installing guide</a>.</p></li>
+  <li>Execute:
+<pre class="no-pretty-print">
+android create project --target &lt;target-id> --name MyFirstApp \
+--path &lt;path-to-workspace>/MyFirstApp --activity MyFirstActivity \
+--package com.example.myapp
+</pre>
+<p>Replace <code>&lt;target-id></code> with an id from the list of targets (from the previous step)
+and replace
+<code>&lt;path-to-workspace></code> with the location in which you want to save your Android
+projects.</p></li>
+</ol>
+
+<p>Your Android project is now set up with several default configurations and you’re ready to begin
+building the app. Continue to the <a href="running-app.html">next lesson</a>.</p>
+
+<p class="note"><strong>Tip:</strong> Add the <code>platform-tools/</code> as well as the
+<code>tools/</code> directory to your <code>PATH</code> environment variable.</p>
+
+
+
+
diff --git a/docs/html/training/basics/firstapp/index.jd b/docs/html/training/basics/firstapp/index.jd
new file mode 100644
index 0000000..a95ed8e
--- /dev/null
+++ b/docs/html/training/basics/firstapp/index.jd
@@ -0,0 +1,64 @@
+page.title=Building Your First App
+
+trainingnavtop=true
+startpage=true
+next.title=Creating an Android Project
+next.link=creating-project.html
+
+@jd:body
+
+<div id="tb-wrapper"> 
+<div id="tb"> 
+ 
+<h2>Dependencies and prerequisites</h2> 
+
+<ul>
+  <li>Android 1.6 or higher</li>
+  <li><a href="http://developer.android.com/sdk/index.html">Android SDK</a></li>
+</ul>
+ 
+</div> 
+</div> 
+ 
+<p>Welcome to Android application development!</p> 
+
+<p>This class teaches you how to build your first Android app. You’ll learn how to create an Android
+project and run a debuggable version of the app. You'll also learn some fundamentals of Android app
+design, including how to build a simple user interface and handle user input.</p>
+
+<p>Before you start this class, be sure that you have your development environment set up. You need
+to:</p>
+<ol>
+  <li>Download the Android SDK Starter Package.</li>
+  <li>Install the ADT plugin for Eclipse (if you’ll use the Eclipse IDE).</li>
+  <li>Download the latest SDK tools and platforms using the SDK Manager.</li>
+</ol>
+
+<p>If you haven't already done this setup, read <a href="{@docRoot}sdk/installing.html">Installing
+the SDK</a>. Once you've finished the setup, you're ready to begin this class.</p>
+
+<p>This class uses a tutorial format that incrementally builds a small Android app in order to teach
+you some fundamental concepts about Android development, so it's important that you follow each
+step.</p>
+
+<p><strong><a href="creating-project.html">Start the first lesson &rsaquo;</a></strong></p>
+
+
+<h2>Lessons</h2> 
+
+<dl> 
+  <dt><b><a href="creating-project.html">Creating an Android Project</a></b></dt> 
+    <dd>Shows how to create a project for an Android app, which includes a set of default
+app files.</dd> 
+ 
+  <dt><b><a href="running-app.html">Running Your Application</a></b></dt> 
+    <dd>Shows how to run your app on an Android-powered device or the Android
+emulator.</dd>
+ 
+  <dt><b><a href="building-ui.html">Building a Simple User Interface</a></b></dt> 
+    <dd>Shows how to create a new user interface using an XML file.</dd>
+ 
+  <dt><b><a href="starting-activity.html">Starting Another Activity</a></b></dt>
+    <dd>Shows how to respond to a button press, start another activity, send it some
+data, then receive the data in the subsequent activity.</dd>
+</dl> 
diff --git a/docs/html/training/basics/firstapp/running-app.jd b/docs/html/training/basics/firstapp/running-app.jd
new file mode 100644
index 0000000..2398fa0
--- /dev/null
+++ b/docs/html/training/basics/firstapp/running-app.jd
@@ -0,0 +1,178 @@
+page.title=Running Your App
+parent.title=Building Your First App
+parent.link=index.html
+
+trainingnavtop=true
+previous.title=Creating a Project
+previous.link=creating-project.html
+next.title=Building a Simple User Interface
+next.link=building-ui.html
+
+@jd:body
+
+
+<!-- This is the training bar -->
+<div id="tb-wrapper"> 
+<div id="tb"> 
+ 
+<h2>This lesson teaches you to</h2>
+
+<ol>
+  <li><a href="#RealDevice">Run on a Real Device</a></li>
+  <li><a href="#Emulator">Run on the Emulator</a></li>
+</ol>
+
+<h2>You should also read</h2>
+
+<ul>
+  <li><a href="{@docRoot}guide/developing/device.html">Using Hardware Devices</a></li>
+  <li><a href="{@docRoot}guide/developing/devices/index.html">Managing Virtual Devices</a></li>
+  <li><a href="{@docRoot}guide/developing/projects/index.html">Managing Projects</a></li>
+</ul>
+ 
+ 
+</div> 
+</div> 
+
+
+<p>If you followed the <a href="{@docRoot}creating-project.html">previous lesson</a> to create an
+Android project, it includes a default set of "Hello World" source files that allow you to
+run the app right away.</p>
+
+<p>How you run your app depends on two things: whether you have a real Android-powered device and
+whether you’re using Eclipse. This lesson shows you how to install and run your app on a
+real device and on the Android emulator, and in both cases with either Eclipse or the command line
+tools.</p>
+
+<p>Before you run your app, you should be aware of a few directories and files in the Android
+project:</p>
+
+<dl>
+  <dt><code>AndroidManifest.xml</code></dt>
+  <dd>This manifest file describes the fundamental characteristics of the app and defines each of
+its components. You'll learn about various declarations in this file as you read more training
+classes.</dd>
+  <dt><code>src/</code></dt>
+  <dd>Directory for your app's main source files. By default, it includes an {@link
+android.app.Activity} class that runs when your app is launched using the app icon.</dd>
+  <dt><code>res/</code></dt>
+  <dd>Contains several sub-directories for app resources. Here are just a few:
+    <dl style="margin-top:1em">
+      <dt><code>drawable-hdpi/</code></dt>
+        <dd>Directory for drawable objects (such as bitmaps) that are designed for high-density
+(hdpi) screens. Other drawable directories contain assets designed for other screen densities.</dd>
+      <dt><code>layout/</code></dt>
+        <dd>Directory for files that define your app's user interface.</dd>
+      <dt><code>values/</code></dt>
+        <dd>Directory for other various XML files that contain a collection of resources, such as
+string and color definitions.</dd>
+    </dl>  
+  </dd>
+</dl>
+
+<p>When you build and run the default Android project, the default {@link android.app.Activity}
+class in the <code>src/</code> directory starts and loads a layout file from the
+<code>layout/</code> directory, which includes a "Hello World" message. Not real exciting, but it's
+important that you understand how to build and run your app before adding real functionality to
+the app.</p>
+
+
+
+<h2 id="RealDevice">Run on a Real Device</h2>
+
+<p>Whether you’re using Eclipse or the command line, you need to:</p>
+
+<ol>
+  <li>Plug in your Android-powered device to your machine with a USB cable.
+If you’re developing on Windows, you might need to install the appropriate USB driver for your
+device. For help installing drivers, see the <a href=”{@docRoot}sdk/oem-usb.html”>OEM USB
+Drivers</a> document.</li>
+  <li>Ensure that <strong>USB debugging</strong> is enabled in the device Settings (open Settings
+and navitage to <strong>Applications > Development</strong> on most devices, or select
+<strong>Developer options</strong> on Android 4.0 and higher).</li>
+</ol>
+
+<p>To run the app from Eclipse, open one of your project's files and click
+<strong>Run</strong> from the toolbar. Eclipse installs the app on your connected device and starts
+it.</p>
+
+
+<p>Or to run your app from a command line:</p>
+
+<ol>
+  <li>Change directories to the root of your Android project and execute:
+<pre class="no-pretty-print">ant debug</pre></li>
+  <li>Make sure the Android SDK <code>platform-tools/</code> directory is included in your
+<code>PATH</code> environment variable, then execute:
+<pre class="no-pretty-print">adb install bin/MyFirstApp-debug.apk</pre></li>
+  <li>On your device, locate <em>MyFirstActivity</em> and open it.</li>
+</ol>
+
+<p>To start adding stuff to the app, continue to the <a href="building-ui.html">next
+lesson</a>.</p>
+
+
+
+<h2 id="Emulator">Run on the Emulator</h2>
+
+<p>Whether you’re using Eclipse or the command line, you need to first create an <a
+href="{@docRoot}guide/developing/devices/index.html">Android Virtual
+Device</a> (AVD). An AVD is a
+device configuration for the Android emulator that allows you to model
+different device configurations.</p>
+
+<div class="figure" style="width:457px">
+  <img src="{@docRoot}images/screens_support/avds-config.png" alt="" />
+  <p class="img-caption"><strong>Figure 1.</strong> The AVD Manager showing a few virtual
+devices.</p>
+</div>
+
+<p>To create an AVD:</p>
+<ol>
+  <li>Launch the Android Virtual Device Manager:
+    <ol type="a">
+      <li>In Eclipse, select <strong>Window > AVD Manager</strong>, or click the <em>AVD
+Manager</em> icon in the Eclipse toolbar.</li>
+      <li>From the command line, change directories to <code>&lt;sdk>/tools/</code> and execute:
+<pre class="no-pretty-print">./android avd</pre></li>
+    </ol>
+  </li>
+  <li>In the <em>Android Virtual Device Device Manager</em> panel, click <strong>New</strong>.</li>
+  <li>Fill in the details for the AVD.
+Give it a name, a platform target, an SD card size, and a skin (HVGA is default).</li>
+  <li>Click <strong>Create AVD</strong>.</li>
+  <li>Select the new AVD from the <em>Android Virtual Device Manager</em> and click
+<strong>Start</strong>.</li>
+  <li>After the emulator boots up, unlock the emulator screen.</li>
+</ol>
+
+<p>To run the app from Eclipse, open one of your project's files and click
+<strong>Run</strong> from the toolbar. Eclipse installs the app on your AVD and starts it.</p>
+
+
+<p>Or to run your app from the command line:</p>
+
+<ol>
+  <li>Change directories to the root of your Android project and execute:
+<pre class="no-pretty-print">ant debug</pre></li>
+  <li>Make sure the Android SDK <code>platform-tools/</code> directory is included in your
+<code>PATH</code> environment
+variable, then execute:
+<pre class="no-pretty-print">adb install bin/MyFirstApp-debug.apk</pre></li>
+  <li>On the emulator, locate <em>MyFirstActivity</em> and open it.</li>
+</ol>
+
+
+<p>To start adding stuff to the app, continue to the <a href="building-ui.html">next
+lesson</a>.</p>
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/html/training/basics/firstapp/starting-activity.jd b/docs/html/training/basics/firstapp/starting-activity.jd
new file mode 100644
index 0000000..16a6fd8
--- /dev/null
+++ b/docs/html/training/basics/firstapp/starting-activity.jd
@@ -0,0 +1,308 @@
+page.title=Starting Another Activity
+parent.title=Building Your First App
+parent.link=index.html
+
+trainingnavtop=true
+previous.title=Building a Simpler User Interface
+previous.link=building-ui.html
+
+@jd:body
+
+
+<!-- This is the training bar -->
+<div id="tb-wrapper"> 
+<div id="tb"> 
+ 
+<h2>This lesson teaches you to</h2>
+
+<ol>
+  <li><a href="#RespondToButton">Respond to the Send Button</a></li>
+  <li><a href="#BuildIntent">Build an Intent</a></li>
+  <li><a href="#StartActivity">Start the Second Activity</a></li>
+  <li><a href="#CreateActivity">Create the Second Activity</a>
+    <ol>
+      <li><a href="#AddToManifest">Add it to the manifest</a></li>
+    </ol>
+  </li>
+  <li><a href="#ReceiveIntent">Receive the Intent</a></li>
+  <li><a href="#DisplayMessage">Display the Message</a></li>
+</ol>
+
+<h2>You should also read</h2>
+
+<ul>
+  <li><a href="{@docRoot}sdk/installing.html">Installing the
+SDK</a></li>
+</ul>
+ 
+ 
+</div> 
+</div> 
+
+
+
+<p>After completing the <a href="building-ui.html">previous lesson</a>, you have an app that
+shows an activity (a single screen) with a text box and a button. In this lesson, you’ll add some
+code to <code>MyFirstActivity</code> that
+starts a new activity when the user selects the Send button.</p>
+
+
+<h2 id="RespondToButton">Respond to the Send Button</h2>
+
+<p>To respond to the button's on-click event, open the <code>main.xml</code> layout file and add the
+<a
+href="{@docRoot}reference/android/view/View.html#attr_android:onClick">{@code android:onClick}</a>
+attribute to the {@link android.widget.Button &lt;Button>} element:</p>
+
+<pre>
+&lt;Button android:id="@+id/button_send"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:text="@string/button_send"
+    android:onClick="sendMessage" />
+</pre>
+
+<p>The <a
+href="{@docRoot}reference/android/view/View.html#attr_android:onClick">{@code
+android:onClick}</a> attribute’s value, <code>sendMessage</code>, is the name of a method in your
+activity that you want to call when the user selects the button.</p>
+
+<p>Add the corresponding method inside the <code>MyFirstActivity</code> class:</p>
+
+<pre>
+/** Called when the user selects the Send button */
+public void sendMessage(View view) {
+    // Do something in response to button
+}
+</pre>
+
+<p class="note"><strong>Tip:</strong> In Eclipse, press Ctrl + Shift + O to import missing classes
+(Cmd + Shift + O on Mac).</p>
+
+<p>Note that, in order for the system to match this method to the method name given to <a
+href="{@docRoot}reference/android/view/View.html#attr_android:onClick">{@code android:onClick}</a>,
+the signature must be exactly as shown. Specifically, the method must:</p>
+
+<ul>
+<li>Be public</li>
+<li>Have a void return value</li>
+<li>Have a {@link android.view.View} as the only parameter (this will be the {@link
+android.view.View} that was clicked)</li>
+</ul>
+
+<p>Next, you’ll fill in this method to read the contents of the text box and deliver that text to
+another activity.</p>
+
+
+
+<h2 id="BuildIntent">Build an Intent</h2>
+
+<p>An {@link android.content.Intent} is an object that provides runtime binding between separate
+components (such as two activities). The {@link android.content.Intent} represents an
+app’s "intent to do something." You can use an {@link android.content.Intent} for a wide
+variety of tasks, but most often they’re used to start another activity.</p>
+
+<p>Inside the {@code sendMessage()} method, create an {@link android.content.Intent} to start
+an activity called {@code DisplayMessageActvity}:</p>
+
+<pre>
+Intent intent = new Intent(this, DisplayMessageActivity.class);
+</pre>
+
+<p>The constructor used here takes two parameters:</p>
+<ul>
+  <li>A {@link
+android.content.Context} as its first parameter ({@code this} is used because the {@link
+android.app.Activity} class is a subclass of {@link android.content.Context})
+  <li>The {@link java.lang.Class} of the app component to which the system should deliver
+the {@link android.content.Intent} (in this case, the activity that should be started)
+</ul>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+  <h3>Sending an intent to other apps</h3>
+  <p>The intent created in this lesson is what's considered an <em>explicit intent</em>, because the
+{@link android.content.Intent}
+specifies the exact app component to which the intent should be given. However, intents
+can also be <em>implicit</em>, in which case the {@link android.content.Intent} does not specify
+the desired component, but allows any app installed on the device to respond to the intent
+as long as it satisfies the meta-data specifications for the action that's specified in various
+{@link android.content.Intent} parameters. For more informations, see the class about <a
+href="{@docRoot}training/intents/index.html">Interacting with Other Apps</a>.</p>
+</div>
+</div>
+
+<p class="note"><strong>Note:</strong> The reference to {@code DisplayMessageActivity}
+will raise an error if you’re using an IDE such as Eclipse because the class doesn’t exist yet.
+Ignore the error for now; you’ll create the class soon.</p>
+
+<p>An intent not only allows you to start another activity, but can carry a bundle of data to the
+activity as well. So, use {@link android.app.Activity#findViewById findViewById()} to get the
+{@link android.widget.EditText} element and add its message to the intent:</p>
+
+<pre>
+Intent intent = new Intent(this, DisplayMessageActivity.class);
+EditText editText = (EditText) findViewById(R.id.edit_message);
+String message = editText.getText().toString();
+intent.putExtra(EXTRA_MESSAGE, message);
+</pre>
+
+<p>An {@link android.content.Intent} can carry a collection of various data types as key-value
+pairs called <em>extras</em>. The {@link android.content.Intent#putExtra putExtra()} method takes a
+string as the key and the value in the second parameter.</p>
+
+<p>In order for the next activity to query the extra data, you should define your keys using a
+public constant. So add the {@code EXTRA_MESSAGE} definition to the top of the {@code
+MyFirstActivity} class:</p>
+
+<pre>
+public class MyFirstActivity extends Activity {
+    public final static String EXTRA_MESSAGE = "com.example.myapp.MESSAGE";
+    ...
+}
+</pre>
+
+<p>It's generally a good practice to define keys for extras with your app's package name as a prefix
+to ensure it's unique, in case your app interacts with other apps.</p>
+
+
+<h2 id="StartActivity">Start the Second Activity</h2>
+
+<p>To start an activity, you simply need to call {@link android.app.Activity#startActivity
+startActivity()} and pass it your {@link android.content.Intent}.</p>
+
+<p>The system receives this call and starts an instance of the {@link android.app.Activity}
+specified by the {@link android.content.Intent}.</p>
+
+<p>With this method included, the complete {@code sendMessage()} method that's invoked by the Send
+button now looks like this:</p>
+
+<pre>
+/** Called when the user selects the Send button */
+public void sendMessage(View view) {
+    Intent intent = new Intent(this, DisplayMessageActivity.class);
+    EditText editText = (EditText) findViewById(R.id.edit_message);
+    String message = editText.getText().toString();
+    intent.putExtra(EXTRA_MESSAGE, message);
+    startActivity(intent);
+}
+</pre>
+
+<p>Now you need to create the {@code DisplayMessageActivity} class in order for this to
+work.</p>
+
+
+
+<h2 id="CreateActivity">Create the Second Activity</h2>
+
+<p>In your project, create a new class file under the <code>src/&lt;package-name&gt;/</code>
+directory called <code>DisplayMessageActivity.java</code>.</p>
+
+<p class="note"><strong>Tip:</strong> In Eclipse, right-click the package name under the
+<code>src/</code> directory and select <strong>New > Class</strong>.
+Enter "DisplayMessageActivity" for the name and {@code android.app.Activity} for the superclass.</p>
+
+<p>Inside the class, add the {@link android.app.Activity#onCreate onCreate()} callback method:</p>
+
+<pre>
+public class DisplayMessageActivity extends Activity {
+    &#64;Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+}
+</pre>
+
+<p>All subclasses of {@link android.app.Activity} must implement the {@link
+android.app.Activity#onCreate onCreate()} method. The system calls this when creating a new
+instance of the activity. It is where you must define the activity layout and where you should
+initialize essential activity components.</p>
+
+
+
+<h3 id="AddToManifest">Add it to the manifest</h3>
+
+<p>You must declare all activities in your manifest file, <code>AndroidManifest.xml</code>, using an
+<a
+href="{@docRoot}guide/topics/manifest/activity-element.html">{@code &lt;activity>}</a> element.</p>
+
+<p>Because {@code DisplayMessageActivity} is invoked using an explicit intent, it does not require
+any intent filters (such as those you can see in the manifest for <code>MyFirstActivity</code>). So
+the declaration for <code>DisplayMessageActivity</code> can be simply one line of code inside the <a
+href="{@docRoot}guide/topics/manifest/application-element.html">{@code &lt;application>}</a>
+element:</p>
+
+<pre>
+&lt;application ... >
+    &lt;activity android:name="com.example.myapp.DisplayMessageActivity" />
+    ...
+&lt;/application>
+</pre>
+
+<p>The app is now runnable because the {@link android.content.Intent} in the
+first activity now resolves to the {@code DisplayMessageActivity} class. If you run the app now,
+pressing the Send button starts the
+second activity, but it doesn't show anything yet.</p>
+
+
+<h2 id="ReceiveIntent">Receive the Intent</h2>
+
+<p>Every {@link android.app.Activity} is invoked by an {@link android.content.Intent}, regardless of
+how the user navigated there. You can get the {@link android.content.Intent} that started your
+activity by calling {@link android.app.Activity#getIntent()} and the retrieve data contained
+within it.</p>
+
+<p>In the {@code DisplayMessageActivity} class’s {@link android.app.Activity#onCreate onCreate()}
+method, get the intent and extract the message delivered by {@code MyFirstActivity}:</p>
+
+<pre>
+Intent intent = getIntent();
+String message = intent.getStringExtra(MyFirstActivity.EXTRA_MESSAGE);
+</pre>
+
+
+
+<h2 id="DisplayMessage">Display the Message</h2>
+
+<p>To show the message on the screen, create a {@link android.widget.TextView} widget and set the
+text using {@link android.widget.TextView#setText setText()}. Then add the {@link
+android.widget.TextView} as the root view of the activity’s layout by passing it to {@link
+android.app.Activity#setContentView setContentView()}.</p>
+
+<p>The complete {@link android.app.Activity#onCreate onCreate()} method for {@code
+DisplayMessageActivity} now looks like this:</p>
+
+<pre>
+&#64;Override
+public void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+
+    // Get the message from the intent
+    Intent intent = getIntent();
+    String message = intent.getStringExtra(MyFirstActivity.EXTRA_MESSAGE);
+
+    // Create the text view
+    TextView textView = new TextView(this);
+    textView.setTextSize(40);
+    textView.setText(message);
+
+    setContentView(textView);
+}
+</pre>
+
+<p>You can now run the app, type a message in the text box, press Send, and view the message on the
+second activity.</p>
+
+<img src="{@docRoot}images/training/firstapp/firstapp.png" />
+<p class="img-caption"><strong>Figure 1.</strong> Both activities in the final app, running
+on Android 4.0.
+
+<p>That's it, you've built your first Android app!</p>
+
+<p>To learn more about building Android apps, continue to follow the
+basic training classes. The next class is <a
+href="{@docRoot}training/activity-lifecycle/index.html">Managing the Activity Lifecycle</a>.</p>
+
+
+
+
diff --git a/docs/html/training/basics/supporting-devices/index.jd b/docs/html/training/basics/supporting-devices/index.jd
new file mode 100644
index 0000000..49ea81d
--- /dev/null
+++ b/docs/html/training/basics/supporting-devices/index.jd
@@ -0,0 +1,49 @@
+page.title=Supporting Different Devices
+
+trainingnavtop=true
+startpage=true
+next.title=Supporting Multiple Languages
+next.link=languages.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>Dependencies and prerequisites</h2>
+<ul>
+  <li>Android 1.6 or higher</li>
+</ul>
+
+<h2>You should also read</h2>
+<ul>
+  <li><a href="{@docRoot}guide/topics/resources/index.html">Application Resources</a></li>
+  <li><a href="{@docRoot}training/multiscreen/index.html">Designing for Multiple Screens</a></li>
+</ul>
+
+
+</div>
+</div>
+
+<p>Android devices come in many shapes and sizes all around the world. With a wide range of device
+types, you have an opportunity to reach a huge audience with your app. In order to be as successful
+as possible on Android, your app needs to adapt to various device configurations. Some of the
+important variations that you should consider include different languages, screen sizes, and
+versions of the Android platform.</p>
+
+<p>This class teaches you how to use basic platform features that leverage alternative
+resources and other features so your app can provide an optimized user experience on a
+variety of Android-compatible devices, using a single application package (APK).</p>
+
+<h2>Lessons</h2>
+ 
+<dl>
+  <dt><b><a href="languages.html">Supporting Different Languages</a></b></dt>
+  <dd>Learn how to support multiple languages with alternative string resources.</dd>
+  <dt><b><a href="screens.html">Supporting Different Screens</a></b></dt>
+  <dd>Learn how to optimize the user experience for different screen sizes and densities.</dd>
+  <dt><b><a href="platforms.html">Supporting Different Platform Versions</a></b></dt>
+  <dd>Learn how to use APIs available in new versions of Android while continuing to support
+older versions of Android.</dd>
+</dl> 
+
diff --git a/docs/html/training/basics/supporting-devices/languages.jd b/docs/html/training/basics/supporting-devices/languages.jd
new file mode 100644
index 0000000..fcc95c2
--- /dev/null
+++ b/docs/html/training/basics/supporting-devices/languages.jd
@@ -0,0 +1,134 @@
+page.title=Supporting Different Languages
+parent.title=Supporting Different Devices
+parent.link=index.html
+
+trainingnavtop=true
+next.title=Supporting Different Screens
+next.link=screens.html
+
+@jd:body
+
+
+<div id="tb-wrapper">
+  <div id="tb">
+    <h2>This class teaches you to</h2>
+    <ol>
+      <li><a href="#CreateDirs">Create Locale Directories and String Files</a></li>
+      <li><a href="#UseString">Use the String Resources</a></li>
+    </ol>
+    <h2>You should also read</h2>
+    <ul>
+      <li><a href="{@docRoot}guide/topics/resources/localization.html">Localization</a></li>
+    </ul>
+  </div>
+</div>
+
+<p>It’s always a good practice to extract UI strings from your app code and keep them
+in an external file.  Android makes this easy with a resources directory in each Android
+project.</p>
+
+<p>If you created your project using the Android SDK
+Tools (read <a href="{@docRoot}training/basics/firstapp/creating-project.html">Creating an
+Android Project</a>), the tools create a <code>res/</code> directory in the top level of
+the project. Within this <code>res/</code> directory are subdirectories for various resource
+types. There are also a few default files such as <code>res/values/strings.xml</code>, which holds
+your string values.</p>
+
+
+<h2 id="CreateDirs">Create Locale Directories and String Files</h2> 
+
+<p>To add support for more languages, create additional <code>values</code> directories inside
+<code>res/</code> that include a hyphen and the ISO country code at the end of the
+directory name. For example, <code>values-es/</code> is the directory containing simple
+resourcess for the Locales with the language code "es".  Android loads the appropriate resources
+according to the locale settings of the device at run time.</p>
+
+<p>Once you’ve decided on the languages you will support, create the resource subdirectories and
+string resource files. For example:</p>
+
+<pre class="classic no-pretty-print">
+MyProject/
+    res/
+       values/
+           strings.xml
+       values-es/
+           strings.xml
+       values-fr/
+           strings.xml
+</pre>
+
+<p>Add the string values for each locale into the appropriate file.</p>
+
+<p>At runtime, the Android system uses the appropriate set of string resources based on the
+locale currently set for the user's device.</p>
+  
+<p>For example, the following are some different string resource files for different languages.</p>
+
+
+<p>English (default locale), <code>/values/strings.xml</code>:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;resources>
+    &lt;string name="title">My Application&lt;/string>
+    &lt;string name="hello_world">Hello World!&lt;/string>
+&lt;/resources>
+</pre>
+
+
+<p>Spanish, <code>/values-es/strings.xml</code>:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;resources>
+    &lt;string name="title">Mi Aplicación&lt;/string>
+    &lt;string name="hello_world">Hola Mundo!&lt;/string>
+&lt;/resources>
+</pre>
+
+
+<p>French, <code>/values-fr/strings.xml</code>:</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?>
+&lt;resources>
+    &lt;string name="title">Ma Application&lt;/string>
+    &lt;string name="hello_world">Bonjour tout le Monde!&lt;/string>
+&lt;/resources>
+</pre>
+
+
+<h2 id="UseString">Use the String Resources</h2>
+
+<p>You can reference your string resources in your source code and other XML files using the
+resource name defined by the {@code &lt;string>} element's {@code name} attribute.</p>
+
+<p>In your source code, you can refer to a string resource with the syntax {@code
+R.string.&lt;string_name>}. There are a variety of methods that accept a string resource this
+way.</p>
+  
+<p>For example:</p>
+
+<pre>
+// Get a string resource from your app's {@link android.content.res.Resources}
+String hello = {@link android.content.Context#getResources()}.getString(R.string.hello_world);
+
+// Or supply a string resource to a method that requires a string
+TextView textView = new TextView(this);
+textView.setText(R.string.hello_world);
+</pre>
+
+<p>In other XML files, you can refer to a string resource with the syntax {@code
+&#64;string/&lt;string_name>} whenever the XML attribute accepts a string value.</p>
+
+<p>For example:</p>
+
+<pre>
+&lt;TextView
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:text="@string/hello_world" />
+</pre>
+
+
+
diff --git a/docs/html/training/basics/supporting-devices/platforms.jd b/docs/html/training/basics/supporting-devices/platforms.jd
new file mode 100644
index 0000000..0d4e7d9
--- /dev/null
+++ b/docs/html/training/basics/supporting-devices/platforms.jd
@@ -0,0 +1,138 @@
+page.title=Supporting Different Platform Versions
+parent.title=Supporting Different Devices
+parent.link=index.html
+
+trainingnavtop=true
+previous.title=Supporting Different Screens
+previous.link=screens.html
+
+@jd:body
+
+
+<div id="tb-wrapper">
+  <div id="tb">
+    
+    <h2>This lesson teaches you to</h2>
+    <ol>
+      <li><a href="#sdk-versions">Specify Minimum and Target API Levels</a></li>
+      <li><a href="#version-codes">Check System Version at Runtime</a></li>
+      <li><a href="#style-themes">Use Platform Styles and Themes</a></li>
+    </ol>
+    
+    <h2>You should also read</h2>
+    <ul>
+      <li><a href="{@docRoot}guide/appendix/api-levels.html">Android API Levels</a></li>
+      <li><a
+href="{@docRoot}sdk/compatibility-library.html">Android Support Library</a></li>
+    </ul>
+  </div>
+</div>
+
+<p>While the latest versions of Android often provide great APIs for your app, you should continue 
+to support older versions of Android until more devices get updated. This 
+lesson shows you how to take advantage of the latest APIs while continuing to support older 
+versions as well.</p>
+
+<p>The dashboard for <a
+href="http://developer.android.com/resources/dashboard/platform-versions.html">Platform Versions</a>
+is updated regularly to show the distribution of active 
+devices running each version of Android, based on the number of devices that visit the Google Play 
+Store.  Generally, it’s a good practice to support about 90% of the active devices, while 
+targeting your app to the latest version.</p>
+
+<p class="note"><strong>Tip:</strong> In order to provide the best features and 
+functionality across several Android versions, you should use the <a
+href="{@docRoot}sdk/compatibility-library.html">Android Support Library</a> in your app,
+which allows you to use several recent platform APIs on older versions.</p>
+
+
+
+<h2 id="sdk-versions">Specify Minimum and Target API Levels</h2>
+
+<p>The <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a> file
+describes details about your app and 
+identifies which versions of Android it supports.   Specifically, the <code>minSdkVersion</code> 
+and <code>targetSdkVersion</code> attributes for the <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">{@code &lt;uses-sdk}</a> element
+identify the lowest API level with which your app is compatible and the highest API level against
+which you’ve designed and tested your app.</p>
+
+<p>For example:</p>
+
+<pre>
+&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android" ... >
+    &lt;uses-sdk android:minSdkVersion="4" android:targetSdkVersion="15" />
+    ...
+&lt;/manifest>
+</pre>
+
+<p>As new versions of Android are released, some style and behaviors may change. 
+To allow your app to take advantage of these changes and ensure that your app fits the style of
+each user's device, you should set the 
+<a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code targetSdkVersion}</a>
+value to match the latest Android version
+available.</p>
+
+
+
+<h2 id="version-codes">Check System Version at Runtime</h2>
+
+<p>Android provides a unique code for each platform version in the {@link android.os.Build}
+constants class. Use these codes within your app to build conditions that ensure the code that
+depends on higher API levels is executed only when those APIs are available on the system.</p>
+
+<pre>
+private void setUpActionBar() {
+    // Make sure we're running on Honeycomb or higher to use ActionBar APIs
+    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+        ActionBar actionBar = getActionBar();
+        actionBar.setDisplayHomeAsUpEnabled(true);
+    }
+}
+</pre>
+
+
+
+<p class="note"><strong>Note:</strong> When parsing XML resources, Android ignores XML 
+attributes that aren’t supported by the current device. So you can safely use XML attributes that
+are only supported by newer versions without worrying about older versions breaking when they
+encounter that code. For example, if you set the 
+<code>targetSdkVersion="11"</code>, your app includes the {@link android.app.ActionBar} by default
+on Android 3.0 and higher. To then add menu items to the action bar, you need to set 
+<code>android:showAsAction="ifRoom"</code> in your menu resource XML. It's safe to do this 
+in a cross-version XML file, because the older versions of Android simply ignore the 
+<code>showAsAction</code> attribute (that is, you <em>do not</em> need a separate 
+version in <code>res/menu-v11/</code>).</p>
+
+
+
+<h2 id="style-themes">Use Platform Styles and Themes</h2> 
+
+<p>Android provides user experience themes that give apps the look and feel of the 
+underlying operating system.  These themes can be applied to your app within the 
+manifest file.  By using these built in styles and themes, your app will 
+naturally follow the latest look and feel of Android with each new release.</p>
+
+<p>To make your activity look like a dialog box:</p>
+
+<pre>&lt;activity android:theme="@android:style/Theme.Dialog"></pre>
+
+<p>To make your activity have a transparent background:</p>
+
+<pre>&lt;activity android:theme="@android:style/Theme.Translucent"></pre>
+
+<p>To apply your own custom theme defined in <code>/res/values/styles.xml</code>:</p>
+
+<pre>&lt;activity android:theme="@style/CustomTheme"></pre>
+
+<p>To apply a theme to your entire app (all activities), add the <code>android:theme</code>
+attribute 
+to the <a href="{@docRoot}guide/topics/manifest/application-element.html">{@code
+&lt;application>}</a> element:</p>
+
+<pre>&lt;application android:theme="@style/CustomTheme"></pre>
+
+<p>For more about creating and using themes, read the <a
+href="{@docRoot}guide/topics/ui/themes.html">Styles and Themes</a> guide.</p>
+
diff --git a/docs/html/training/basics/supporting-devices/screens.jd b/docs/html/training/basics/supporting-devices/screens.jd
new file mode 100644
index 0000000..8697cd5
--- /dev/null
+++ b/docs/html/training/basics/supporting-devices/screens.jd
@@ -0,0 +1,180 @@
+page.title=Supporting Different Screens
+parent.title=Supporting Different Devices
+parent.link=index.html
+
+trainingnavtop=true
+previous.title=Supporting Different Languages
+previous.link=languages.html
+next.title=Supporting Different Platform Versions
+next.link=platforms.html
+
+@jd:body
+
+<div id="tb-wrapper">
+  <div id="tb">
+    
+    <h2>This lesson teaches you to</h2>
+    <ol>
+      <li><a href="#create-layouts">Create Different Layouts</a></li>
+      <li><a href="#create-bitmaps">Create Different Bitmaps</a></li>
+    </ol>
+    
+    <h2>You should also read</h2>
+    <ul>
+      <li><a href="{@docRoot}training/multiscreen/index.html">Designing for Multiple
+Screens</a></li>
+      <li><a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple
+Screens</a></li>
+      <li><a href="{@docRoot}design/style/iconography.html">Iconography design guide</a></li>
+    </ul>
+  </div>
+</div>
+
+<p>Android categorizes device screens using two general properties:  size and density.  You should 
+expect that your app will be installed on devices with screens that range in both size 
+and density. As such, you should include some alternative resources that optimize your app’s 
+appearance for different screen sizes and densities.</p>
+
+<ul>
+  <li>There are four generalized sizes: small, normal, large, xlarge</li>
+  <li>And four generalized densities: low (ldpi), medium (mdpi), high (hdpi), extra high
+(xhdpi)</li>
+</ul>
+
+<p>To declare different layouts and bitmaps you'd like to use for different screens, you must place
+these alternative resources in separate directories, similar to how you do for different language
+strings.</p>
+
+<p>Also be aware that the screens orientation (landscape or portrait) is considered a variation of
+screen size, so many apps should revise the layout to optimize the user experience in each
+orientation.</p>
+
+
+<h2 id="create-layouts">Create Different Layouts</h2> 
+
+<p>To optimize your user experience on different screen sizes, you should create a unique layout XML
+file for each screen size you want to support. Each layout should be 
+saved into the appropriate resources directory, named with a <code>-&lt;screen_size></code> 
+suffix.  For example, a unique layout for large screens should be saved under 
+<code>res/layout-large/</code>.</p>
+
+<p class="note"><strong>Note:</strong> Android automatically scales your layout in order to
+properly fit the screen. Thus, your layouts for different screen sizes don't
+need to worry about the absolute size of UI elements but instead focus on the layout structure that
+affects the user experience (such as the size or position of important views relative to sibling
+views).</p>
+
+<p>For example, this project includes a default layout and an alternative layout for <em>large</em>
+screens:</p>
+
+<pre class="classic no-pretty-print">
+MyProject/
+    res/
+        layout/
+            main.xml
+        layout-large/
+            main.xml
+</pre>
+
+<p>The file names must be exactly the same, but their contents are different in order to provide
+an optimized UI for the corresponding screen size.</p>
+
+<p>Simply reference the layout file in your app as usual:</p>
+
+<pre>
+&#64;Override
+ protected void onCreate(Bundle savedInstanceState) {
+     super.onCreate(savedInstanceState);
+     setContentView(R.layout.main);
+}
+</pre>
+
+<p>The system loads the layout file from the appropriate layout directory based on screen size of 
+the device on which your app is running. More information about how Android selects the
+appropriate resource is available in the <a
+href="{@docRoot}guide/topics/resources/providing-resources.html#BestMatch">Providing Resources</a>
+guide.</p>
+
+<p>As another example, here's a project with an alternative layout for landscape orientation:</p>
+
+<pre class="classic no-pretty-print">
+MyProject/
+    res/
+        layout/
+            main.xml
+        layout-land/
+            main.xml
+</pre>
+
+<p>By default, the <code>layout/main.xml</code> file is used for portrait orientation.</p>
+
+<p>If you want a provide a special layout for landscape, including while on large screens, then
+you need to use both the <code>large</code> and <code>land</code> qualifier:</p>
+
+<pre class="classic no-pretty-print">
+MyProject/
+    res/
+        layout/              # default (portrait)
+            main.xml
+        layout-land/         # landscape
+            main.xml
+        layout-large/        # large (portrait)
+            main.xml
+        layout-large-land/   # large landscape
+            main.xml
+</pre>
+
+<p class="note"><strong>Note:</strong> Android 3.2 and above supports an advanced method of 
+defining screen sizes that allows you to specify resources for screen sizes based on
+the minimum width and height in terms of density-independent pixels. This lesson does not cover
+this new technique. For more information, read <a
+href="{@docRoot}training/multiscreen/index.html">Designing for Multiple
+Screens</a>.</p>
+
+
+ 
+<h2 id="create-bitmaps">Create Different Bitmaps</h2>
+
+<p>You should always provide bitmap resources that are properly scaled to each of the generalized
+density buckets: low, medium, high and extra-high density. This helps you achieve good graphical
+quality and performance on all screen densities.</p>
+
+<p>To generate these images, you should start with your raw resource in vector format and generate 
+the images for each density using the following size scale:</p>
+<ul>
+<li>xhdpi: 2.0</li>
+<li>hdpi: 1.5</li>
+<li>mdpi: 1.0 (baseline)</li>
+<li>ldpi: 0.75</li>
+</ul>
+
+<p>This means that if you generate a 200x200 image for xhdpi devices, you should generate the same 
+resource in 150x150 for hdpi, 100x100 for mdpi, and 75x75 for ldpi devices.</p>
+
+<p>Then, place the files in the appropriate drawable resource directory:</p>
+
+<pre class="classic no-pretty-print">
+MyProject/
+    res/
+        drawable-xhdpi/
+            awesomeimage.png
+        drawable-hdpi/
+            awesomeimage.png
+        drawable-mdpi/
+            awesomeimage.png
+        drawable-ldpi/
+            awesomeimage.png
+</pre>
+
+<p>Any time you reference <code>@drawable/awesomeimage</code>, the system selects the 
+appropriate bitmap based on the screen's density.</p>
+
+<p class="note"><strong>Note:</strong> Low-density (ldpi) resources aren’t always necessary.  When
+you provide hdpi assets, the system scales them down by one half to properly fit ldpi
+screens.</p>
+
+<p>For more tips and guidelines about creating icon assets for your app, see the 
+<a href="{@docRoot}design/style/iconography.html">Iconography design guide</a>.</p>
+
+
+
diff --git a/docs/html/training/tv/optimizing-layouts-tv.jd b/docs/html/training/tv/optimizing-layouts-tv.jd
index 6eac6d3..e4a8e69 100644
--- a/docs/html/training/tv/optimizing-layouts-tv.jd
+++ b/docs/html/training/tv/optimizing-layouts-tv.jd
@@ -16,7 +16,7 @@
   <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>
+  <li><a href="#HandleLargeBitmaps">Design to Handle Large Bitmaps</a></li>
 </ol>
 
 <h2>You should also read</h2>
diff --git a/docs/html/training/tv/optimizing-navigation-tv.jd b/docs/html/training/tv/optimizing-navigation-tv.jd
index 8b5878e..bb78258 100644
--- a/docs/html/training/tv/optimizing-navigation-tv.jd
+++ b/docs/html/training/tv/optimizing-navigation-tv.jd
@@ -5,7 +5,7 @@
 trainingnavtop=true
 previous.title=Optimizing Layouts for TV
 previous.link=optimizing-layouts-tv.html
-next.title=Handling features not supported on TV
+next.title=Handling Features Not Supported on TV
 next.link=unsupported-features-tv.html
 
 @jd:body
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index ed5b2f6..c726d0e 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -16,11 +16,9 @@
 
 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;
@@ -183,7 +181,7 @@
 
     /**
      * Sets the layout bounds as an array of left, top, right, bottom integers
-     * @param padding the array containing the padding values
+     * @param bounds the array containing the padding values
      *
      * @hide
      */
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index 0521e69..e101581 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -161,7 +161,31 @@
     public void updateTexImage() {
         int err = nativeUpdateTexImage(); 
         if (err != 0) {
-            throw new RuntimeException("Error during updateTexImage (see logs)");
+            throw new RuntimeException("Error during updateTexImage (see logcat for details)");
+        }
+    }
+
+    /**
+     * Detach the SurfaceTexture from the OpenGL ES context with which it is currently associated.
+     * This can be used to change from one OpenGL ES context to another.
+     *
+     * @hide
+     */
+    public void detachFromGLContext() {
+        int err = nativeDetachFromGLContext();
+        if (err != 0) {
+            throw new RuntimeException("Error during detachFromGLContext (see logcat for details)");
+        }
+    }
+
+    /**
+     *
+     * @hide
+     */
+    public void attachToGLContext(int texName) {
+        int err = nativeAttachToGLContext(texName);
+        if (err != 0) {
+            throw new RuntimeException("Error during detachFromGLContext (see logcat for details)");
         }
     }
 
@@ -269,6 +293,8 @@
     private native long nativeGetTimestamp();
     private native void nativeSetDefaultBufferSize(int width, int height);
     private native int nativeUpdateTexImage();
+    private native int nativeDetachFromGLContext();
+    private native int nativeAttachToGLContext(int texName);
     private native int nativeGetQueuedCount();
     private native void nativeRelease();
 
diff --git a/include/androidfw/Input.h b/include/androidfw/Input.h
index a4ebd95..f8cbdde 100644
--- a/include/androidfw/Input.h
+++ b/include/androidfw/Input.h
@@ -811,6 +811,31 @@
     VelocityTracker mVelocityTracker;
 };
 
+/*
+ * Identifies a device.
+ */
+struct InputDeviceIdentifier {
+    inline InputDeviceIdentifier() :
+            bus(0), vendor(0), product(0), version(0) {
+    }
+
+    // Information provided by the kernel.
+    String8 name;
+    String8 location;
+    String8 uniqueId;
+    uint16_t bus;
+    uint16_t vendor;
+    uint16_t product;
+    uint16_t version;
+
+    // A composite input device descriptor string that uniquely identifies the device
+    // even across reboots or reconnections.  The value of this field is used by
+    // upper layers of the input system to associate settings with individual devices.
+    // It is hashed from whatever kernel provided information is available.
+    // Ideally, the way this value is computed should not change between Android releases
+    // because that would invalidate persistent settings that rely on it.
+    String8 descriptor;
+};
 
 /*
  * Describes the characteristics and capabilities of an input device.
@@ -830,10 +855,11 @@
         float fuzz;
     };
 
-    void initialize(int32_t id, const String8& name);
+    void initialize(int32_t id, const String8& name, const String8& descriptor);
 
     inline int32_t getId() const { return mId; }
     inline const String8 getName() const { return mName; }
+    inline const String8 getDescriptor() const { return mDescriptor; }
     inline uint32_t getSources() const { return mSources; }
 
     const MotionRange* getMotionRange(int32_t axis, uint32_t source) const;
@@ -856,6 +882,7 @@
 private:
     int32_t mId;
     String8 mName;
+    String8 mDescriptor;
     uint32_t mSources;
     int32_t mKeyboardType;
     String8 mKeyCharacterMapFile;
@@ -863,23 +890,6 @@
     Vector<MotionRange> mMotionRanges;
 };
 
-/*
- * Identifies a device.
- */
-struct InputDeviceIdentifier {
-    inline InputDeviceIdentifier() :
-            bus(0), vendor(0), product(0), version(0) {
-    }
-
-    String8 name;
-    String8 location;
-    String8 uniqueId;
-    uint16_t bus;
-    uint16_t vendor;
-    uint16_t product;
-    uint16_t version;
-};
-
 /* Types of input device configuration files. */
 enum InputDeviceConfigurationFileType {
     INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION = 0,     /* .idc file */
diff --git a/libs/androidfw/Input.cpp b/libs/androidfw/Input.cpp
index da57839..2e4b26f 100644
--- a/libs/androidfw/Input.cpp
+++ b/libs/androidfw/Input.cpp
@@ -1226,21 +1226,24 @@
 // --- InputDeviceInfo ---
 
 InputDeviceInfo::InputDeviceInfo() {
-    initialize(-1, String8("uninitialized device info"));
+    initialize(-1, String8("uninitialized device info"), String8("unknown"));
 }
 
 InputDeviceInfo::InputDeviceInfo(const InputDeviceInfo& other) :
-        mId(other.mId), mName(other.mName), mSources(other.mSources),
+        mId(other.mId), mName(other.mName), mDescriptor(other.mDescriptor),
+        mSources(other.mSources),
         mKeyboardType(other.mKeyboardType),
+        mKeyCharacterMapFile(other.mKeyCharacterMapFile),
         mMotionRanges(other.mMotionRanges) {
 }
 
 InputDeviceInfo::~InputDeviceInfo() {
 }
 
-void InputDeviceInfo::initialize(int32_t id, const String8& name) {
+void InputDeviceInfo::initialize(int32_t id, const String8& name, const String8& descriptor) {
     mId = id;
     mName = name;
+    mDescriptor = descriptor;
     mSources = 0;
     mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
     mMotionRanges.clear();
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 39d2e39..2a908ab 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -260,7 +260,7 @@
             Rect localDirty(info.dirtyLeft, info.dirtyTop, info.dirtyRight, info.dirtyBottom);
             dirty.unionWith(localDirty);
 
-            if (result == DrawGlInfo::kStatusInvoke) {
+            if (result & DrawGlInfo::kStatusInvoke) {
                 mFunctors.push(f);
             }
         }
@@ -300,7 +300,7 @@
         Rect localDirty(info.dirtyLeft, info.dirtyTop, info.dirtyRight, info.dirtyBottom);
         dirty.unionWith(localDirty);
 
-        if (result == DrawGlInfo::kStatusInvoke) {
+        if (result & DrawGlInfo::kStatusInvoke) {
             mFunctors.push(functor);
         }
     }
diff --git a/libs/storage/Android.mk b/libs/storage/Android.mk
index b42c34f..7a9dd6c 100644
--- a/libs/storage/Android.mk
+++ b/libs/storage/Android.mk
@@ -7,10 +7,6 @@
 	IObbActionListener.cpp \
 	IMountService.cpp
 
-LOCAL_STATIC_LIBRARIES := \
-	libutils \
-	libbinder
-
 LOCAL_MODULE:= libstorage
 
 include $(BUILD_STATIC_LIBRARY)
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index c7e71eb..41d5c32 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2237,6 +2237,14 @@
      *  docking station
      */
     public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET;
+    /** {@hide} The audio output device code for a USB audio accessory. The accessory is in USB host
+     * mode and the Android device in USB device mode
+     */
+    public static final int DEVICE_OUT_USB_ACCESSORY = AudioSystem.DEVICE_OUT_USB_ACCESSORY;
+    /** {@hide} The audio output device code for a USB audio device. The device is in USB device
+     * mode and the Android device in USB host mode
+     */
+    public static final int DEVICE_OUT_USB_DEVICE = AudioSystem.DEVICE_OUT_USB_DEVICE;
     /** {@hide} This is not used as a returned value from {@link #getDevicesForStream}, but could be
      *  used in the future in a set method to select whatever default device is chosen by the
      *  platform-specific implementation.
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 2e456f0..48d3712 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -389,9 +389,11 @@
         intentFilter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED);
         intentFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED);
         intentFilter.addAction(Intent.ACTION_DOCK_EVENT);
-        intentFilter.addAction(Intent.ACTION_USB_ANLG_HEADSET_PLUG);
-        intentFilter.addAction(Intent.ACTION_USB_DGTL_HEADSET_PLUG);
+        intentFilter.addAction(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG);
+        intentFilter.addAction(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG);
         intentFilter.addAction(Intent.ACTION_HDMI_AUDIO_PLUG);
+        intentFilter.addAction(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG);
+        intentFilter.addAction(Intent.ACTION_USB_AUDIO_DEVICE_PLUG);
         intentFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
         intentFilter.addAction(Intent.ACTION_SCREEN_ON);
         intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
@@ -2800,6 +2802,28 @@
         }
     }
 
+    private boolean handleDeviceConnection(boolean connected, int device, String params) {
+        synchronized (mConnectedDevices) {
+            boolean isConnected = (mConnectedDevices.containsKey(device) &&
+                    mConnectedDevices.get(device).equals(params));
+
+            if (isConnected && !connected) {
+                AudioSystem.setDeviceConnectionState(device,
+                                              AudioSystem.DEVICE_STATE_UNAVAILABLE,
+                                              params);
+                 mConnectedDevices.remove(device);
+                 return true;
+            } else if (!isConnected && connected) {
+                 AudioSystem.setDeviceConnectionState(device,
+                                                      AudioSystem.DEVICE_STATE_AVAILABLE,
+                                                      params);
+                 mConnectedDevices.put(new Integer(device), params);
+                 return true;
+            }
+        }
+        return false;
+    }
+
     /* cache of the address of the last dock the device was connected to */
     private String mDockAddress;
 
@@ -2810,6 +2834,8 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
+            int device;
+            int state;
 
             if (action.equals(Intent.ACTION_DOCK_EVENT)) {
                 int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
@@ -2834,15 +2860,15 @@
                 }
                 AudioSystem.setForceUse(AudioSystem.FOR_DOCK, config);
             } else if (action.equals(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)) {
-                int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
+                state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
                                                BluetoothProfile.STATE_DISCONNECTED);
                 BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
 
                 handleA2dpConnectionStateChange(btDevice, state);
             } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
-                int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
+                state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
                                                BluetoothProfile.STATE_DISCONNECTED);
-                int device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
+                device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
                 String address = null;
 
                 BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
@@ -2868,129 +2894,56 @@
                     address = "";
                 }
 
-                synchronized (mConnectedDevices) {
-                    boolean isConnected = (mConnectedDevices.containsKey(device) &&
-                                           mConnectedDevices.get(device).equals(address));
-
+                boolean connected = (state == BluetoothProfile.STATE_CONNECTED);
+                if (handleDeviceConnection(connected, device, address)) {
                     synchronized (mScoClients) {
-                        if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
-                            AudioSystem.setDeviceConnectionState(device,
-                                                             AudioSystem.DEVICE_STATE_UNAVAILABLE,
-                                                             address);
-                            mConnectedDevices.remove(device);
+                        if (connected) {
+                            mBluetoothHeadsetDevice = btDevice;
+                        } else {
                             mBluetoothHeadsetDevice = null;
                             resetBluetoothSco();
-                        } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
-                            AudioSystem.setDeviceConnectionState(device,
-                                                                 AudioSystem.DEVICE_STATE_AVAILABLE,
-                                                                 address);
-                            mConnectedDevices.put(new Integer(device), address);
-                            mBluetoothHeadsetDevice = btDevice;
                         }
                     }
                 }
             } else if (action.equals(Intent.ACTION_HEADSET_PLUG)) {
-                int state = intent.getIntExtra("state", 0);
+                state = intent.getIntExtra("state", 0);
                 int microphone = intent.getIntExtra("microphone", 0);
 
-                synchronized (mConnectedDevices) {
-                    if (microphone != 0) {
-                        boolean isConnected =
-                            mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_WIRED_HEADSET);
-                        if (state == 0 && isConnected) {
-                            AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
-                                    AudioSystem.DEVICE_STATE_UNAVAILABLE,
-                                    "");
-                            mConnectedDevices.remove(AudioSystem.DEVICE_OUT_WIRED_HEADSET);
-                        } else if (state == 1 && !isConnected)  {
-                            AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
-                                    AudioSystem.DEVICE_STATE_AVAILABLE,
-                                    "");
-                            mConnectedDevices.put(
-                                    new Integer(AudioSystem.DEVICE_OUT_WIRED_HEADSET), "");
-                        }
-                    } else {
-                        boolean isConnected =
-                            mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
-                        if (state == 0 && isConnected) {
-                            AudioSystem.setDeviceConnectionState(
-                                    AudioSystem.DEVICE_OUT_WIRED_HEADPHONE,
-                                    AudioSystem.DEVICE_STATE_UNAVAILABLE,
-                                    "");
-                            mConnectedDevices.remove(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE);
-                        } else if (state == 1 && !isConnected)  {
-                            AudioSystem.setDeviceConnectionState(
-                                    AudioSystem.DEVICE_OUT_WIRED_HEADPHONE,
-                                    AudioSystem.DEVICE_STATE_AVAILABLE,
-                                    "");
-                            mConnectedDevices.put(
-                                    new Integer(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE), "");
-                        }
-                    }
+                if (microphone != 0) {
+                    device = AudioSystem.DEVICE_OUT_WIRED_HEADSET;
+                } else {
+                    device = AudioSystem.DEVICE_OUT_WIRED_HEADPHONE;
                 }
-            } else if (action.equals(Intent.ACTION_USB_ANLG_HEADSET_PLUG)) {
-                int state = intent.getIntExtra("state", 0);
-                Log.v(TAG, "Broadcast Receiver: Got ACTION_USB_ANLG_HEADSET_PLUG, state = "+state);
-                synchronized (mConnectedDevices) {
-                    boolean isConnected =
-                        mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET);
-                    if (state == 0 && isConnected) {
-                        AudioSystem.setDeviceConnectionState(
-                                                        AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET,
-                                                        AudioSystem.DEVICE_STATE_UNAVAILABLE,
-                                                        "");
-                        mConnectedDevices.remove(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET);
-                    } else if (state == 1 && !isConnected)  {
-                        AudioSystem.setDeviceConnectionState(
-                                                        AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET,
-                                                        AudioSystem.DEVICE_STATE_AVAILABLE,
-                                                        "");
-                        mConnectedDevices.put(
-                                new Integer(AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET), "");
-                    }
-                }
+                handleDeviceConnection((state == 1), device, "");
+            } else if (action.equals(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG)) {
+                state = intent.getIntExtra("state", 0);
+                Log.v(TAG, "Broadcast Receiver: Got ACTION_ANALOG_AUDIO_DOCK_PLUG, state = "+state);
+                handleDeviceConnection((state == 1), AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET, "");
             } else if (action.equals(Intent.ACTION_HDMI_AUDIO_PLUG)) {
-                int state = intent.getIntExtra("state", 0);
+                state = intent.getIntExtra("state", 0);
                 Log.v(TAG, "Broadcast Receiver: Got ACTION_HDMI_AUDIO_PLUG, state = "+state);
-                synchronized (mConnectedDevices) {
-                    boolean isConnected =
-                        mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_AUX_DIGITAL);
-                    if (state == 0 && isConnected) {
-                        AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_AUX_DIGITAL,
-                                                             AudioSystem.DEVICE_STATE_UNAVAILABLE,
-                                                             "");
-                        mConnectedDevices.remove(AudioSystem.DEVICE_OUT_AUX_DIGITAL);
-                    } else if (state == 1 && !isConnected)  {
-                        AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_AUX_DIGITAL,
-                                                             AudioSystem.DEVICE_STATE_AVAILABLE,
-                                                             "");
-                        mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_AUX_DIGITAL), "");
-                    }
-                }
-            } else if (action.equals(Intent.ACTION_USB_DGTL_HEADSET_PLUG)) {
-                int state = intent.getIntExtra("state", 0);
-                Log.v(TAG, "Broadcast Receiver: Got ACTION_USB_DGTL_HEADSET_PLUG, state = "+state);
-                synchronized (mConnectedDevices) {
-                    boolean isConnected =
-                        mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET);
-                    if (state == 0 && isConnected) {
-                        AudioSystem.setDeviceConnectionState(
-                                                         AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET,
-                                                         AudioSystem.DEVICE_STATE_UNAVAILABLE,
-                                                         "");
-                        mConnectedDevices.remove(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET);
-                    } else if (state == 1 && !isConnected)  {
-                        AudioSystem.setDeviceConnectionState(
-                                                         AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET,
-                                                         AudioSystem.DEVICE_STATE_AVAILABLE,
-                                                         "");
-                        mConnectedDevices.put(
-                                new Integer(AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET), "");
-                    }
-                }
+                handleDeviceConnection((state == 1), AudioSystem.DEVICE_OUT_AUX_DIGITAL, "");
+            } else if (action.equals(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG)) {
+                state = intent.getIntExtra("state", 0);
+                Log.v(TAG,
+                      "Broadcast Receiver Got ACTION_DIGITAL_AUDIO_DOCK_PLUG, state = " + state);
+                handleDeviceConnection((state == 1), AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET, "");
+            } else if (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ||
+                           action.equals(Intent.ACTION_USB_AUDIO_DEVICE_PLUG)) {
+                state = intent.getIntExtra("state", 0);
+                int alsaCard = intent.getIntExtra("card", -1);
+                int alsaDevice = intent.getIntExtra("device", -1);
+                String params = "card=" + alsaCard + ";device=" + alsaDevice;
+                device = action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ?
+                        AudioSystem.DEVICE_OUT_USB_ACCESSORY : AudioSystem.DEVICE_OUT_USB_DEVICE;
+                Log.v(TAG, "Broadcast Receiver: Got "
+                        + (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ?
+                              "ACTION_USB_AUDIO_ACCESSORY_PLUG" : "ACTION_USB_AUDIO_DEVICE_PLUG")
+                        + ", state = " + state + ", card: " + alsaCard + ", device: " + alsaDevice);
+                handleDeviceConnection((state == 1), device, params);
             } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
                 boolean broadcast = false;
-                int state = AudioManager.SCO_AUDIO_STATE_ERROR;
+                int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR;
                 synchronized (mScoClients) {
                     int btState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1);
                     // broadcast intent if the connection was initated by AudioService
@@ -3002,7 +2955,7 @@
                     }
                     switch (btState) {
                     case BluetoothHeadset.STATE_AUDIO_CONNECTED:
-                        state = AudioManager.SCO_AUDIO_STATE_CONNECTED;
+                        scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED;
                         if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL &&
                             mScoAudioState != SCO_STATE_DEACTIVATE_REQ &&
                             mScoAudioState != SCO_STATE_DEACTIVATE_EXT_REQ) {
@@ -3010,7 +2963,7 @@
                         }
                         break;
                     case BluetoothHeadset.STATE_AUDIO_DISCONNECTED:
-                        state = AudioManager.SCO_AUDIO_STATE_DISCONNECTED;
+                        scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED;
                         mScoAudioState = SCO_STATE_INACTIVE;
                         clearAllScoClients(0, false);
                         break;
@@ -3027,11 +2980,11 @@
                     }
                 }
                 if (broadcast) {
-                    broadcastScoConnectionState(state);
+                    broadcastScoConnectionState(scoAudioState);
                     //FIXME: this is to maintain compatibility with deprecated intent
                     // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate.
                     Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
-                    newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, state);
+                    newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, scoAudioState);
                     mContext.sendStickyBroadcast(newIntent);
                 }
             } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 18a00bc..9bafa5c 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -202,6 +202,9 @@
     public static final int DEVICE_OUT_AUX_DIGITAL = 0x400;
     public static final int DEVICE_OUT_ANLG_DOCK_HEADSET = 0x800;
     public static final int DEVICE_OUT_DGTL_DOCK_HEADSET = 0x1000;
+    public static final int DEVICE_OUT_USB_ACCESSORY = 0x2000;
+    public static final int DEVICE_OUT_USB_DEVICE = 0x4000;
+
     public static final int DEVICE_OUT_DEFAULT = 0x8000;
     public static final int DEVICE_OUT_ALL = (DEVICE_OUT_EARPIECE |
                                               DEVICE_OUT_SPEAKER |
@@ -216,10 +219,18 @@
                                               DEVICE_OUT_AUX_DIGITAL |
                                               DEVICE_OUT_ANLG_DOCK_HEADSET |
                                               DEVICE_OUT_DGTL_DOCK_HEADSET |
+                                              DEVICE_OUT_USB_ACCESSORY |
+                                              DEVICE_OUT_USB_DEVICE |
                                               DEVICE_OUT_DEFAULT);
     public static final int DEVICE_OUT_ALL_A2DP = (DEVICE_OUT_BLUETOOTH_A2DP |
                                                    DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES |
                                                    DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER);
+    public static final int DEVICE_OUT_ALL_SCO = (DEVICE_OUT_BLUETOOTH_SCO |
+                                                  DEVICE_OUT_BLUETOOTH_SCO_HEADSET |
+                                                  DEVICE_OUT_BLUETOOTH_SCO_CARKIT);
+    public static final int DEVICE_OUT_ALL_USB = (DEVICE_OUT_USB_ACCESSORY |
+                                                  DEVICE_OUT_USB_DEVICE);
+
     // input devices
     public static final int DEVICE_IN_COMMUNICATION = 0x10000;
     public static final int DEVICE_IN_AMBIENT = 0x20000;
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 66cea9d4..410383d 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -45,10 +45,16 @@
         public int mFlags;
     };
 
+    // The follow flag constants MUST stay in sync with their equivalents
+    // in MediaCodec.h !
     public static int FLAG_SYNCFRAME   = 1;
     public static int FLAG_CODECCONFIG = 2;
     public static int FLAG_EOS         = 4;
-    public static int FLAG_ENCRYPTED   = 8;
+
+    // The following mode constants MUST stay in sync with their equivalents
+    // in media/hardware/CryptoAPI.h !
+    public static int MODE_UNENCRYPTED = 0;
+    public static int MODE_AES_CTR     = 1;
 
     /** Instantiate a codec component by mime type. For decoder components
         this is the mime type of media that this decoder should be able to
@@ -176,6 +182,36 @@
             int index,
             int offset, int size, long presentationTimeUs, int flags);
 
+    /** Similar to {@link queueInputBuffer} but submits a buffer that is
+     *  potentially encrypted. The buffer's data is considered to be
+     *  partitioned into "subSamples", each subSample starts with a
+     *  (potentially empty) run of plain, unencrypted bytes followed
+     *  by a (also potentially empty) run of encrypted bytes.
+     *  @param numBytesOfClearData The number of leading unencrypted bytes in
+     *                             each subSample.
+     *  @param numBytesOfEncryptedData The number of trailing encrypted bytes
+     *                             in each subSample.
+     *  @param numSubSamples    The number of subSamples that make up the
+     *                          buffer's contents.
+     *  @param key              A 16-byte opaque key
+     *  @param iv               A 16-byte initialization vector
+     *  @param mode             The type of encryption that has been applied
+     *
+     *  Either numBytesOfClearData or numBytesOfEncryptedData (but not both)
+     *  can be null to indicate that all respective sizes are 0.
+     */
+    public native final void queueSecureInputBuffer(
+            int index,
+            int offset,
+            int[] numBytesOfClearData,
+            int[] numBytesOfEncryptedData,
+            int numSubSamples,
+            byte[] key,
+            byte[] iv,
+            int mode,
+            long presentationTimeUs,
+            int flags);
+
     // Returns the index of an input buffer to be filled with valid data
     // or -1 if no such buffer is currently available.
     // This method will return immediately if timeoutUs == 0, wait indefinitely
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 217216a..01d3833 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -126,6 +126,21 @@
     return mCodec->queueInputBuffer(index, offset, size, timeUs, flags);
 }
 
+status_t JMediaCodec::queueSecureInputBuffer(
+        size_t index,
+        size_t offset,
+        const CryptoPlugin::SubSample *subSamples,
+        size_t numSubSamples,
+        const uint8_t key[16],
+        const uint8_t iv[16],
+        CryptoPlugin::Mode mode,
+        int64_t presentationTimeUs,
+        uint32_t flags) {
+    return mCodec->queueSecureInputBuffer(
+            index, offset, subSamples, numSubSamples, key, iv, mode,
+            presentationTimeUs, flags);
+}
+
 status_t JMediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
     return mCodec->dequeueInputBuffer(index, timeoutUs);
 }
@@ -367,6 +382,125 @@
     throwExceptionAsNecessary(env, err);
 }
 
+static void android_media_MediaCodec_queueSecureInputBuffer(
+        JNIEnv *env,
+        jobject thiz,
+        jint index,
+        jint offset,
+        jintArray numBytesOfClearDataObj,
+        jintArray numBytesOfEncryptedDataObj,
+        jint numSubSamples,
+        jbyteArray keyObj,
+        jbyteArray ivObj,
+        jint mode,
+        jlong timestampUs,
+        jint flags) {
+    ALOGV("android_media_MediaCodec_queueSecureInputBuffer");
+
+    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
+
+    if (codec == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+
+    status_t err = OK;
+
+    CryptoPlugin::SubSample *subSamples = NULL;
+    jbyte *key = NULL;
+    jbyte *iv = NULL;
+
+    if (numSubSamples <= 0) {
+        err = -EINVAL;
+    } else if (numBytesOfClearDataObj == NULL
+            && numBytesOfEncryptedDataObj == NULL) {
+        err = -EINVAL;
+    } else if (numBytesOfEncryptedDataObj != NULL
+            && env->GetArrayLength(numBytesOfEncryptedDataObj) < numSubSamples) {
+        err = -ERANGE;
+    } else if (numBytesOfClearDataObj != NULL
+            && env->GetArrayLength(numBytesOfClearDataObj) < numSubSamples) {
+        err = -ERANGE;
+    } else {
+        jboolean isCopy;
+
+        jint *numBytesOfClearData =
+            (numBytesOfClearDataObj == NULL)
+                ? NULL
+                : env->GetIntArrayElements(numBytesOfClearDataObj, &isCopy);
+
+        jint *numBytesOfEncryptedData =
+            (numBytesOfEncryptedDataObj == NULL)
+                ? NULL
+                : env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy);
+
+        subSamples = new CryptoPlugin::SubSample[numSubSamples];
+
+        for (jint i = 0; i < numSubSamples; ++i) {
+            subSamples[i].mNumBytesOfClearData =
+                (numBytesOfClearData == NULL) ? 0 : numBytesOfClearData[i];
+
+            subSamples[i].mNumBytesOfEncryptedData =
+                (numBytesOfEncryptedData == NULL)
+                    ? 0 : numBytesOfEncryptedData[i];
+        }
+
+        if (numBytesOfEncryptedData != NULL) {
+            env->ReleaseIntArrayElements(
+                    numBytesOfEncryptedDataObj, numBytesOfEncryptedData, 0);
+            numBytesOfEncryptedData = NULL;
+        }
+
+        if (numBytesOfClearData != NULL) {
+            env->ReleaseIntArrayElements(
+                    numBytesOfClearDataObj, numBytesOfClearData, 0);
+            numBytesOfClearData = NULL;
+        }
+    }
+
+    if (err == OK && keyObj != NULL) {
+        if (env->GetArrayLength(keyObj) != 16) {
+            err = -EINVAL;
+        } else {
+            jboolean isCopy;
+            key = env->GetByteArrayElements(keyObj, &isCopy);
+        }
+    }
+
+    if (err == OK && ivObj != NULL) {
+        if (env->GetArrayLength(ivObj) != 16) {
+            err = -EINVAL;
+        } else {
+            jboolean isCopy;
+            iv = env->GetByteArrayElements(ivObj, &isCopy);
+        }
+    }
+
+    if (err == OK) {
+        err = codec->queueSecureInputBuffer(
+                index, offset,
+                subSamples, numSubSamples,
+                (const uint8_t *)key, (const uint8_t *)iv,
+                (CryptoPlugin::Mode)mode,
+                timestampUs, flags);
+    }
+
+    if (iv != NULL) {
+        env->ReleaseByteArrayElements(ivObj, iv, 0);
+        iv = NULL;
+    }
+
+    if (key != NULL) {
+        env->ReleaseByteArrayElements(keyObj, key, 0);
+        key = NULL;
+    }
+
+    delete[] subSamples;
+    subSamples = NULL;
+
+    throwExceptionAsNecessary(env, err);
+}
+
 static jint android_media_MediaCodec_dequeueInputBuffer(
         JNIEnv *env, jobject thiz, jlong timeoutUs) {
     ALOGV("android_media_MediaCodec_dequeueInputBuffer");
@@ -532,6 +666,9 @@
     { "queueInputBuffer", "(IIIJI)V",
       (void *)android_media_MediaCodec_queueInputBuffer },
 
+    { "queueSecureInputBuffer", "(II[I[II[B[BIJI)V",
+      (void *)android_media_MediaCodec_queueSecureInputBuffer },
+
     { "dequeueInputBuffer", "(J)I",
       (void *)android_media_MediaCodec_dequeueInputBuffer },
 
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index 6bb4071..570c33b 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -19,6 +19,7 @@
 
 #include "jni.h"
 
+#include <media/hardware/CryptoAPI.h>
 #include <media/stagefright/foundation/ABase.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
@@ -53,6 +54,17 @@
             size_t index,
             size_t offset, size_t size, int64_t timeUs, uint32_t flags);
 
+    status_t queueSecureInputBuffer(
+            size_t index,
+            size_t offset,
+            const CryptoPlugin::SubSample *subSamples,
+            size_t numSubSamples,
+            const uint8_t key[16],
+            const uint8_t iv[16],
+            CryptoPlugin::Mode mode,
+            int64_t presentationTimeUs,
+            uint32_t flags);
+
     status_t dequeueInputBuffer(size_t *index, int64_t timeoutUs);
 
     status_t dequeueOutputBuffer(
diff --git a/obex/MODULE_LICENSE_BSD_LIKE b/obex/MODULE_LICENSE_BSD_LIKE
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/obex/MODULE_LICENSE_BSD_LIKE
diff --git a/obex/NOTICE b/obex/NOTICE
new file mode 100644
index 0000000..92e8e59
--- /dev/null
+++ b/obex/NOTICE
@@ -0,0 +1,29 @@
+Copyright (c) 2008-2009, Motorola, Inc.
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+- Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+- Neither the name of the Motorola, Inc. nor the names of its contributors
+may be used to endorse or promote products derived from this software
+without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index b1aaade..0ba8cce 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -26,6 +26,7 @@
     android:orientation="vertical"
     android:focusable="true"
     android:descendantFocusability="afterDescendants"
+    android:fitsSystemWindows="true"
     >
 
     <LinearLayout android:id="@+id/icons"
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 5ba72c7..804ae06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -591,10 +591,14 @@
         }
 
         final StatusBarNotification oldNotification = oldEntry.notification;
-        final RemoteViews oldContentView = oldNotification.notification.contentView;
 
-        final RemoteViews contentView = notification.notification.contentView;
-
+        // XXX: modify when we do something more intelligent with the two content views
+        final RemoteViews oldContentView = (oldNotification.notification.bigContentView != null) 
+                ? oldNotification.notification.bigContentView
+                : oldNotification.notification.contentView;
+        final RemoteViews contentView = (notification.notification.bigContentView != null) 
+                ? notification.notification.bigContentView
+                : notification.notification.contentView;
 
         if (DEBUG) {
             Slog.d(TAG, "old notification: when=" + oldNotification.notification.when
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index cc07240..0c8208f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -23,6 +23,7 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.Canvas;
 import android.graphics.RectF;
+import android.hardware.input.InputManager;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.ServiceManager;
@@ -47,7 +48,6 @@
     final float GLOW_MAX_SCALE_FACTOR = 1.8f;
     final float BUTTON_QUIESCENT_ALPHA = 0.6f;
 
-    IWindowManager mWindowManager;
     long mDownTime;
     int mCode;
     int mTouchSlop;
@@ -93,9 +93,6 @@
         
         a.recycle();
 
-        mWindowManager = IWindowManager.Stub.asInterface(
-                ServiceManager.getService(Context.WINDOW_SERVICE));
-
         setClickable(true);
         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
     }
@@ -276,12 +273,7 @@
                 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
                 flags | KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
                 InputDevice.SOURCE_KEYBOARD);
-        try {
-            //Slog.d(TAG, "injecting event " + ev);
-            mWindowManager.injectInputEventNoWait(ev);
-        } catch (RemoteException ex) {
-            // System process is dead
-        }
+        InputManager.injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
     }
 }
 
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 49b1a14..ba51108 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -867,9 +867,14 @@
         }
 
         final StatusBarNotification oldNotification = oldEntry.notification;
-        final RemoteViews oldContentView = oldNotification.notification.contentView;
 
-        final RemoteViews contentView = notification.notification.contentView;
+        // XXX: modify when we do something more intelligent with the two content views
+        final RemoteViews oldContentView = (oldNotification.notification.bigContentView != null) 
+                ? oldNotification.notification.bigContentView
+                : oldNotification.notification.contentView;
+        final RemoteViews contentView = (notification.notification.bigContentView != null) 
+                ? notification.notification.bigContentView
+                : notification.notification.contentView;
 
         if (DEBUG) {
             Slog.d(TAG, "old notification: when=" + oldNotification.notification.when
@@ -1322,14 +1327,6 @@
         }
     }
 
-    private void sendKey(KeyEvent key) {
-        try {
-            if (DEBUG) Slog.d(TAG, "injecting key event: " + key);
-            mWindowManager.injectInputEventNoWait(key);
-        } catch (RemoteException ex) {
-        }
-    }
-
     private View.OnClickListener mOnClickListener = new View.OnClickListener() {
         public void onClick(View v) {
             if (v == mRecentButton) {
diff --git a/policy/src/com/android/internal/policy/impl/FaceUnlock.java b/policy/src/com/android/internal/policy/impl/FaceUnlock.java
new file mode 100644
index 0000000..2ae99e6
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/FaceUnlock.java
@@ -0,0 +1,375 @@
+/*
+ * 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.internal.policy.impl;
+
+import com.android.internal.R;
+import com.android.internal.policy.IFaceLockCallback;
+import com.android.internal.policy.IFaceLockInterface;
+import com.android.internal.widget.LockPatternUtils;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+import android.view.View;
+
+public class FaceUnlock implements Handler.Callback {
+
+    private static final boolean DEBUG = false;
+    private static final String TAG = "FULLockscreen";
+
+    private final Context mContext;
+    private final KeyguardUpdateMonitor mUpdateMonitor;
+
+    private IFaceLockInterface mService;
+    private boolean mBoundToService = false;
+    private View mAreaView;
+
+    private Handler mHandler;
+    private final int MSG_SHOW_AREA_VIEW = 0;
+    private final int MSG_HIDE_AREA_VIEW = 1;
+
+    private boolean mServiceRunning = false;
+    private final Object mServiceRunningLock = new Object();
+
+    // Long enough to stay visible while dialer comes up
+    // Short enough to not be visible if the user goes back immediately
+    private final int VIEW_AREA_EMERGENCY_DIALER_TIMEOUT = 1000;
+
+    // Long enough to stay visible while the service starts
+    // Short enough to not have to wait long for backup if service fails to start or crashes
+    // The service can take a couple of seconds to start on the first try after boot
+    private final int VIEW_AREA_SERVICE_TIMEOUT = 3000;
+
+    // So the user has a consistent amount of time when brought to the backup method from FaceLock
+    private final int BACKUP_LOCK_TIMEOUT = 5000;
+
+    /**
+     * Used to lookup the state of the lock pattern
+     */
+    private final LockPatternUtils mLockPatternUtils;
+
+    KeyguardScreenCallback mKeyguardScreenCallback;
+
+    public FaceUnlock(Context context, KeyguardUpdateMonitor updateMonitor,
+            LockPatternUtils lockPatternUtils, KeyguardScreenCallback keyguardScreenCallback) {
+        mContext = context;
+        mUpdateMonitor = updateMonitor;
+        mLockPatternUtils = lockPatternUtils;
+        mKeyguardScreenCallback = keyguardScreenCallback;
+        mHandler = new Handler(this);
+    }
+
+    public void cleanUp() {
+        if (mService != null) {
+            try {
+                mService.unregisterCallback(mFaceLockCallback);
+            } catch (RemoteException e) {
+                // Not much we can do
+            }
+            stop();
+            mService = null;
+        }
+    }
+
+    /** When screen is turned on and focused, need to bind to FaceLock service if we are using
+     *  FaceLock, but only if we're not dealing with a call
+    */
+    public void activateIfAble(boolean hasOverlay) {
+        final boolean tooManyFaceUnlockTries = mUpdateMonitor.getMaxFaceUnlockAttemptsReached();
+        final int failedBackupAttempts = mUpdateMonitor.getFailedAttempts();
+        final boolean backupIsTimedOut =
+                (failedBackupAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT);
+        if (tooManyFaceUnlockTries) Log.i(TAG, "tooManyFaceUnlockTries: " + tooManyFaceUnlockTries);
+        if (mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE
+                && installedAndSelected()
+                && !hasOverlay
+                && !tooManyFaceUnlockTries
+                && !backupIsTimedOut) {
+            bind();
+
+            // Show FaceLock area, but only for a little bit so lockpattern will become visible if
+            // FaceLock fails to start or crashes
+            showAreaWithTimeout(VIEW_AREA_SERVICE_TIMEOUT);
+
+            // When switching between portrait and landscape view while FaceLock is running, the
+            // screen will eventually go dark unless we poke the wakelock when FaceLock is
+            // restarted
+            mKeyguardScreenCallback.pokeWakelock();
+        } else {
+            hideArea();
+        }
+    }
+
+    public boolean isServiceRunning() {
+        return mServiceRunning;
+    }
+
+    public int viewAreaEmergencyDialerTimeout() {
+        return VIEW_AREA_EMERGENCY_DIALER_TIMEOUT;
+    }
+
+    // Indicates whether FaceLock is in use
+    public boolean installedAndSelected() {
+        return (mLockPatternUtils.usingBiometricWeak() &&
+                mLockPatternUtils.isBiometricWeakInstalled());
+    }
+
+    // Takes care of FaceLock area when layout is created
+    public void initializeAreaView(View view) {
+        if (installedAndSelected()) {
+            mAreaView = view.findViewById(R.id.faceLockAreaView);
+            if (mAreaView == null) {
+                Log.e(TAG, "Layout does not have areaView and FaceLock is enabled");
+            }
+        } else {
+            mAreaView = null; // Set to null if not using FaceLock
+        }
+    }
+
+    // Stops FaceLock if it is running and reports back whether it was running or not
+    public boolean stopIfRunning() {
+        if (installedAndSelected() && mBoundToService) {
+            stopAndUnbind();
+            return true;
+        }
+        return false;
+    }
+
+    // Handles covering or exposing FaceLock area on the client side when FaceLock starts or stops
+    // This needs to be done in a handler because the call could be coming from a callback from the
+    // FaceLock service that is in a thread that can't modify the UI
+    @Override
+    public boolean handleMessage(Message msg) {
+        switch (msg.what) {
+        case MSG_SHOW_AREA_VIEW:
+            if (mAreaView != null) {
+                mAreaView.setVisibility(View.VISIBLE);
+            }
+            break;
+        case MSG_HIDE_AREA_VIEW:
+            if (mAreaView != null) {
+                mAreaView.setVisibility(View.INVISIBLE);
+            }
+            break;
+        default:
+            Log.w(TAG, "Unhandled message");
+            return false;
+        }
+        return true;
+    }
+
+    // Removes show and hide messages from the message queue
+    private void removeAreaDisplayMessages() {
+        mHandler.removeMessages(MSG_SHOW_AREA_VIEW);
+        mHandler.removeMessages(MSG_HIDE_AREA_VIEW);
+    }
+
+    // Shows the FaceLock area immediately
+    public void showArea() {
+        // Remove messages to prevent a delayed hide message from undo-ing the show
+        removeAreaDisplayMessages();
+        mHandler.sendEmptyMessage(MSG_SHOW_AREA_VIEW);
+    }
+
+    // Hides the FaceLock area immediately
+    public void hideArea() {
+        // Remove messages to prevent a delayed show message from undo-ing the hide
+        removeAreaDisplayMessages();
+        mHandler.sendEmptyMessage(MSG_HIDE_AREA_VIEW);
+    }
+
+    // Shows the FaceLock area for a period of time
+    public void showAreaWithTimeout(long timeoutMillis) {
+        showArea();
+        mHandler.sendEmptyMessageDelayed(MSG_HIDE_AREA_VIEW, timeoutMillis);
+    }
+
+    // Binds to FaceLock service.  This call does not tell it to start, but it causes the service
+    // to call the onServiceConnected callback, which then starts FaceLock.
+    public void bind() {
+        if (installedAndSelected()) {
+            if (!mBoundToService) {
+                if (DEBUG) Log.d(TAG, "before bind to FaceLock service");
+                mContext.bindService(new Intent(IFaceLockInterface.class.getName()),
+                        mConnection,
+                        Context.BIND_AUTO_CREATE);
+                if (DEBUG) Log.d(TAG, "after bind to FaceLock service");
+                mBoundToService = true;
+            } else {
+                Log.w(TAG, "Attempt to bind to FaceLock when already bound");
+            }
+        }
+    }
+
+    // Tells FaceLock to stop and then unbinds from the FaceLock service
+    public void stopAndUnbind() {
+        if (installedAndSelected()) {
+            stop();
+
+            if (mBoundToService) {
+                if (DEBUG) Log.d(TAG, "before unbind from FaceLock service");
+                if (mService != null) {
+                    try {
+                        mService.unregisterCallback(mFaceLockCallback);
+                    } catch (RemoteException e) {
+                        // Not much we can do
+                    }
+                }
+                mContext.unbindService(mConnection);
+                if (DEBUG) Log.d(TAG, "after unbind from FaceLock service");
+                mBoundToService = false;
+            } else {
+                // This is usually not an error when this happens.  Sometimes we will tell it to
+                // unbind multiple times because it's called from both onWindowFocusChanged and
+                // onDetachedFromWindow.
+                if (DEBUG) Log.d(TAG, "Attempt to unbind from FaceLock when not bound");
+            }
+        }
+    }
+
+    private ServiceConnection mConnection = new ServiceConnection() {
+        // Completes connection, registers callback and starts FaceLock when service is bound
+        @Override
+        public void onServiceConnected(ComponentName className, IBinder iservice) {
+            mService = IFaceLockInterface.Stub.asInterface(iservice);
+            if (DEBUG) Log.d(TAG, "Connected to FaceLock service");
+            try {
+                mService.registerCallback(mFaceLockCallback);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Caught exception connecting to FaceLock: " + e.toString());
+                mService = null;
+                mBoundToService = false;
+                return;
+            }
+
+            if (mAreaView != null) {
+                int[] position;
+                position = new int[2];
+                mAreaView.getLocationInWindow(position);
+                start(mAreaView.getWindowToken(), position[0], position[1],
+                        mAreaView.getWidth(), mAreaView.getHeight());
+            }
+        }
+
+        // Cleans up if FaceLock service unexpectedly disconnects
+        @Override
+        public void onServiceDisconnected(ComponentName className) {
+            synchronized(mServiceRunningLock) {
+                mService = null;
+                mServiceRunning = false;
+            }
+            mBoundToService = false;
+            Log.w(TAG, "Unexpected disconnect from FaceLock service");
+        }
+    };
+
+    // Tells the FaceLock service to start displaying its UI and perform recognition
+    public void start(IBinder windowToken, int x, int y, int w, int h) {
+        if (installedAndSelected()) {
+            synchronized (mServiceRunningLock) {
+                if (!mServiceRunning) {
+                    if (DEBUG) Log.d(TAG, "Starting FaceLock");
+                    try {
+                        mService.startUi(windowToken, x, y, w, h);
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Caught exception starting FaceLock: " + e.toString());
+                        return;
+                    }
+                    mServiceRunning = true;
+                } else {
+                    if (DEBUG) Log.w(TAG, "start() attempted while running");
+                }
+            }
+        }
+    }
+
+    // Tells the FaceLock service to stop displaying its UI and stop recognition
+    public void stop() {
+        if (installedAndSelected()) {
+            // Note that attempting to stop FaceLock when it's not running is not an issue.
+            // FaceLock can return, which stops it and then we try to stop it when the
+            // screen is turned off.  That's why we check.
+            synchronized (mServiceRunningLock) {
+                if (mServiceRunning) {
+                    try {
+                        if (DEBUG) Log.d(TAG, "Stopping FaceLock");
+                        mService.stopUi();
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Caught exception stopping FaceLock: " + e.toString());
+                    }
+                    mServiceRunning = false;
+                }
+            }
+        }
+    }
+
+    // Implements the FaceLock service callback interface defined in AIDL
+    private final IFaceLockCallback mFaceLockCallback = new IFaceLockCallback.Stub() {
+        // Stops the FaceLock UI and indicates that the phone should be unlocked
+        @Override
+        public void unlock() {
+            if (DEBUG) Log.d(TAG, "FaceLock unlock()");
+            showArea(); // Keep fallback covered
+            stopAndUnbind();
+
+            mKeyguardScreenCallback.keyguardDone(true);
+            mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
+        }
+
+        // Stops the FaceLock UI and exposes the backup method without unlocking
+        // This means the user has cancelled out
+        @Override
+        public void cancel() {
+            if (DEBUG) Log.d(TAG, "FaceLock cancel()");
+            hideArea(); // Expose fallback
+            stopAndUnbind();
+            mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
+        }
+
+        // Stops the FaceLock UI and exposes the backup method without unlocking
+        // This means FaceLock failed to recognize them
+        @Override
+        public void reportFailedAttempt() {
+            if (DEBUG) Log.d(TAG, "FaceLock reportFailedAttempt()");
+            mUpdateMonitor.reportFailedFaceUnlockAttempt();
+            hideArea(); // Expose fallback
+            stopAndUnbind();
+            mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
+        }
+
+        // Removes the black area that covers the backup unlock method
+        @Override
+        public void exposeFallback() {
+            if (DEBUG) Log.d(TAG, "FaceLock exposeFallback()");
+            hideArea(); // Expose fallback
+        }
+
+        // Allows the Face Unlock service to poke the wake lock to keep the lockscreen alive
+        @Override
+        public void pokeWakelock() {
+            if (DEBUG) Log.d(TAG, "FaceLock pokeWakelock()");
+            mKeyguardScreenCallback.pokeWakelock();
+        }
+    };
+}
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 404dc6f..596040c 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -20,8 +20,6 @@
 import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallback;
 import com.android.internal.policy.impl.KeyguardUpdateMonitor.InfoCallbackImpl;
 import com.android.internal.policy.impl.LockPatternKeyguardView.UnlockMode;
-import com.android.internal.policy.IFaceLockCallback;
-import com.android.internal.policy.IFaceLockInterface;
 import com.android.internal.telephony.IccCard;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.internal.widget.LockScreenWidgetCallback;
@@ -36,12 +34,10 @@
 import android.accounts.OperationCanceledException;
 import android.app.AlertDialog;
 import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.content.ServiceConnection;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -50,12 +46,8 @@
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.IBinder;
 import android.os.Parcelable;
 import android.os.PowerManager;
-import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.telephony.TelephonyManager;
@@ -82,7 +74,7 @@
  * {@link com.android.internal.policy.impl.KeyguardViewManager}
  * via its {@link com.android.internal.policy.impl.KeyguardViewCallback}, as appropriate.
  */
-public class LockPatternKeyguardView extends KeyguardViewBase implements Handler.Callback {
+public class LockPatternKeyguardView extends KeyguardViewBase {
 
     private static final int TRANSPORT_USERACTIVITY_TIMEOUT = 10000;
 
@@ -110,30 +102,9 @@
     private boolean mShowLockBeforeUnlock = false;
 
     // The following were added to support FaceLock
-    private IFaceLockInterface mFaceLockService;
-    private boolean mBoundToFaceLockService = false;
-    private View mFaceLockAreaView;
-
-    private boolean mFaceLockServiceRunning = false;
-    private final Object mFaceLockServiceRunningLock = new Object();
+    private FaceUnlock mFaceUnlock;
     private final Object mFaceLockStartupLock = new Object();
 
-    private Handler mHandler;
-    private final int MSG_SHOW_FACELOCK_AREA_VIEW = 0;
-    private final int MSG_HIDE_FACELOCK_AREA_VIEW = 1;
-
-    // Long enough to stay visible while dialer comes up
-    // Short enough to not be visible if the user goes back immediately
-    private final int FACELOCK_VIEW_AREA_EMERGENCY_DIALER_TIMEOUT = 1000;
-
-    // Long enough to stay visible while the service starts
-    // Short enough to not have to wait long for backup if service fails to start or crashes
-    // The service can take a couple of seconds to start on the first try after boot
-    private final int FACELOCK_VIEW_AREA_SERVICE_TIMEOUT = 3000;
-
-    // So the user has a consistent amount of time when brought to the backup method from FaceLock
-    private final int BACKUP_LOCK_TIMEOUT = 5000;
-
     private boolean mRequiresSim;
     //True if we have some sort of overlay on top of the Lockscreen
     //Also true if we've activated a phone call, either emergency dialing or incoming
@@ -340,12 +311,12 @@
             mHasOverlay = true;
 
             // Continue showing FaceLock area until dialer comes up or call is resumed
-            if (usingFaceLock() && mFaceLockServiceRunning) {
-                showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_EMERGENCY_DIALER_TIMEOUT);
+            if (mFaceUnlock.installedAndSelected() && mFaceUnlock.isServiceRunning()) {
+                mFaceUnlock.showAreaWithTimeout(mFaceUnlock.viewAreaEmergencyDialerTimeout());
             }
 
             // FaceLock must be stopped if it is running when emergency call is pressed
-            stopAndUnbindFromFaceLock();
+            mFaceUnlock.stopAndUnbind();
 
             pokeWakelock(EMERGENCY_CALL_TIMEOUT);
             if (TelephonyManager.getDefault().getCallState()
@@ -450,7 +421,8 @@
             LockPatternUtils lockPatternUtils, KeyguardWindowController controller) {
         super(context, callback);
 
-        mHandler = new Handler(this);
+        mFaceUnlock = new FaceUnlock(context, updateMonitor, lockPatternUtils,
+                mKeyguardScreenCallback);
         mConfiguration = context.getResources().getConfiguration();
         mEnableFallback = false;
         mRequiresSim = TextUtils.isEmpty(SystemProperties.get("keyguard.no_require_sim"));
@@ -570,36 +542,7 @@
         saveWidgetState();
 
         // When screen is turned off, need to unbind from FaceLock service if using FaceLock
-        stopAndUnbindFromFaceLock();
-    }
-
-    /** When screen is turned on and focused, need to bind to FaceLock service if we are using
-     *  FaceLock, but only if we're not dealing with a call
-    */
-    private void activateFaceLockIfAble() {
-        final boolean tooManyFaceUnlockTries = mUpdateMonitor.getMaxFaceUnlockAttemptsReached();
-        final int failedBackupAttempts = mUpdateMonitor.getFailedAttempts();
-        final boolean backupIsTimedOut =
-                (failedBackupAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT);
-        if (tooManyFaceUnlockTries) Log.i(TAG, "tooManyFaceUnlockTries: " + tooManyFaceUnlockTries);
-        if (mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE
-                && usingFaceLock()
-                && !mHasOverlay
-                && !tooManyFaceUnlockTries
-                && !backupIsTimedOut) {
-            bindToFaceLock();
-
-            // Show FaceLock area, but only for a little bit so lockpattern will become visible if
-            // FaceLock fails to start or crashes
-            showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_SERVICE_TIMEOUT);
-
-            // When switching between portrait and landscape view while FaceLock is running, the
-            // screen will eventually go dark unless we poke the wakelock when FaceLock is
-            // restarted
-            mKeyguardScreenCallback.pokeWakelock();
-        } else {
-            hideFaceLockArea();
-        }
+        mFaceUnlock.stopAndUnbind();
     }
 
     @Override
@@ -616,7 +559,7 @@
 
         restoreWidgetState();
 
-        if (runFaceLock) activateFaceLockIfAble();
+        if (runFaceLock) mFaceUnlock.activateIfAble(mHasOverlay);
     }
 
     private void saveWidgetState() {
@@ -647,13 +590,13 @@
             if(mScreenOn && !mWindowFocused) runFaceLock = hasWindowFocus;
             mWindowFocused = hasWindowFocus;
         }
-        if(!hasWindowFocus) {
+        if (!hasWindowFocus) {
             mHasOverlay = true;
-            stopAndUnbindFromFaceLock();
-            hideFaceLockArea();
+            mFaceUnlock.stopAndUnbind();
+            mFaceUnlock.hideArea();
         } else {
             mHasDialog = false;
-            if (runFaceLock) activateFaceLockIfAble();
+            if (runFaceLock) mFaceUnlock.activateIfAble(mHasOverlay);
         }
     }
 
@@ -667,14 +610,14 @@
             ((KeyguardScreen) mUnlockScreen).onResume();
         }
 
-        if (usingFaceLock() && !mHasOverlay) {
+        if (mFaceUnlock.installedAndSelected() && !mHasOverlay) {
             // Note that show() gets called before the screen turns off to set it up for next time
             // it is turned on.  We don't want to set a timeout on the FaceLock area here because it
             // may be gone by the time the screen is turned on again.  We set the timeout when the
             // screen turns on instead.
-            showFaceLockArea();
+            mFaceUnlock.showArea();
         } else {
-            hideFaceLockArea();
+            mFaceUnlock.hideArea();
         }
     }
 
@@ -710,7 +653,7 @@
 
         // When view is hidden, need to unbind from FaceLock service if we are using FaceLock
         // e.g., when device becomes unlocked
-        stopAndUnbindFromFaceLock();
+        mFaceUnlock.stopAndUnbind();
 
         super.onDetachedFromWindow();
     }
@@ -734,9 +677,9 @@
             mHasOverlay |= mPluggedIn != pluggedIn;
             mPluggedIn = pluggedIn;
             //If it's already running, don't close it down: the unplug didn't start it
-            if (!mFaceLockServiceRunning) {
-                stopAndUnbindFromFaceLock();
-                hideFaceLockArea();
+            if (!mFaceUnlock.isServiceRunning()) {
+                mFaceUnlock.stopAndUnbind();
+                mFaceUnlock.hideArea();
             }
         }
 
@@ -753,8 +696,8 @@
             if (DEBUG) Log.d(TAG, "phone state: " + phoneState);
             if(phoneState == TelephonyManager.CALL_STATE_RINGING) {
                 mHasOverlay = true;
-                stopAndUnbindFromFaceLock();
-                hideFaceLockArea();
+                mFaceUnlock.stopAndUnbind();
+                mFaceUnlock.hideArea();
             }
         }
 
@@ -822,15 +765,7 @@
             mUnlockScreen = null;
         }
         mUpdateMonitor.removeCallback(this);
-        if (mFaceLockService != null) {
-            try {
-                mFaceLockService.unregisterCallback(mFaceLockCallback);
-            } catch (RemoteException e) {
-                // Not much we can do
-            }
-            stopFaceLock();
-            mFaceLockService = null;
-        }
+        mFaceUnlock.cleanUp();
     }
 
     private boolean isSecure() {
@@ -880,9 +815,9 @@
         final UnlockMode unlockMode = getUnlockMode();
         if (mode == Mode.UnlockScreen && unlockMode != UnlockMode.Unknown) {
             if (force || mUnlockScreen == null || unlockMode != mUnlockScreenMode) {
-                boolean restartFaceLock = stopFaceLockIfRunning();
+                boolean restartFaceLock = mFaceUnlock.stopIfRunning();
                 recreateUnlockScreen(unlockMode);
-                if (restartFaceLock) activateFaceLockIfAble();
+                if (restartFaceLock) mFaceUnlock.activateIfAble(mHasOverlay);
             }
         }
 
@@ -995,7 +930,7 @@
             throw new IllegalArgumentException("unknown unlock mode " + unlockMode);
         }
         initializeTransportControlView(unlockView);
-        initializeFaceLockAreaView(unlockView); // Only shows view if FaceLock is enabled
+        mFaceUnlock.initializeAreaView(unlockView); // Only shows view if FaceLock is enabled
 
         mUnlockScreenMode = unlockMode;
         return unlockView;
@@ -1177,254 +1112,4 @@
             return mBitmap.getHeight();
         }
     }
-
-    // Everything below pertains to FaceLock - might want to separate this out
-
-    // Indicates whether FaceLock is in use
-    private boolean usingFaceLock() {
-        return (mLockPatternUtils.usingBiometricWeak() &&
-                mLockPatternUtils.isBiometricWeakInstalled());
-    }
-
-    // Takes care of FaceLock area when layout is created
-    private void initializeFaceLockAreaView(View view) {
-        if (usingFaceLock()) {
-            mFaceLockAreaView = view.findViewById(R.id.faceLockAreaView);
-            if (mFaceLockAreaView == null) {
-                Log.e(TAG, "Layout does not have faceLockAreaView and FaceLock is enabled");
-            }
-        } else {
-            mFaceLockAreaView = null; // Set to null if not using FaceLock
-        }
-    }
-
-    // Stops FaceLock if it is running and reports back whether it was running or not
-    private boolean stopFaceLockIfRunning() {
-        if (usingFaceLock() && mBoundToFaceLockService) {
-            stopAndUnbindFromFaceLock();
-            return true;
-        }
-        return false;
-    }
-
-    // Handles covering or exposing FaceLock area on the client side when FaceLock starts or stops
-    // This needs to be done in a handler because the call could be coming from a callback from the
-    // FaceLock service that is in a thread that can't modify the UI
-    @Override
-    public boolean handleMessage(Message msg) {
-        switch (msg.what) {
-        case MSG_SHOW_FACELOCK_AREA_VIEW:
-            if (mFaceLockAreaView != null) {
-                mFaceLockAreaView.setVisibility(View.VISIBLE);
-            }
-            break;
-        case MSG_HIDE_FACELOCK_AREA_VIEW:
-            if (mFaceLockAreaView != null) {
-                mFaceLockAreaView.setVisibility(View.INVISIBLE);
-            }
-            break;
-        default:
-            Log.w(TAG, "Unhandled message");
-            return false;
-        }
-        return true;
-    }
-
-    // Removes show and hide messages from the message queue
-    private void removeFaceLockAreaDisplayMessages() {
-        mHandler.removeMessages(MSG_SHOW_FACELOCK_AREA_VIEW);
-        mHandler.removeMessages(MSG_HIDE_FACELOCK_AREA_VIEW);
-    }
-
-    // Shows the FaceLock area immediately
-    private void showFaceLockArea() {
-        // Remove messages to prevent a delayed hide message from undo-ing the show
-        removeFaceLockAreaDisplayMessages();
-        mHandler.sendEmptyMessage(MSG_SHOW_FACELOCK_AREA_VIEW);
-    }
-
-    // Hides the FaceLock area immediately
-    private void hideFaceLockArea() {
-        // Remove messages to prevent a delayed show message from undo-ing the hide
-        removeFaceLockAreaDisplayMessages();
-        mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW);
-    }
-
-    // Shows the FaceLock area for a period of time
-    private void showFaceLockAreaWithTimeout(long timeoutMillis) {
-        showFaceLockArea();
-        mHandler.sendEmptyMessageDelayed(MSG_HIDE_FACELOCK_AREA_VIEW, timeoutMillis);
-    }
-
-    // Binds to FaceLock service.  This call does not tell it to start, but it causes the service
-    // to call the onServiceConnected callback, which then starts FaceLock.
-    public void bindToFaceLock() {
-        if (usingFaceLock()) {
-            if (!mBoundToFaceLockService) {
-                if (DEBUG) Log.d(TAG, "before bind to FaceLock service");
-                mContext.bindService(new Intent(IFaceLockInterface.class.getName()),
-                        mFaceLockConnection,
-                        Context.BIND_AUTO_CREATE);
-                if (DEBUG) Log.d(TAG, "after bind to FaceLock service");
-                mBoundToFaceLockService = true;
-            } else {
-                Log.w(TAG, "Attempt to bind to FaceLock when already bound");
-            }
-        }
-    }
-
-    // Tells FaceLock to stop and then unbinds from the FaceLock service
-    public void stopAndUnbindFromFaceLock() {
-        if (usingFaceLock()) {
-            stopFaceLock();
-
-            if (mBoundToFaceLockService) {
-                if (DEBUG) Log.d(TAG, "before unbind from FaceLock service");
-                if (mFaceLockService != null) {
-                    try {
-                        mFaceLockService.unregisterCallback(mFaceLockCallback);
-                    } catch (RemoteException e) {
-                        // Not much we can do
-                    }
-                }
-                mContext.unbindService(mFaceLockConnection);
-                if (DEBUG) Log.d(TAG, "after unbind from FaceLock service");
-                mBoundToFaceLockService = false;
-            } else {
-                // This is usually not an error when this happens.  Sometimes we will tell it to
-                // unbind multiple times because it's called from both onWindowFocusChanged and
-                // onDetachedFromWindow.
-                if (DEBUG) Log.d(TAG, "Attempt to unbind from FaceLock when not bound");
-            }
-        }
-    }
-
-    private ServiceConnection mFaceLockConnection = new ServiceConnection() {
-        // Completes connection, registers callback and starts FaceLock when service is bound
-        @Override
-        public void onServiceConnected(ComponentName className, IBinder iservice) {
-            mFaceLockService = IFaceLockInterface.Stub.asInterface(iservice);
-            if (DEBUG) Log.d(TAG, "Connected to FaceLock service");
-            try {
-                mFaceLockService.registerCallback(mFaceLockCallback);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Caught exception connecting to FaceLock: " + e.toString());
-                mFaceLockService = null;
-                mBoundToFaceLockService = false;
-                return;
-            }
-
-            if (mFaceLockAreaView != null) {
-                int[] faceLockPosition;
-                faceLockPosition = new int[2];
-                mFaceLockAreaView.getLocationInWindow(faceLockPosition);
-                startFaceLock(mFaceLockAreaView.getWindowToken(),
-                        faceLockPosition[0], faceLockPosition[1],
-                        mFaceLockAreaView.getWidth(), mFaceLockAreaView.getHeight());
-            }
-        }
-
-        // Cleans up if FaceLock service unexpectedly disconnects
-        @Override
-        public void onServiceDisconnected(ComponentName className) {
-            synchronized(mFaceLockServiceRunningLock) {
-                mFaceLockService = null;
-                mFaceLockServiceRunning = false;
-            }
-            mBoundToFaceLockService = false;
-            Log.w(TAG, "Unexpected disconnect from FaceLock service");
-        }
-    };
-
-    // Tells the FaceLock service to start displaying its UI and perform recognition
-    public void startFaceLock(IBinder windowToken, int x, int y, int w, int h)
-    {
-        if (usingFaceLock()) {
-            synchronized (mFaceLockServiceRunningLock) {
-                if (!mFaceLockServiceRunning) {
-                    if (DEBUG) Log.d(TAG, "Starting FaceLock");
-                    try {
-                        mFaceLockService.startUi(windowToken, x, y, w, h);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Caught exception starting FaceLock: " + e.toString());
-                        return;
-                    }
-                    mFaceLockServiceRunning = true;
-                } else {
-                    if (DEBUG) Log.w(TAG, "startFaceLock() attempted while running");
-                }
-            }
-        }
-    }
-
-    // Tells the FaceLock service to stop displaying its UI and stop recognition
-    public void stopFaceLock()
-    {
-        if (usingFaceLock()) {
-            // Note that attempting to stop FaceLock when it's not running is not an issue.
-            // FaceLock can return, which stops it and then we try to stop it when the
-            // screen is turned off.  That's why we check.
-            synchronized (mFaceLockServiceRunningLock) {
-                if (mFaceLockServiceRunning) {
-                    try {
-                        if (DEBUG) Log.d(TAG, "Stopping FaceLock");
-                        mFaceLockService.stopUi();
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "Caught exception stopping FaceLock: " + e.toString());
-                    }
-                    mFaceLockServiceRunning = false;
-                }
-            }
-        }
-    }
-
-    // Implements the FaceLock service callback interface defined in AIDL
-    private final IFaceLockCallback mFaceLockCallback = new IFaceLockCallback.Stub() {
-
-        // Stops the FaceLock UI and indicates that the phone should be unlocked
-        @Override
-        public void unlock() {
-            if (DEBUG) Log.d(TAG, "FaceLock unlock()");
-            showFaceLockArea(); // Keep fallback covered
-            stopAndUnbindFromFaceLock();
-
-            mKeyguardScreenCallback.keyguardDone(true);
-            mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
-        }
-
-        // Stops the FaceLock UI and exposes the backup method without unlocking
-        // This means the user has cancelled out
-        @Override
-        public void cancel() {
-            if (DEBUG) Log.d(TAG, "FaceLock cancel()");
-            hideFaceLockArea(); // Expose fallback
-            stopAndUnbindFromFaceLock();
-            mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
-        }
-
-        // Stops the FaceLock UI and exposes the backup method without unlocking
-        // This means FaceLock failed to recognize them
-        @Override
-        public void reportFailedAttempt() {
-            if (DEBUG) Log.d(TAG, "FaceLock reportFailedAttempt()");
-            mUpdateMonitor.reportFailedFaceUnlockAttempt();
-            hideFaceLockArea(); // Expose fallback
-            stopAndUnbindFromFaceLock();
-            mKeyguardScreenCallback.pokeWakelock(BACKUP_LOCK_TIMEOUT);
-        }
-
-        // Removes the black area that covers the backup unlock method
-        @Override
-        public void exposeFallback() {
-            if (DEBUG) Log.d(TAG, "FaceLock exposeFallback()");
-            hideFaceLockArea(); // Expose fallback
-        }
-
-        // Allows the Face Unlock service to poke the wake lock to keep the lockscreen alive
-        @Override
-        public void pokeWakelock() {
-            if (DEBUG) Log.d(TAG, "FaceLock pokeWakelock()");
-            mKeyguardScreenCallback.pokeWakelock();
-        }
-    };
 }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index c3cac6e..f3622ef 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -132,6 +132,9 @@
 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
 import android.view.WindowManagerImpl;
 import android.view.WindowManagerPolicy;
+import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
+import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
+import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
 import android.view.KeyCharacterMap.FallbackAction;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.Animation;
@@ -237,8 +240,6 @@
     static final int SYSTEM_UI_CHANGING_LAYOUT =
             View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN;
 
-    // Useful scan codes.
-    private static final int SW_LID = 0x00;
     private static final int BTN_MOUSE = 0x110;
 
     /* Table of Application Launch keys.  Maps from key codes to intent categories.
@@ -322,10 +323,6 @@
     RecentApplicationsDialog mRecentAppsDialog;
     int mRecentAppsDialogHeldModifiers;
 
-    private static final int LID_ABSENT = -1;
-    private static final int LID_CLOSED = 0;
-    private static final int LID_OPEN = 1;
-
     int mLidOpen = LID_ABSENT;
 
     boolean mSystemReady;
@@ -976,12 +973,13 @@
                 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
+        // of the screen.  We assume sizes >= 600dp are tablets where we
         // will use the system bar.
+        // XXX: This will change to 720dp soon.
         int shortSizeDp = shortSize
                 * DisplayMetrics.DENSITY_DEFAULT
                 / DisplayMetrics.DENSITY_DEVICE;
-        mHasSystemNavBar = shortSizeDp > 600;
+        mHasSystemNavBar = shortSizeDp >= 600;
 
         if (!mHasSystemNavBar) {
             mHasNavigationBar = mContext.getResources().getBoolean(
@@ -1120,16 +1118,11 @@
             lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
             wm.addView(mPointerLocationView, lp);
 
-            try {
-                mPointerLocationInputChannel =
-                        mWindowManager.monitorInput("PointerLocationView");
-                mPointerLocationInputEventReceiver =
-                        new PointerLocationInputEventReceiver(mPointerLocationInputChannel,
-                                Looper.myLooper(), mPointerLocationView);
-            } catch (RemoteException ex) {
-                Slog.e(TAG, "Could not set up input monitoring channel for PointerLocation.",
-                        ex);
-            }
+            mPointerLocationInputChannel =
+                    mWindowManagerFuncs.monitorInput("PointerLocationView");
+            mPointerLocationInputEventReceiver =
+                    new PointerLocationInputEventReceiver(mPointerLocationInputChannel,
+                            Looper.myLooper(), mPointerLocationView);
         }
     }
 
@@ -1223,18 +1216,7 @@
     }
     
     void readLidState() {
-        try {
-            int sw = mWindowManager.getSwitchState(SW_LID);
-            if (sw > 0) {
-                mLidOpen = LID_OPEN;
-            } else if (sw == 0) {
-                mLidOpen = LID_CLOSED;
-            } else {
-                mLidOpen = LID_ABSENT;
-            }
-        } catch (RemoteException e) {
-            // Ignore
-        }
+        mLidOpen = mWindowManagerFuncs.getLidState();
     }
     
     private int determineHiddenState(int mode, int hiddenValue, int visibleValue) {
@@ -1358,18 +1340,29 @@
     }
 
     public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation) {
-        // Assumes that the navigation bar appears on the side of the display in landscape.
-        if (mHasNavigationBar && fullWidth > fullHeight) {
-            return fullWidth - mNavigationBarWidth;
+        if (mHasNavigationBar) {
+            // For a basic navigation bar, when we are in landscape mode we place
+            // the navigation bar to the side.
+            if (fullWidth > fullHeight) {
+                return fullWidth - mNavigationBarWidth;
+            }
         }
         return fullWidth;
     }
 
     public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation) {
-        // Assumes the navigation bar appears on the bottom of the display in portrait.
-        return fullHeight
-            - (mHasSystemNavBar ? mNavigationBarHeight : 0)
-            - ((mHasNavigationBar && fullWidth > fullHeight) ? 0 : mNavigationBarHeight);
+        if (mHasSystemNavBar) {
+            // For the system navigation bar, we always place it at the bottom.
+            return fullHeight - mNavigationBarHeight;
+        }
+        if (mHasNavigationBar) {
+            // For a basic navigation bar, when we are in portrait mode we place
+            // the navigation bar to the bottom.
+            if (fullWidth < fullHeight) {
+                return fullHeight - mNavigationBarHeight;
+            }
+        }
+        return fullHeight;
     }
 
     public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation) {
@@ -1377,13 +1370,15 @@
     }
 
     public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation) {
-        // This is the same as getNonDecorDisplayHeight, unless the status bar
-        // can hide.  If the status bar can hide, we don't count that as part
-        // of the decor; however for purposes of configurations, we do want to
-        // exclude it since applications can't generally use that part of the
-        // screen.
-        return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation)
-                - (mHasSystemNavBar ? 0 : mStatusBarHeight);
+        // If we don't have a system nav bar, then there is a separate status
+        // bar at the top of the display.  We don't count that as part of the
+        // fixed decor, since it can hide; however, for purposes of configurations,
+        // we do want to exclude it since applications can't generally use that part
+        // of the screen.
+        if (!mHasSystemNavBar) {
+            return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation) - mStatusBarHeight;
+        }
+        return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation);
     }
 
     public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) {
@@ -2230,10 +2225,14 @@
         // 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;
-            pf.bottom = df.bottom = vf.bottom = mDockBottom;
+            pf.left = df.left = mUnrestrictedScreenLeft;
+            pf.top = df.top = mUnrestrictedScreenTop;
+            pf.right = df.right = mUnrestrictedScreenWidth - mUnrestrictedScreenLeft;
+            pf.bottom = df.bottom = mUnrestrictedScreenHeight - mUnrestrictedScreenTop;
+            vf.left = mStableLeft;
+            vf.top = mStableTop;
+            vf.right = mStableRight;
+            vf.bottom = mStableBottom;
 
             mStatusBar.computeFrameLw(pf, df, vf, vf);
             final Rect r = mStatusBar.getFrameLw();
@@ -3644,29 +3643,11 @@
         }
     }
 
-    public boolean detectSafeMode() {
-        try {
-            int menuState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_MENU);
-            int sState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_S);
-            int dpadState = mWindowManager.getDPadKeycodeState(KeyEvent.KEYCODE_DPAD_CENTER);
-            int trackballState = mWindowManager.getTrackballScancodeState(BTN_MOUSE);
-            int volumeDownState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_VOLUME_DOWN);
-            mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
-                    || volumeDownState > 0;
-            performHapticFeedbackLw(null, mSafeMode
-                    ? HapticFeedbackConstants.SAFE_MODE_ENABLED
-                    : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
-            if (mSafeMode) {
-                Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
-                        + " dpad=" + dpadState + " trackball=" + trackballState + ")");
-            } else {
-                Log.i(TAG, "SAFE MODE not enabled");
-            }
-            return mSafeMode;
-        } catch (RemoteException e) {
-            // Doom! (it's also local)
-            throw new RuntimeException("window manager dead");
-        }
+    public void setSafeMode(boolean safeMode) {
+        mSafeMode = safeMode;
+        performHapticFeedbackLw(null, safeMode
+                ? HapticFeedbackConstants.SAFE_MODE_ENABLED
+                : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
     }
     
     static long[] getLongIntArray(Resources r, int resid) {
diff --git a/services/common_time/common_time_server.cpp b/services/common_time/common_time_server.cpp
index ef7fa168..7a4986b 100644
--- a/services/common_time/common_time_server.cpp
+++ b/services/common_time/common_time_server.cpp
@@ -80,14 +80,14 @@
 
 // number of sync requests that can fail before a client assumes its master
 // is dead
-const int CommonTimeServer::kClient_NumSyncRequestRetries = 5;
+const int CommonTimeServer::kClient_NumSyncRequestRetries = 10;
 
 /*** Master state constants ***/
 
 /*** Ronin state constants ***/
 
 // number of WhoIsMaster attempts sent before declaring ourselves master
-const int CommonTimeServer::kRonin_NumWhoIsMasterRetries = 4;
+const int CommonTimeServer::kRonin_NumWhoIsMasterRetries = 20;
 
 // timeout used when waiting for a response to a WhoIsMaster request
 const int CommonTimeServer::kRonin_WhoIsMasterTimeoutMs = 500;
@@ -96,7 +96,7 @@
 
 // how long do we wait for an announcement from a master before
 // trying another election?
-const int CommonTimeServer::kWaitForElection_TimeoutMs = 5000;
+const int CommonTimeServer::kWaitForElection_TimeoutMs = 12500;
 
 CommonTimeServer::CommonTimeServer()
     : Thread(false)
@@ -279,10 +279,14 @@
                     // If we were in the master state, then either we were the
                     // master in a no-network situation, or we were the master
                     // of a different network and have moved to a new interface.
-                    // In either case, immediately send out a master
-                    // announcement at low priority.
+                    // In either case, immediately transition to Ronin at low
+                    // priority.  If there is no one in the network we just
+                    // joined, we will become master soon enough.  If there is,
+                    // we want to be certain to defer master status to the
+                    // existing timeline currently running on the network.
+                    //
                     case CommonClockService::STATE_MASTER:
-                        sendMasterAnnouncement();
+                        becomeRonin("leaving networkless mode");
                         break;
 
                     // If we were in any other state (CLIENT, RONIN, or
@@ -1072,6 +1076,12 @@
 
     mMasterEP = masterEP;
     mMasterEPValid = true;
+
+    // If we are on a real network as a client of a real master, then we should
+    // no longer force low priority.  If our master disappears, we should have
+    // the high priority bit set during the election to replace the master
+    // because this group was a real group and not a singleton created in
+    // networkless mode.
     setForceLowPriority(false);
 
     mClient_MasterDeviceID = masterDeviceID;
@@ -1113,7 +1123,6 @@
 
     memset(&mMasterEP, 0, sizeof(mMasterEP));
     mMasterEPValid = false;
-    setForceLowPriority(false);
     mClient_MasterDevicePriority = effectivePriority();
     mClient_MasterDeviceID = mDeviceID;
     mClockRecovery.reset(false, true);
diff --git a/services/input/EventHub.cpp b/services/input/EventHub.cpp
index 1b74aa6..7060ae2 100644
--- a/services/input/EventHub.cpp
+++ b/services/input/EventHub.cpp
@@ -40,6 +40,7 @@
 #include <androidfw/KeyCharacterMap.h>
 #include <androidfw/VirtualKeyMap.h>
 
+#include <sha1.h>
 #include <string.h>
 #include <stdint.h>
 #include <dirent.h>
@@ -78,6 +79,20 @@
     return value ? "true" : "false";
 }
 
+static String8 sha1(const String8& in) {
+    SHA1_CTX ctx;
+    SHA1Init(&ctx);
+    SHA1Update(&ctx, reinterpret_cast<const u_char*>(in.string()), in.size());
+    u_char digest[SHA1_DIGEST_LENGTH];
+    SHA1Final(digest, &ctx);
+
+    String8 out;
+    for (size_t i = 0; i < SHA1_DIGEST_LENGTH; i++) {
+        out.appendFormat("%02x", digest[i]);
+    }
+    return out;
+}
+
 // --- Global Functions ---
 
 uint32_t getAbsAxisUsage(int32_t axis, uint32_t deviceClasses) {
@@ -209,11 +224,11 @@
     release_wake_lock(WAKE_LOCK_ID);
 }
 
-String8 EventHub::getDeviceName(int32_t deviceId) const {
+InputDeviceIdentifier EventHub::getDeviceIdentifier(int32_t deviceId) const {
     AutoMutex _l(mLock);
     Device* device = getDeviceLocked(deviceId);
-    if (device == NULL) return String8();
-    return device->identifier.name;
+    if (device == NULL) return InputDeviceIdentifier();
+    return device->identifier;
 }
 
 uint32_t EventHub::getDeviceClasses(int32_t deviceId) const {
@@ -893,6 +908,30 @@
         identifier.uniqueId.setTo(buffer);
     }
 
+    // Compute a device descriptor that uniquely identifies the device.
+    // The descriptor is assumed to be a stable identifier.  Its value should not
+    // change between reboots, reconnections, firmware updates or new releases of Android.
+    // Ideally, we also want the descriptor to be short and relatively opaque.
+    String8 rawDescriptor;
+    rawDescriptor.appendFormat(":%04x:%04x:", identifier.vendor, identifier.product);
+    if (!identifier.uniqueId.isEmpty()) {
+        rawDescriptor.append("uniqueId:");
+        rawDescriptor.append(identifier.uniqueId);
+    } if (identifier.vendor == 0 && identifier.product == 0) {
+        // If we don't know the vendor and product id, then the device is probably
+        // built-in so we need to rely on other information to uniquely identify
+        // the input device.  Usually we try to avoid relying on the device name or
+        // location but for built-in input device, they are unlikely to ever change.
+        if (!identifier.name.isEmpty()) {
+            rawDescriptor.append("name:");
+            rawDescriptor.append(identifier.name);
+        } else if (!identifier.location.isEmpty()) {
+            rawDescriptor.append("location:");
+            rawDescriptor.append(identifier.location);
+        }
+    }
+    identifier.descriptor = sha1(rawDescriptor);
+
     // Make file descriptor non-blocking for use with poll().
     if (fcntl(fd, F_SETFL, O_NONBLOCK)) {
         ALOGE("Error %d making device file descriptor non-blocking.", errno);
@@ -904,19 +943,18 @@
     int32_t deviceId = mNextDeviceId++;
     Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
 
-#if 0
-    ALOGI("add device %d: %s\n", deviceId, devicePath);
-    ALOGI("  bus:       %04x\n"
-         "  vendor     %04x\n"
-         "  product    %04x\n"
-         "  version    %04x\n",
+    ALOGV("add device %d: %s\n", deviceId, devicePath);
+    ALOGV("  bus:        %04x\n"
+         "  vendor      %04x\n"
+         "  product     %04x\n"
+         "  version     %04x\n",
         identifier.bus, identifier.vendor, identifier.product, identifier.version);
-    ALOGI("  name:      \"%s\"\n", identifier.name.string());
-    ALOGI("  location:  \"%s\"\n", identifier.location.string());
-    ALOGI("  unique id: \"%s\"\n", identifier.uniqueId.string());
-    ALOGI("  driver:    v%d.%d.%d\n",
+    ALOGV("  name:       \"%s\"\n", identifier.name.string());
+    ALOGV("  location:   \"%s\"\n", identifier.location.string());
+    ALOGV("  unique id:  \"%s\"\n", identifier.uniqueId.string());
+    ALOGV("  descriptor: \"%s\" (%s)\n", identifier.descriptor.string(), rawDescriptor.string());
+    ALOGV("  driver:     v%d.%d.%d\n",
         driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff);
-#endif
 
     // Load the configuration file for the device.
     loadConfigurationLocked(device);
@@ -1065,18 +1103,35 @@
 
     // Enable wake-lock behavior on kernels that support it.
     // TODO: Only need this for devices that can really wake the system.
-    bool usingSuspendBlock = ioctl(fd, EVIOCSSUSPENDBLOCK, 1) == 0;
+    bool usingSuspendBlockIoctl = !ioctl(fd, EVIOCSSUSPENDBLOCK, 1);
+
+    // Tell the kernel that we want to use the monotonic clock for reporting timestamps
+    // associated with input events.  This is important because the input system
+    // uses the timestamps extensively and assumes they were recorded using the monotonic
+    // clock.
+    //
+    // In older kernel, before Linux 3.4, there was no way to tell the kernel which
+    // clock to use to input event timestamps.  The standard kernel behavior was to
+    // record a real time timestamp, which isn't what we want.  Android kernels therefore
+    // contained a patch to the evdev_event() function in drivers/input/evdev.c to
+    // replace the call to do_gettimeofday() with ktime_get_ts() to cause the monotonic
+    // clock to be used instead of the real time clock.
+    //
+    // As of Linux 3.4, there is a new EVIOCSCLOCKID ioctl to set the desired clock.
+    // Therefore, we no longer require the Android-specific kernel patch described above
+    // as long as we make sure to set select the monotonic clock.  We do that here.
+    bool usingClockIoctl = !ioctl(fd, EVIOCSCLOCKID, CLOCK_MONOTONIC);
 
     ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=0x%x, "
             "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, "
-            "usingSuspendBlock=%s",
+            "usingSuspendBlockIoctl=%s, usingClockIoctl=%s",
          deviceId, fd, devicePath, device->identifier.name.string(),
          device->classes,
          device->configurationFile.string(),
          device->keyMap.keyLayoutFile.string(),
          device->keyMap.keyCharacterMapFile.string(),
          toString(mBuiltInKeyboardId == deviceId),
-         toString(usingSuspendBlock));
+         toString(usingSuspendBlockIoctl), toString(usingClockIoctl));
 
     mDevices.add(deviceId, device);
 
@@ -1303,6 +1358,7 @@
             }
             dump.appendFormat(INDENT3 "Classes: 0x%08x\n", device->classes);
             dump.appendFormat(INDENT3 "Path: %s\n", device->path.string());
+            dump.appendFormat(INDENT3 "Descriptor: %s\n", device->identifier.descriptor.string());
             dump.appendFormat(INDENT3 "Location: %s\n", device->identifier.location.string());
             dump.appendFormat(INDENT3 "UniqueId: %s\n", device->identifier.uniqueId.string());
             dump.appendFormat(INDENT3 "Identifier: bus=0x%04x, vendor=0x%04x, "
diff --git a/services/input/EventHub.h b/services/input/EventHub.h
index 4eb47c6..bd21a3d 100644
--- a/services/input/EventHub.h
+++ b/services/input/EventHub.h
@@ -151,7 +151,7 @@
 
     virtual uint32_t getDeviceClasses(int32_t deviceId) const = 0;
 
-    virtual String8 getDeviceName(int32_t deviceId) const = 0;
+    virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const = 0;
 
     virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const = 0;
 
@@ -230,7 +230,7 @@
 
     virtual uint32_t getDeviceClasses(int32_t deviceId) const;
 
-    virtual String8 getDeviceName(int32_t deviceId) const;
+    virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const;
 
     virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const;
 
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index eccce292..ddd870d 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -344,18 +344,19 @@
 }
 
 void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
-    String8 name = mEventHub->getDeviceName(deviceId);
+    InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
     uint32_t classes = mEventHub->getDeviceClasses(deviceId);
 
-    InputDevice* device = createDeviceLocked(deviceId, name, classes);
+    InputDevice* device = createDeviceLocked(deviceId, identifier, classes);
     device->configure(when, &mConfig, 0);
     device->reset(when);
 
     if (device->isIgnored()) {
-        ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string());
+        ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,
+                identifier.name.string());
     } else {
-        ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, name.string(),
-                device->getSources());
+        ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId,
+                identifier.name.string(), device->getSources());
     }
 
     ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
@@ -392,8 +393,8 @@
 }
 
 InputDevice* InputReader::createDeviceLocked(int32_t deviceId,
-        const String8& name, uint32_t classes) {
-    InputDevice* device = new InputDevice(&mContext, deviceId, name, classes);
+        const InputDeviceIdentifier& identifier, uint32_t classes) {
+    InputDevice* device = new InputDevice(&mContext, deviceId, identifier, classes);
 
     // External devices.
     if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
@@ -851,9 +852,9 @@
 
 // --- InputDevice ---
 
-InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name,
-        uint32_t classes) :
-        mContext(context), mId(id), mName(name), mClasses(classes),
+InputDevice::InputDevice(InputReaderContext* context, int32_t id,
+        const InputDeviceIdentifier& identifier, uint32_t classes) :
+        mContext(context), mId(id), mIdentifier(identifier), mClasses(classes),
         mSources(0), mIsExternal(false), mDropUntilNextSync(false) {
 }
 
@@ -961,7 +962,7 @@
 #endif
             }
         } else if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_DROPPED) {
-            ALOGI("Detected input event buffer overrun for device %s.", mName.string());
+            ALOGI("Detected input event buffer overrun for device %s.", getName().string());
             mDropUntilNextSync = true;
             reset(rawEvent->when);
         } else {
@@ -982,7 +983,7 @@
 }
 
 void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
-    outDeviceInfo->initialize(mId, mName);
+    outDeviceInfo->initialize(mId, mIdentifier.name, mIdentifier.descriptor);
 
     size_t numMappers = mMappers.size();
     for (size_t i = 0; i < numMappers; i++) {
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index 9bbe49c..8520a75 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -338,7 +338,7 @@
 protected:
     // These members are protected so they can be instrumented by test cases.
     virtual InputDevice* createDeviceLocked(int32_t deviceId,
-            const String8& name, uint32_t classes);
+            const InputDeviceIdentifier& identifier, uint32_t classes);
 
     class ContextImpl : public InputReaderContext {
         InputReader* mReader;
@@ -432,12 +432,13 @@
 /* Represents the state of a single input device. */
 class InputDevice {
 public:
-    InputDevice(InputReaderContext* context, int32_t id, const String8& name, uint32_t classes);
+    InputDevice(InputReaderContext* context, int32_t id,
+            const InputDeviceIdentifier& identifier, uint32_t classes);
     ~InputDevice();
 
     inline InputReaderContext* getContext() { return mContext; }
     inline int32_t getId() { return mId; }
-    inline const String8& getName() { return mName; }
+    inline const String8& getName() { return mIdentifier.name; }
     inline uint32_t getClasses() { return mClasses; }
     inline uint32_t getSources() { return mSources; }
 
@@ -486,7 +487,7 @@
 private:
     InputReaderContext* mContext;
     int32_t mId;
-    String8 mName;
+    InputDeviceIdentifier mIdentifier;
     uint32_t mClasses;
 
     Vector<InputMapper*> mMappers;
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 08efe7d..2cccf9f 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -274,7 +274,7 @@
     };
 
     struct Device {
-        String8 name;
+        InputDeviceIdentifier identifier;
         uint32_t classes;
         PropertyMap configuration;
         KeyedVector<int, RawAbsoluteAxisInfo> absoluteAxes;
@@ -287,8 +287,8 @@
         KeyedVector<int32_t, bool> leds;
         Vector<VirtualKeyDefinition> virtualKeys;
 
-        Device(const String8& name, uint32_t classes) :
-                name(name), classes(classes) {
+        Device(uint32_t classes) :
+                classes(classes) {
         }
     };
 
@@ -307,7 +307,8 @@
     FakeEventHub() { }
 
     void addDevice(int32_t deviceId, const String8& name, uint32_t classes) {
-        Device* device = new Device(name, classes);
+        Device* device = new Device(classes);
+        device->identifier.name = name;
         mDevices.add(deviceId, device);
 
         enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_ADDED, 0, 0, 0, 0);
@@ -433,9 +434,9 @@
         return device ? device->classes : 0;
     }
 
-    virtual String8 getDeviceName(int32_t deviceId) const {
+    virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const {
         Device* device = getDevice(deviceId);
-        return device ? device->name : String8("unknown");
+        return device ? device->identifier : InputDeviceIdentifier();
     }
 
     virtual void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const {
@@ -857,18 +858,20 @@
     }
 
     InputDevice* newDevice(int32_t deviceId, const String8& name, uint32_t classes) {
-        return new InputDevice(&mContext, deviceId, name, classes);
+        InputDeviceIdentifier identifier;
+        identifier.name = name;
+        return new InputDevice(&mContext, deviceId, identifier, classes);
     }
 
 protected:
     virtual InputDevice* createDeviceLocked(int32_t deviceId,
-            const String8& name, uint32_t classes) {
+            const InputDeviceIdentifier& identifier, uint32_t classes) {
         if (mNextDevice) {
             InputDevice* device = mNextDevice;
             mNextDevice = NULL;
             return device;
         }
-        return InputReader::createDeviceLocked(deviceId, name, classes);
+        return InputReader::createDeviceLocked(deviceId, identifier, classes);
     }
 
     friend class InputReaderTest;
@@ -1231,7 +1234,9 @@
         mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeListener);
 
         mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
-        mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME), DEVICE_CLASSES);
+        InputDeviceIdentifier identifier;
+        identifier.name = DEVICE_NAME;
+        mDevice = new InputDevice(mFakeContext, DEVICE_ID, identifier, DEVICE_CLASSES);
     }
 
     virtual void TearDown() {
@@ -1411,7 +1416,9 @@
         mFakePolicy = new FakeInputReaderPolicy();
         mFakeListener = new FakeInputListener();
         mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeListener);
-        mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME), DEVICE_CLASSES);
+        InputDeviceIdentifier identifier;
+        identifier.name = DEVICE_NAME;
+        mDevice = new InputDevice(mFakeContext, DEVICE_ID, identifier, DEVICE_CLASSES);
 
         mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
     }
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java
index 0574405..32ac8e1 100644
--- a/services/java/com/android/server/AlarmManagerService.java
+++ b/services/java/com/android/server/AlarmManagerService.java
@@ -34,9 +34,9 @@
 import android.os.PowerManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.os.WorkSource;
 import android.text.TextUtils;
 import android.text.format.Time;
-import android.util.EventLog;
 import android.util.Slog;
 import android.util.TimeUtils;
 
@@ -50,6 +50,7 @@
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.Map;
 import java.util.TimeZone;
 
@@ -89,6 +90,7 @@
     private int mDescriptor;
     private int mBroadcastRefCount = 0;
     private PowerManager.WakeLock mWakeLock;
+    private LinkedList<PendingIntent> mInFlight = new LinkedList<PendingIntent>();
     private final AlarmThread mWaitThread = new AlarmThread();
     private final AlarmHandler mHandler = new AlarmHandler();
     private ClockReceiver mClockReceiver;
@@ -668,10 +670,12 @@
                                             Intent.EXTRA_ALARM_COUNT, alarm.count),
                                     mResultReceiver, mHandler);
                             
-                            // we have an active broadcast so stay awake. 
+                            // we have an active broadcast so stay awake.
                             if (mBroadcastRefCount == 0) {
+                                setWakelockWorkSource(alarm.operation);
                                 mWakeLock.acquire();
                             }
+                            mInFlight.add(alarm.operation);
                             mBroadcastRefCount++;
                             
                             BroadcastStats bs = getStatsLocked(alarm.operation);
@@ -700,7 +704,22 @@
             }
         }
     }
-    
+
+    void setWakelockWorkSource(PendingIntent pi) {
+        try {
+            final int uid = ActivityManagerNative.getDefault()
+                    .getUidForIntentSender(pi.getTarget());
+            if (uid >= 0) {
+                mWakeLock.setWorkSource(new WorkSource(uid));
+                return;
+            }
+        } catch (Exception e) {
+        }
+
+        // Something went wrong; fall back to attributing the lock to the OS
+        mWakeLock.setWorkSource(null);
+    }
+
     private class AlarmHandler extends Handler {
         public static final int ALARM_EVENT = 1;
         public static final int MINUTE_CHANGE_EVENT = 2;
@@ -876,9 +895,20 @@
                         fs.count++;
                     }
                 }
+                mInFlight.removeFirst();
                 mBroadcastRefCount--;
                 if (mBroadcastRefCount == 0) {
                     mWakeLock.release();
+                } else {
+                    // the next of our alarms is now in flight.  reattribute the wakelock.
+                    final PendingIntent nowInFlight = mInFlight.peekFirst();
+                    if (nowInFlight != null) {
+                        setWakelockWorkSource(nowInFlight);
+                    } else {
+                        // should never happen
+                        Slog.e(TAG, "Alarm wakelock still held but sent queue empty");
+                        mWakeLock.setWorkSource(null);
+                    }
                 }
             }
         }
diff --git a/services/java/com/android/server/WiredAccessoryObserver.java b/services/java/com/android/server/WiredAccessoryObserver.java
index 9b4eddc..53d1f0e 100644
--- a/services/java/com/android/server/WiredAccessoryObserver.java
+++ b/services/java/com/android/server/WiredAccessoryObserver.java
@@ -301,13 +301,13 @@
 
                 //  Pack up the values and broadcast them to everyone
                 if (headset == BIT_USB_HEADSET_ANLG) {
-                    intent = new Intent(Intent.ACTION_USB_ANLG_HEADSET_PLUG);
+                    intent = new Intent(Intent.ACTION_ANALOG_AUDIO_DOCK_PLUG);
                     intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                     intent.putExtra("state", state);
                     intent.putExtra("name", headsetName);
                     ActivityManagerNative.broadcastStickyIntent(intent, null);
                 } else if (headset == BIT_USB_HEADSET_DGTL) {
-                    intent = new Intent(Intent.ACTION_USB_DGTL_HEADSET_PLUG);
+                    intent = new Intent(Intent.ACTION_DIGITAL_AUDIO_DOCK_PLUG);
                     intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                     intent.putExtra("state", state);
                     intent.putExtra("name", headsetName);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 2da827e..80e59cd 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -4444,6 +4444,17 @@
         return null;
     }
 
+    public int getUidForIntentSender(IIntentSender sender) {
+        if (sender instanceof PendingIntentRecord) {
+            try {
+                PendingIntentRecord res = (PendingIntentRecord)sender;
+                return res.uid;
+            } catch (ClassCastException e) {
+            }
+        }
+        return -1;
+    }
+
     public boolean isIntentSenderTargetedToPackage(IIntentSender pendingResult) {
         if (!(pendingResult instanceof PendingIntentRecord)) {
             return false;
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index d60ff2b..a098f18 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import com.android.internal.app.ResolverActivity;
 import com.android.server.AttributeCache;
 import com.android.server.am.ActivityStack.ActivityState;
 
@@ -382,7 +383,7 @@
                         _intent.getData() == null &&
                         _intent.getType() == null &&
                         (intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
-                        !"android".equals(realActivity.getClassName())) {
+                        !ResolverActivity.class.getName().equals(realActivity.getClassName())) {
                     // This sure looks like a home activity!
                     // Note the last check is so we don't count the resolver
                     // activity as being home...  really, we don't care about
diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/java/com/android/server/input/InputManagerService.java
index 6a566ae..b8cc65e 100644
--- a/services/java/com/android/server/input/InputManagerService.java
+++ b/services/java/com/android/server/input/InputManagerService.java
@@ -28,11 +28,13 @@
 import android.content.res.Configuration;
 import android.database.ContentObserver;
 import android.hardware.input.IInputManager;
+import android.hardware.input.InputManager;
 import android.os.Binder;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.MessageQueue;
+import android.os.Process;
 import android.os.SystemProperties;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
@@ -108,18 +110,16 @@
     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.
-    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
-    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;
-    
+    // Input event injection constants defined in InputDispatcher.h.
+    private static final int INPUT_EVENT_INJECTION_SUCCEEDED = 0;
+    private static final int INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1;
+    private static final int INPUT_EVENT_INJECTION_FAILED = 2;
+    private static final int INPUT_EVENT_INJECTION_TIMED_OUT = 3;
+
+    // Maximum number of milliseconds to wait for input event injection.
+    private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000;
+
     // Key states (may be returned by queries about the current state of a
     // particular key code, scan code or switch).
     
@@ -194,7 +194,7 @@
         
         nativeGetInputConfiguration(mPtr, config);
     }
-    
+
     /**
      * Gets the current state of a key or button by key code.
      * @param deviceId The input device id, or -1 to consult all devices.
@@ -246,6 +246,7 @@
      * key codes.
      * @return True if the lookup was successful, false otherwise.
      */
+    @Override
     public boolean hasKeys(int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists) {
         if (keyCodes == null) {
             throw new IllegalArgumentException("keyCodes must not be null.");
@@ -336,43 +337,42 @@
         }
     }
 
-    /**
-     * Injects an input event into the event system on behalf of an application.
-     * The synchronization mode determines whether the method blocks while waiting for
-     * input injection to proceed.
-     * 
-     * {@link #INPUT_EVENT_INJECTION_SYNC_NONE} never blocks.  Injection is asynchronous and
-     * is assumed always to be successful.
-     * 
-     * {@link #INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT} waits for previous events to be
-     * dispatched so that the input dispatcher can determine whether input event injection will
-     * be permitted based on the current input focus.  Does not wait for the input event to
-     * finish processing.
-     * 
-     * {@link #INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH} waits for the input event to
-     * be completely processed.
-     * 
-     * @param event The event to inject.
-     * @param injectorPid The pid of the injecting application.
-     * @param injectorUid The uid of the injecting application.
-     * @param syncMode The synchronization mode.
-     * @param timeoutMillis The injection timeout in milliseconds.
-     * @return One of the INPUT_EVENT_INJECTION_XXX constants.
-     */
-    public int injectInputEvent(InputEvent event, int injectorPid, int injectorUid,
-            int syncMode, int timeoutMillis) {
+    @Override
+    public boolean injectInputEvent(InputEvent event, int mode) {
         if (event == null) {
             throw new IllegalArgumentException("event must not be null");
         }
-        if (injectorPid < 0 || injectorUid < 0) {
-            throw new IllegalArgumentException("injectorPid and injectorUid must not be negative.");
-        }
-        if (timeoutMillis <= 0) {
-            throw new IllegalArgumentException("timeoutMillis must be positive");
+        if (mode != InputManager.INJECT_INPUT_EVENT_MODE_ASYNC
+                && mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH
+                && mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) {
+            throw new IllegalArgumentException("mode is invalid");
         }
 
-        return nativeInjectInputEvent(mPtr, event, injectorPid, injectorUid, syncMode,
-                timeoutMillis, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);
+        final int pid = Binder.getCallingPid();
+        final int uid = Binder.getCallingUid();
+        final long ident = Binder.clearCallingIdentity();
+        final int result;
+        try {
+            result = nativeInjectInputEvent(mPtr, event, pid, uid, mode,
+                    INJECTION_TIMEOUT_MILLIS, WindowManagerPolicy.FLAG_DISABLE_KEY_REPEAT);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+        switch (result) {
+            case 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 INPUT_EVENT_INJECTION_SUCCEEDED:
+                return true;
+            case INPUT_EVENT_INJECTION_TIMED_OUT:
+                Slog.w(TAG, "Input event injection from pid " + pid + " timed out.");
+                return false;
+            case INPUT_EVENT_INJECTION_FAILED:
+            default:
+                Slog.w(TAG, "Input event injection from pid " + pid + " failed.");
+                return false;
+        }
     }
 
     /**
@@ -380,6 +380,7 @@
      * @param id The device id.
      * @return The input device or null if not found.
      */
+    @Override
     public InputDevice getInputDevice(int deviceId) {
         return nativeGetInputDevice(mPtr, deviceId);
     }
@@ -388,6 +389,7 @@
      * Gets the ids of all input devices in the system.
      * @return The input device ids.
      */
+    @Override
     public int[] getInputDeviceIds() {
         return nativeGetInputDeviceIds(mPtr);
     }
@@ -436,14 +438,25 @@
      * @param speed The pointer speed as a value between -7 (slowest) and 7 (fastest)
      * where 0 is the default speed.
      */
-    public void setPointerSpeed(int speed) {
-        speed = Math.min(Math.max(speed, -7), 7);
-        nativeSetPointerSpeed(mPtr, speed);
+    @Override
+    public void tryPointerSpeed(int speed) {
+        if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED,
+                "tryPointerSpeed()")) {
+            throw new SecurityException("Requires SET_POINTER_SPEED permission");
+        }
+
+        setPointerSpeedUnchecked(speed);
     }
 
     public void updatePointerSpeedFromSettings() {
-        int speed = getPointerSpeedSetting(0);
-        setPointerSpeed(speed);
+        int speed = getPointerSpeedSetting();
+        setPointerSpeedUnchecked(speed);
+    }
+
+    private void setPointerSpeedUnchecked(int speed) {
+        speed = Math.min(Math.max(speed, InputManager.MIN_POINTER_SPEED),
+                InputManager.MAX_POINTER_SPEED);
+        nativeSetPointerSpeed(mPtr, speed);
     }
 
     private void registerPointerSpeedSettingObserver() {
@@ -457,8 +470,8 @@
                 });
     }
 
-    private int getPointerSpeedSetting(int defaultValue) {
-        int speed = defaultValue;
+    private int getPointerSpeedSetting() {
+        int speed = InputManager.DEFAULT_POINTER_SPEED;
         try {
             speed = Settings.System.getInt(mContext.getContentResolver(),
                     Settings.System.POINTER_SPEED);
@@ -510,6 +523,23 @@
         }
     }
 
+    private boolean checkCallingPermission(String permission, String func) {
+        // Quick check: if the calling permission is me, it's all okay.
+        if (Binder.getCallingPid() == Process.myPid()) {
+            return true;
+        }
+
+        if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) {
+            return true;
+        }
+        String msg = "Permission Denial: " + func + " from pid="
+                + Binder.getCallingPid()
+                + ", uid=" + Binder.getCallingUid()
+                + " requires " + permission;
+        Slog.w(TAG, msg);
+        return false;
+    }
+
     // Called by the heartbeat to ensure locks are not held indefinitely (for deadlock detection).
     public void monitor() {
         synchronized (mInputFilterLock) { }
@@ -703,7 +733,8 @@
 
             synchronized (mInputFilterLock) {
                 if (!mDisconnected) {
-                    nativeInjectInputEvent(mPtr, event, 0, 0, INPUT_EVENT_INJECTION_SYNC_NONE, 0,
+                    nativeInjectInputEvent(mPtr, event, 0, 0,
+                            InputManager.INJECT_INPUT_EVENT_MODE_ASYNC, 0,
                             policyFlags | WindowManagerPolicy.FLAG_FILTERED);
                 }
             }
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index b0657a6..fa62e497 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -1588,7 +1588,7 @@
     }
 
     private Handler.Callback mHandlerCallback = new Handler.Callback() {
-        /** {@inheritDoc} */
+        @Override
         public boolean handleMessage(Message msg) {
             switch (msg.what) {
                 case MSG_RULES_CHANGED: {
@@ -1740,7 +1740,7 @@
 
     private long getTotalBytes(NetworkTemplate template, long start, long end) {
         try {
-            return mNetworkStats.getSummaryForNetwork(template, start, end).getTotalBytes();
+            return mNetworkStats.getNetworkTotalBytes(template, start, end);
         } catch (RuntimeException e) {
             Slog.w(TAG, "problem reading network stats: " + e);
             return 0;
diff --git a/services/java/com/android/server/net/NetworkStatsCollection.java b/services/java/com/android/server/net/NetworkStatsCollection.java
index 70038d9..2892a74 100644
--- a/services/java/com/android/server/net/NetworkStatsCollection.java
+++ b/services/java/com/android/server/net/NetworkStatsCollection.java
@@ -57,8 +57,6 @@
  * {@link NetworkIdentitySet}, UID, set, and tag. Knows how to persist itself.
  */
 public class NetworkStatsCollection implements FileRotator.Reader {
-    private static final String TAG = "NetworkStatsCollection";
-
     /** File header magic number: "ANET" */
     private static final int FILE_MAGIC = 0x414E4554;
 
@@ -173,7 +171,7 @@
     }
 
     /**
-     * Record given {@link NetworkStats.Entry} into this collection.
+     * Record given {@link android.net.NetworkStats.Entry} into this collection.
      */
     public void recordData(NetworkIdentitySet ident, int uid, int set, int tag, long start,
             long end, NetworkStats.Entry entry) {
@@ -227,7 +225,7 @@
         }
     }
 
-    /** {@inheritDoc} */
+    @Override
     public void read(InputStream in) throws IOException {
         read(new DataInputStream(in));
     }
@@ -502,7 +500,7 @@
             return false;
         }
 
-        /** {@inheritDoc} */
+        @Override
         public int compareTo(Key another) {
             return Integer.compare(uid, another.uid);
         }
diff --git a/services/java/com/android/server/net/NetworkStatsRecorder.java b/services/java/com/android/server/net/NetworkStatsRecorder.java
index 290bd2c..57ad158 100644
--- a/services/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/java/com/android/server/net/NetworkStatsRecorder.java
@@ -221,6 +221,11 @@
         if (mLastSnapshot != null) {
             mLastSnapshot = mLastSnapshot.withoutUid(uid);
         }
+
+        final NetworkStatsCollection complete = mComplete != null ? mComplete.get() : null;
+        if (complete != null) {
+            complete.removeUid(uid);
+        }
     }
 
     /**
@@ -235,22 +240,22 @@
             mCollection = checkNotNull(collection, "missing NetworkStatsCollection");
         }
 
-        /** {@inheritDoc} */
+        @Override
         public void reset() {
             // ignored
         }
 
-        /** {@inheritDoc} */
+        @Override
         public void read(InputStream in) throws IOException {
             mCollection.read(in);
         }
 
-        /** {@inheritDoc} */
+        @Override
         public boolean shouldWrite() {
             return true;
         }
 
-        /** {@inheritDoc} */
+        @Override
         public void write(OutputStream out) throws IOException {
             mCollection.write(new DataOutputStream(out));
             mCollection.reset();
@@ -270,24 +275,24 @@
             mUid = uid;
         }
 
-        /** {@inheritDoc} */
+        @Override
         public void reset() {
             mTemp.reset();
         }
 
-        /** {@inheritDoc} */
+        @Override
         public void read(InputStream in) throws IOException {
             mTemp.read(in);
             mTemp.clearDirty();
             mTemp.removeUid(mUid);
         }
 
-        /** {@inheritDoc} */
+        @Override
         public boolean shouldWrite() {
             return mTemp.isDirty();
         }
 
-        /** {@inheritDoc} */
+        @Override
         public void write(OutputStream out) throws IOException {
             mTemp.write(new DataOutputStream(out));
         }
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index b847673..4382a03 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -70,6 +70,7 @@
 import android.net.IConnectivityManager;
 import android.net.INetworkManagementEventObserver;
 import android.net.INetworkStatsService;
+import android.net.INetworkStatsSession;
 import android.net.LinkProperties;
 import android.net.NetworkIdentity;
 import android.net.NetworkInfo;
@@ -412,40 +413,75 @@
     }
 
     @Override
-    public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
-        return mDevStatsCached.getHistory(template, UID_ALL, SET_ALL, TAG_NONE, fields);
+    public INetworkStatsSession openSession() {
+        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
+
+        // return an IBinder which holds strong references to any loaded stats
+        // for its lifetime; when caller closes only weak references remain.
+
+        return new INetworkStatsSession.Stub() {
+            private NetworkStatsCollection mUidComplete;
+            private NetworkStatsCollection mUidTagComplete;
+
+            private NetworkStatsCollection getUidComplete() {
+                if (mUidComplete == null) {
+                    mUidComplete = mUidRecorder.getOrLoadCompleteLocked();
+                }
+                return mUidComplete;
+            }
+
+            private NetworkStatsCollection getUidTagComplete() {
+                if (mUidTagComplete == null) {
+                    mUidTagComplete = mUidTagRecorder.getOrLoadCompleteLocked();
+                }
+                return mUidTagComplete;
+            }
+
+            @Override
+            public NetworkStats getSummaryForNetwork(
+                    NetworkTemplate template, long start, long end) {
+                return mDevStatsCached.getSummary(template, start, end);
+            }
+
+            @Override
+            public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
+                return mDevStatsCached.getHistory(template, UID_ALL, SET_ALL, TAG_NONE, fields);
+            }
+
+            @Override
+            public NetworkStats getSummaryForAllUid(
+                    NetworkTemplate template, long start, long end, boolean includeTags) {
+                final NetworkStats stats = getUidComplete().getSummary(template, start, end);
+                if (includeTags) {
+                    final NetworkStats tagStats = getUidTagComplete()
+                            .getSummary(template, start, end);
+                    stats.combineAllValues(tagStats);
+                }
+                return stats;
+            }
+
+            @Override
+            public NetworkStatsHistory getHistoryForUid(
+                    NetworkTemplate template, int uid, int set, int tag, int fields) {
+                if (tag == TAG_NONE) {
+                    return getUidComplete().getHistory(template, uid, set, tag, fields);
+                } else {
+                    return getUidTagComplete().getHistory(template, uid, set, tag, fields);
+                }
+            }
+
+            @Override
+            public void close() {
+                mUidComplete = null;
+                mUidTagComplete = null;
+            }
+        };
     }
 
     @Override
-    public NetworkStats getSummaryForNetwork(NetworkTemplate template, long start, long end) {
-        return mDevStatsCached.getSummary(template, start, end);
-    }
-
-    @Override
-    public NetworkStatsHistory getHistoryForUid(
-            NetworkTemplate template, int uid, int set, int tag, int fields) {
-        // TODO: transition to stats sessions to avoid WeakReferences
-        if (tag == TAG_NONE) {
-            return mUidRecorder.getOrLoadCompleteLocked().getHistory(
-                    template, uid, set, tag, fields);
-        } else {
-            return mUidTagRecorder.getOrLoadCompleteLocked().getHistory(
-                    template, uid, set, tag, fields);
-        }
-    }
-
-    @Override
-    public NetworkStats getSummaryForAllUid(
-            NetworkTemplate template, long start, long end, boolean includeTags) {
-        // TODO: transition to stats sessions to avoid WeakReferences
-        final NetworkStats stats = mUidRecorder.getOrLoadCompleteLocked().getSummary(
-                template, start, end);
-        if (includeTags) {
-            final NetworkStats tagStats = mUidTagRecorder.getOrLoadCompleteLocked().getSummary(
-                    template, start, end);
-            stats.combineAllValues(tagStats);
-        }
-        return stats;
+    public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
+        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
+        return mDevStatsCached.getSummary(template, start, end).getTotalBytes();
     }
 
     @Override
@@ -464,6 +500,9 @@
             Binder.restoreCallingIdentity(token);
         }
 
+        // splice in operation counts
+        networkLayer.spliceOperationsFrom(mUidOperations);
+
         final NetworkStats dataLayer = new NetworkStats(
                 networkLayer.getElapsedRealtime(), networkLayer.size());
 
@@ -474,8 +513,6 @@
             dataLayer.combineValues(entry);
         }
 
-        // splice in operation counts
-        dataLayer.spliceOperationsFrom(mUidOperations);
         return dataLayer;
     }
 
@@ -962,7 +999,7 @@
     }
 
     private Handler.Callback mHandlerCallback = new Handler.Callback() {
-        /** {@inheritDoc} */
+        @Override
         public boolean handleMessage(Message msg) {
             switch (msg.what) {
                 case MSG_PERFORM_POLL: {
@@ -1001,7 +1038,7 @@
     }
 
     private class DropBoxNonMonotonicObserver implements NonMonotonicObserver<String> {
-        /** {@inheritDoc} */
+        @Override
         public void foundNonMonotonic(NetworkStats left, int leftIndex, NetworkStats right,
                 int rightIndex, String cookie) {
             Log.w(TAG, "found non-monotonic values; saving to dropbox");
@@ -1020,7 +1057,8 @@
     }
 
     /**
-     * Default external settings that read from {@link Settings.Secure}.
+     * Default external settings that read from
+     * {@link android.provider.Settings.Secure}.
      */
     private static class DefaultNetworkStatsSettings implements NetworkStatsSettings {
         private final ContentResolver mResolver;
@@ -1038,19 +1076,24 @@
             return Settings.Secure.getInt(mResolver, name, defInt) != 0;
         }
 
+        @Override
         public long getPollInterval() {
             return getSecureLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
         }
+        @Override
         public long getTimeCacheMaxAge() {
             return getSecureLong(NETSTATS_TIME_CACHE_MAX_AGE, DAY_IN_MILLIS);
         }
+        @Override
         public long getGlobalAlertBytes() {
             return getSecureLong(NETSTATS_GLOBAL_ALERT_BYTES, 2 * MB_IN_BYTES);
         }
+        @Override
         public boolean getSampleEnabled() {
             return getSecureBoolean(NETSTATS_SAMPLE_ENABLED, true);
         }
 
+        @Override
         public Config getDevConfig() {
             return new Config(getSecureLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS),
                     getSecureLong(NETSTATS_DEV_PERSIST_BYTES, 2 * MB_IN_BYTES),
@@ -1058,6 +1101,7 @@
                     getSecureLong(NETSTATS_DEV_DELETE_AGE, 90 * DAY_IN_MILLIS));
         }
 
+        @Override
         public Config getUidConfig() {
             return new Config(getSecureLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
                     getSecureLong(NETSTATS_UID_PERSIST_BYTES, 2 * MB_IN_BYTES),
@@ -1065,6 +1109,7 @@
                     getSecureLong(NETSTATS_UID_DELETE_AGE, 90 * DAY_IN_MILLIS));
         }
 
+        @Override
         public Config getUidTagConfig() {
             return new Config(getSecureLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
                     getSecureLong(NETSTATS_UID_PERSIST_BYTES, 2 * MB_IN_BYTES),
diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java
index 4bea5e40..1bd15f6 100644
--- a/services/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/java/com/android/server/usb/UsbDeviceManager.java
@@ -60,6 +60,7 @@
 import java.util.List;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Scanner;
 
 /**
  * UsbDeviceManager manages USB state in device mode.
@@ -81,6 +82,8 @@
             "/sys/class/android_usb/android0/f_mass_storage/lun/file";
     private static final String RNDIS_ETH_ADDR_PATH =
             "/sys/class/android_usb/android0/f_rndis/ethaddr";
+    private static final String AUDIO_SOURCE_PCM_PATH =
+            "/sys/class/android_usb/android0/f_audio_source/pcm";
 
     private static final int MSG_UPDATE_STATE = 0;
     private static final int MSG_ENABLE_ADB = 1;
@@ -105,6 +108,7 @@
     private final boolean mHasUsbAccessory;
     private boolean mUseUsbNotification;
     private boolean mAdbEnabled;
+    private boolean mAudioSourceEnabled;
     private Map<String, List<Pair<String, String>>> mOemModeMap;
 
     private class AdbSettingsObserver extends ContentObserver {
@@ -291,6 +295,8 @@
                 String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
                 updateState(state);
                 mAdbEnabled = containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ADB);
+                mAudioSourceEnabled = containsFunction(mCurrentFunctions,
+                        UsbManager.USB_FUNCTION_AUDIO_SOURCE);
 
                 // Upgrade step for previous versions that used persist.service.adb.enable
                 String value = SystemProperties.get("persist.service.adb.enable", "");
@@ -504,6 +510,28 @@
             mContext.sendStickyBroadcast(intent);
         }
 
+        private void updateAudioSourceFunction(boolean enabled) {
+            // send a sticky broadcast containing current USB state
+            Intent intent = new Intent(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG);
+            intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+            intent.putExtra("state", (enabled ? 1 : 0));
+            if (enabled) {
+                try {
+                    Scanner scanner = new Scanner(new File(AUDIO_SOURCE_PCM_PATH));
+                    int card = scanner.nextInt();
+                    int device = scanner.nextInt();
+                    intent.putExtra("card", card);
+                    intent.putExtra("device", device);
+                } catch (FileNotFoundException e) {
+                    Slog.e(TAG, "could not open audio source PCM file", e);
+                }
+            }
+
+            mContext.sendStickyBroadcast(intent);
+            mAudioSourceEnabled = enabled;
+        }
+
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
@@ -523,6 +551,11 @@
                     }
                     if (mBootCompleted) {
                         updateUsbState();
+                        boolean audioSourceEnabled = containsFunction(mCurrentFunctions,
+                                UsbManager.USB_FUNCTION_AUDIO_SOURCE);
+                        if (audioSourceEnabled != mAudioSourceEnabled) {
+                            updateAudioSourceFunction(audioSourceEnabled);
+                        }
                     }
                     break;
                 case MSG_ENABLE_ADB:
@@ -543,6 +576,7 @@
                     if (mCurrentAccessory != null) {
                         mSettingsManager.accessoryAttached(mCurrentAccessory);
                     }
+                    updateAudioSourceFunction(mAudioSourceEnabled);
                     break;
             }
         }
diff --git a/services/java/com/android/server/wm/AppWindowAnimator.java b/services/java/com/android/server/wm/AppWindowAnimator.java
index 6ba4c35..c3b5465d 100644
--- a/services/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/java/com/android/server/wm/AppWindowAnimator.java
@@ -224,7 +224,7 @@
 
         hasTransformation = false;
 
-        if (!animating) {
+        if (!animating && animation == null) {
             return false;
         }
 
@@ -259,6 +259,19 @@
         return false;
     }
 
+    boolean showAllWindowsLocked() {
+        boolean isAnimating = false;
+        final int NW = mAppToken.allAppWindows.size();
+        for (int i=0; i<NW; i++) {
+            WindowStateAnimator winAnimator = mAppToken.allAppWindows.get(i).mWinAnimator;
+            if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG,
+                    "performing show on: " + winAnimator);
+            winAnimator.performShowLocked();
+            isAnimating |= winAnimator.isAnimating();
+        }
+        return isAnimating;
+    }
+
     void dump(PrintWriter pw, String prefix) {
         if (freezingScreen) {
             pw.print(prefix); pw.print(" freezingScreen="); pw.println(freezingScreen);
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index 1f8348d..bf35154 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -124,19 +124,6 @@
         }
     }
 
-    boolean showAllWindowsLocked() {
-        boolean isAnimating = false;
-        final int NW = allAppWindows.size();
-        for (int i=0; i<NW; i++) {
-            WindowStateAnimator winAnimator = allAppWindows.get(i).mWinAnimator;
-            if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG,
-                    "performing show on: " + winAnimator);
-            winAnimator.performShowLocked();
-            isAnimating |= winAnimator.isAnimating();
-        }
-        return isAnimating;
-    }
-
     void updateReportedVisibilityLocked() {
         if (appToken == null) {
             return;
diff --git a/services/java/com/android/server/wm/DimAnimator.java b/services/java/com/android/server/wm/DimAnimator.java
index 405dd04..b08c864 100644
--- a/services/java/com/android/server/wm/DimAnimator.java
+++ b/services/java/com/android/server/wm/DimAnimator.java
@@ -41,14 +41,14 @@
 
     DimAnimator (SurfaceSession session) {
         if (mDimSurface == null) {
-            if (WindowManagerService.SHOW_TRANSACTIONS ||
-                    WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
-                            "  DIM " + mDimSurface + ": CREATE");
             try {
                 mDimSurface = new Surface(session, 0,
                         "DimAnimator",
                         -1, 16, 16, PixelFormat.OPAQUE,
                         Surface.FX_SURFACE_DIM);
+                if (WindowManagerService.SHOW_TRANSACTIONS ||
+                        WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
+                                "  DIM " + mDimSurface + ": CREATE");
                 mDimSurface.setAlpha(0.0f);
             } catch (Exception e) {
                 Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e);
diff --git a/services/java/com/android/server/wm/DimSurface.java b/services/java/com/android/server/wm/DimSurface.java
index dc6cc0d..c1dbb36a 100644
--- a/services/java/com/android/server/wm/DimSurface.java
+++ b/services/java/com/android/server/wm/DimSurface.java
@@ -32,14 +32,14 @@
 
     DimSurface(SurfaceSession session) {
         if (mDimSurface == null) {
-            if (WindowManagerService.SHOW_TRANSACTIONS ||
-                    WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
-                            "  DIM " + mDimSurface + ": CREATE");
             try {
                 mDimSurface = new Surface(session, 0,
                         "DimSurface",
                         -1, 16, 16, PixelFormat.OPAQUE,
                         Surface.FX_SURFACE_DIM);
+                if (WindowManagerService.SHOW_TRANSACTIONS ||
+                        WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
+                                "  DIM " + mDimSurface + ": CREATE");
                 mDimSurface.setAlpha(0.0f);
             } catch (Exception e) {
                 Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e);
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
index 9b196cc..0d64b68 100644
--- a/services/java/com/android/server/wm/WindowAnimator.java
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -22,6 +22,7 @@
 import com.android.internal.policy.impl.PhoneWindowManager;
 
 import java.io.PrintWriter;
+import java.util.HashSet;
 
 /**
  * Singleton class that carries out the animations and Surface operations in a separate task
@@ -34,6 +35,9 @@
     final Context mContext;
     final WindowManagerPolicy mPolicy;
 
+    HashSet<WindowStateAnimator> mWinAnimators = new HashSet<WindowStateAnimator>();
+    HashSet<WindowStateAnimator> mFinished = new HashSet<WindowStateAnimator>();
+
     boolean mAnimating;
     boolean mTokenMayBeDrawn;
     boolean mForceHiding;
@@ -171,16 +175,16 @@
         ++mTransactionSequence;
 
         for (int i = mService.mWindows.size() - 1; i >= 0; i--) {
-            WindowState w = mService.mWindows.get(i);
-            WindowStateAnimator winAnimator = w.mWinAnimator;
-            final WindowManager.LayoutParams attrs = w.mAttrs;
+            WindowState win = mService.mWindows.get(i);
+            WindowStateAnimator winAnimator = win.mWinAnimator;
+            final int flags = winAnimator.mAttrFlags;
 
             if (winAnimator.mSurface != null) {
                 final boolean wasAnimating = winAnimator.mWasAnimating;
                 final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime);
 
                 if (WindowManagerService.DEBUG_WALLPAPER) {
-                    Slog.v(TAG, w + ": wasAnimating=" + wasAnimating +
+                    Slog.v(TAG, win + ": wasAnimating=" + wasAnimating +
                             ", nowAnimating=" + nowAnimating);
                 }
 
@@ -189,16 +193,16 @@
                 // a detached wallpaper animation.
                 if (nowAnimating) {
                     if (winAnimator.mAnimation != null) {
-                        if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0
+                        if ((flags & FLAG_SHOW_WALLPAPER) != 0
                                 && winAnimator.mAnimation.getDetachWallpaper()) {
-                            mDetachedWallpaper = w;
+                            mDetachedWallpaper = win;
                         }
                         final int backgroundColor = winAnimator.mAnimation.getBackgroundColor();
                         if (backgroundColor != 0) {
                             if (mWindowAnimationBackground == null
                                     || (winAnimator.mAnimLayer <
                                             mWindowAnimationBackground.mWinAnimator.mAnimLayer)) {
-                                mWindowAnimationBackground = w;
+                                mWindowAnimationBackground = win;
                                 mWindowAnimationBackgroundColor = backgroundColor;
                             }
                         }
@@ -210,25 +214,25 @@
                 // animation, make a note so we can ensure the wallpaper is
                 // displayed behind it.
                 final AppWindowAnimator appAnimator =
-                        w.mAppToken == null ? null : w.mAppToken.mAppAnimator;
+                        win.mAppToken == null ? null : win.mAppToken.mAppAnimator;
                 if (appAnimator != null && appAnimator.animation != null
                         && appAnimator.animating) {
-                    if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0
+                    if ((flags & FLAG_SHOW_WALLPAPER) != 0
                             && appAnimator.animation.getDetachWallpaper()) {
-                        mDetachedWallpaper = w;
+                        mDetachedWallpaper = win;
                     }
                     final int backgroundColor = appAnimator.animation.getBackgroundColor();
                     if (backgroundColor != 0) {
                         if (mWindowAnimationBackground == null
                                 || (winAnimator.mAnimLayer <
                                         mWindowAnimationBackground.mWinAnimator.mAnimLayer)) {
-                            mWindowAnimationBackground = w;
+                            mWindowAnimationBackground = win;
                             mWindowAnimationBackgroundColor = backgroundColor;
                         }
                     }
                 }
 
-                if (wasAnimating && !winAnimator.mAnimating && mService.mWallpaperTarget == w) {
+                if (wasAnimating && !winAnimator.mAnimating && mService.mWallpaperTarget == win) {
                     mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
                     mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
                     if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
@@ -237,11 +241,11 @@
                     }
                 }
 
-                if (mPolicy.doesForceHide(w, attrs)) {
+                if (mPolicy.doesForceHide(win, win.mAttrs)) {
                     if (!wasAnimating && nowAnimating) {
                         if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
                                 "Animation started that could impact force hide: "
-                                + w);
+                                + win);
                         mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED;
                         mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
                         if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
@@ -249,22 +253,22 @@
                                 mPendingLayoutChanges);
                         }
                         mService.mFocusMayChange = true;
-                    } else if (w.isReadyForDisplay() && winAnimator.mAnimation == null) {
+                    } else if (win.isReadyForDisplay() && winAnimator.mAnimation == null) {
                         mForceHiding = true;
                     }
-                } else if (mPolicy.canBeForceHidden(w, attrs)) {
+                } else if (mPolicy.canBeForceHidden(win, win.mAttrs)) {
                     final boolean changed;
                     if (mForceHiding) {
-                        changed = w.hideLw(false, false);
+                        changed = win.hideLw(false, false);
                         if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
-                                "Now policy hidden: " + w);
+                                "Now policy hidden: " + win);
                     } else {
-                        changed = w.showLw(false, false);
+                        changed = win.showLw(false, false);
                         if (WindowManagerService.DEBUG_VISIBILITY && changed) Slog.v(TAG,
-                                "Now policy shown: " + w);
+                                "Now policy shown: " + win);
                         if (changed) {
                             if ((mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
-                                    && w.isVisibleNow() /*w.isReadyForDisplay()*/) {
+                                    && win.isVisibleNow() /*w.isReadyForDisplay()*/) {
                                 // Assume we will need to animate.  If
                                 // we don't (because the wallpaper will
                                 // stay with the lock screen), then we will
@@ -274,7 +278,7 @@
                                     winAnimator.setAnimation(a);
                                 }
                             }
-                            if (mCurrentFocus == null || mCurrentFocus.mLayer < w.mLayer) {
+                            if (mCurrentFocus == null || mCurrentFocus.mLayer < win.mLayer) {
                                 // We are showing on to of the current
                                 // focus, so re-evaluate focus to make
                                 // sure it is correct.
@@ -282,8 +286,7 @@
                             }
                         }
                     }
-                    if (changed && (attrs.flags
-                            & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
+                    if (changed && (flags & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
                         mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
                         mPendingLayoutChanges |= WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
                         if (WindowManagerService.DEBUG_LAYOUT_REPEATS) {
@@ -294,44 +297,43 @@
                 }
             }
 
-            final AppWindowToken atoken = w.mAppToken;
+            final AppWindowToken atoken = win.mAppToken;
             if (atoken != null && (!atoken.allDrawn || atoken.mAppAnimator.freezingScreen)) {
                 if (atoken.lastTransactionSequence != mTransactionSequence) {
                     atoken.lastTransactionSequence = mTransactionSequence;
                     atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
                     atoken.startingDisplayed = false;
                 }
-                if ((w.isOnScreen() || w.mAttrs.type
+                if ((win.isOnScreen() || winAnimator.mAttrType
                         == WindowManager.LayoutParams.TYPE_BASE_APPLICATION)
-                        && !w.mExiting && !w.mDestroying) {
+                        && !win.mExiting && !win.mDestroying) {
                     if (WindowManagerService.DEBUG_VISIBILITY ||
                             WindowManagerService.DEBUG_ORIENTATION) {
-                        Slog.v(TAG, "Eval win " + w + ": isDrawn="
-                                + w.isDrawnLw()
+                        Slog.v(TAG, "Eval win " + win + ": isDrawn=" + win.isDrawnLw()
                                 + ", isAnimating=" + winAnimator.isAnimating());
-                        if (!w.isDrawnLw()) {
+                        if (!win.isDrawnLw()) {
                             Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurface
-                                    + " pv=" + w.mPolicyVisibility
+                                    + " pv=" + win.mPolicyVisibility
                                     + " mDrawState=" + winAnimator.mDrawState
-                                    + " ah=" + w.mAttachedHidden
+                                    + " ah=" + win.mAttachedHidden
                                     + " th=" + atoken.hiddenRequested
                                     + " a=" + winAnimator.mAnimating);
                         }
                     }
-                    if (w != atoken.startingWindow) {
-                        if (!atoken.mAppAnimator.freezingScreen || !w.mAppFreezing) {
+                    if (win != atoken.startingWindow) {
+                        if (!atoken.mAppAnimator.freezingScreen || !win.mAppFreezing) {
                             atoken.numInterestingWindows++;
-                            if (w.isDrawnLw()) {
+                            if (win.isDrawnLw()) {
                                 atoken.numDrawnWindows++;
                                 if (WindowManagerService.DEBUG_VISIBILITY ||
                                         WindowManagerService.DEBUG_ORIENTATION) Slog.v(TAG,
                                         "tokenMayBeDrawn: " + atoken
                                         + " freezingScreen=" + atoken.mAppAnimator.freezingScreen
-                                        + " mAppFreezing=" + w.mAppFreezing);
+                                        + " mAppFreezing=" + win.mAppFreezing);
                                 mTokenMayBeDrawn = true;
                             }
                         }
-                    } else if (w.isDrawnLw()) {
+                    } else if (win.isDrawnLw()) {
                         atoken.startingDisplayed = true;
                     }
                 }
@@ -371,7 +373,7 @@
                             "allDrawn: " + wtoken
                             + " interesting=" + numInteresting
                             + " drawn=" + wtoken.numDrawnWindows);
-                    wtoken.showAllWindowsLocked();
+                    wtoken.mAppAnimator.showAllWindowsLocked();
                     mService.unsetAppFreezingScreenLocked(wtoken, false, true);
                     if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(TAG,
                             "Setting mOrientationChangeComplete=true because wtoken "
@@ -394,7 +396,7 @@
 
                     // We can now show all of the drawn windows!
                     if (!mService.mOpeningApps.contains(wtoken)) {
-                        mAnimating |= wtoken.showAllWindowsLocked();
+                        mAnimating |= wtoken.mAppAnimator.showAllWindowsLocked();
                     }
                 }
             }
@@ -435,14 +437,24 @@
                 mScreenRotationAnimation.updateSurfaces();
             }
 
-            for (int i = mService.mWindows.size() - 1; i >= 0; i--) {
-                WindowState w = mService.mWindows.get(i);
-                w.mWinAnimator.prepareSurfaceLocked(true);
+            mFinished.clear();
+            for (final WindowStateAnimator winAnimator : mWinAnimators) {
+                if (winAnimator.mSurface == null) {
+                    mFinished.add(winAnimator);
+                } else {
+                    winAnimator.prepareSurfaceLocked(true);
+                }
+            }
+            for (final WindowStateAnimator winAnimator : mFinished) {
+                mWinAnimators.remove(winAnimator);
             }
 
+            if (mDimParams != null) {
+                mDimAnimator.updateParameters(mContext.getResources(), mDimParams, mCurrentTime);
+            }
             if (mDimAnimator != null && mDimAnimator.mDimShown) {
-                mAnimating |= mDimAnimator.updateSurface(mService.mInnerFields.mDimming,
-                            mCurrentTime, !mService.okToDisplay());
+                mAnimating |= mDimAnimator.updateSurface(mDimParams != null, mCurrentTime,
+                        !mService.okToDisplay());
             }
 
             if (mService.mBlackFrame != null) {
@@ -453,10 +465,6 @@
                     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 {
@@ -510,4 +518,18 @@
             pw.println( "  no DimAnimator ");
         }
     }
+
+    static class SetAnimationParams {
+        final WindowStateAnimator mWinAnimator;
+        final Animation mAnimation;
+        final int mAnimDw;
+        final int mAnimDh;
+        public SetAnimationParams(final WindowStateAnimator winAnimator,
+                                  final Animation animation, final int animDw, final int animDh) {
+            mWinAnimator = winAnimator;
+            mAnimation = animation;
+            mAnimDw = animDw;
+            mAnimDh = animDh;
+        }
+    }
 }
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 3d6c9f0..a7af8fb 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -245,10 +245,6 @@
      */
     static final boolean CUSTOM_SCREEN_ROTATION = true;
 
-    // Maximum number of milliseconds to wait for input event injection.
-    // FIXME is this value reasonable?
-    private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000;
-
     // Maximum number of milliseconds to wait for input devices to be enumerated before
     // proceding with safe mode detection.
     private static final int INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS = 1000;
@@ -355,32 +351,7 @@
      * controlling the ordering of windows in different applications.  This
      * contains AppWindowToken objects.
      */
-    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);
-            }
-        };
-    };
+    final ArrayList<AppWindowToken> mAppTokens = new ArrayList<AppWindowToken>();
 
     /**
      * Application tokens that are in the process of exiting, but still
@@ -397,32 +368,7 @@
     /**
      * Z-ordered (bottom-most first) list of all Window objects.
      */
-    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);
-            }
-        };
-    };
+    final ArrayList<WindowState> mWindows = new ArrayList<WindowState>();
 
     /**
      * Fake windows added to the window manager.  Note: ordered from top to
@@ -4855,95 +4801,26 @@
                 mAnimatorDurationScale };
     }
 
-    public int getSwitchState(int sw) {
-        if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
-                "getSwitchState()")) {
-            throw new SecurityException("Requires READ_INPUT_STATE permission");
+    // Called by window manager policy. Not exposed externally.
+    @Override
+    public int getLidState() {
+        final int SW_LID = 0x00;
+        int sw = mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_LID);
+        if (sw > 0) {
+            // Switch state: AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL.
+            return LID_CLOSED;
+        } else if (sw == 0) {
+            // Switch state: AKEY_STATE_UP.
+            return LID_OPEN;
+        } else {
+            // Switch state: AKEY_STATE_UNKNOWN.
+            return LID_ABSENT;
         }
-        return mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, sw);
     }
 
-    public int getSwitchStateForDevice(int devid, int sw) {
-        if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
-                "getSwitchStateForDevice()")) {
-            throw new SecurityException("Requires READ_INPUT_STATE permission");
-        }
-        return mInputManager.getSwitchState(devid, InputDevice.SOURCE_ANY, sw);
-    }
-
-    public int getScancodeState(int sw) {
-        if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
-                "getScancodeState()")) {
-            throw new SecurityException("Requires READ_INPUT_STATE permission");
-        }
-        return mInputManager.getScanCodeState(-1, InputDevice.SOURCE_ANY, sw);
-    }
-
-    public int getScancodeStateForDevice(int devid, int sw) {
-        if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
-                "getScancodeStateForDevice()")) {
-            throw new SecurityException("Requires READ_INPUT_STATE permission");
-        }
-        return mInputManager.getScanCodeState(devid, InputDevice.SOURCE_ANY, sw);
-    }
-
-    public int getTrackballScancodeState(int sw) {
-        if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
-                "getTrackballScancodeState()")) {
-            throw new SecurityException("Requires READ_INPUT_STATE permission");
-        }
-        return mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL, sw);
-    }
-
-    public int getDPadScancodeState(int sw) {
-        if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
-                "getDPadScancodeState()")) {
-            throw new SecurityException("Requires READ_INPUT_STATE permission");
-        }
-        return mInputManager.getScanCodeState(-1, InputDevice.SOURCE_DPAD, sw);
-    }
-
-    public int getKeycodeState(int sw) {
-        if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
-                "getKeycodeState()")) {
-            throw new SecurityException("Requires READ_INPUT_STATE permission");
-        }
-        return mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, sw);
-    }
-
-    public int getKeycodeStateForDevice(int devid, int sw) {
-        if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
-                "getKeycodeStateForDevice()")) {
-            throw new SecurityException("Requires READ_INPUT_STATE permission");
-        }
-        return mInputManager.getKeyCodeState(devid, InputDevice.SOURCE_ANY, sw);
-    }
-
-    public int getTrackballKeycodeState(int sw) {
-        if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
-                "getTrackballKeycodeState()")) {
-            throw new SecurityException("Requires READ_INPUT_STATE permission");
-        }
-        return mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_TRACKBALL, sw);
-    }
-
-    public int getDPadKeycodeState(int sw) {
-        if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
-                "getDPadKeycodeState()")) {
-            throw new SecurityException("Requires READ_INPUT_STATE permission");
-        }
-        return mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, sw);
-    }
-    
-    public boolean hasKeys(int[] keycodes, boolean[] keyExists) {
-        return mInputManager.hasKeys(-1, InputDevice.SOURCE_ANY, keycodes, keyExists);
-    }
-
+    // Called by window manager policy.  Not exposed externally.
+    @Override
     public InputChannel monitorInput(String inputChannelName) {
-        if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
-                "monitorInput()")) {
-            throw new SecurityException("Requires READ_INPUT_STATE permission");
-        }
         return mInputManager.monitorInput(inputChannelName);
     }
 
@@ -4951,14 +4828,6 @@
         mInputManager.setInputFilter(filter);
     }
 
-    public InputDevice getInputDevice(int deviceId) {
-        return mInputManager.getInputDevice(deviceId);
-    }
-
-    public int[] getInputDeviceIds() {
-        return mInputManager.getInputDeviceIds();
-    }
-
     public void enableScreenAfterBoot() {
         synchronized(mWindowMap) {
             if (DEBUG_BOOT) {
@@ -6444,164 +6313,6 @@
         sendScreenStatusToClients();
     }
 
-    /**
-     * Injects a keystroke event into the UI.
-     * Even when sync is false, this method may block while waiting for current
-     * input events to be dispatched.
-     *
-     * @param ev A motion event describing the keystroke action.  (Be sure to use
-     * {@link SystemClock#uptimeMillis()} as the timebase.)
-     * @param sync If true, wait for the event to be completed before returning to the caller.
-     * @return Returns true if event was dispatched, false if it was dropped for any reason
-     */
-    public boolean injectKeyEvent(KeyEvent ev, boolean sync) {
-        long downTime = ev.getDownTime();
-        long eventTime = ev.getEventTime();
-
-        int action = ev.getAction();
-        int code = ev.getKeyCode();
-        int repeatCount = ev.getRepeatCount();
-        int metaState = ev.getMetaState();
-        int deviceId = ev.getDeviceId();
-        int scancode = ev.getScanCode();
-        int source = ev.getSource();
-        int flags = ev.getFlags();
-        
-        if (source == InputDevice.SOURCE_UNKNOWN) {
-            source = InputDevice.SOURCE_KEYBOARD;
-        }
-
-        if (eventTime == 0) eventTime = SystemClock.uptimeMillis();
-        if (downTime == 0) downTime = eventTime;
-
-        KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
-                deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source);
-
-        final int pid = Binder.getCallingPid();
-        final int uid = Binder.getCallingUid();
-        final long ident = Binder.clearCallingIdentity();
-        
-        final int result = mInputManager.injectInputEvent(newEvent, pid, uid,
-                sync ? InputManagerService.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH
-                        : InputManagerService.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
-                INJECTION_TIMEOUT_MILLIS);
-        
-        Binder.restoreCallingIdentity(ident);
-        return reportInjectionResult(result, pid);
-    }
-
-    /**
-     * Inject a pointer (touch) event into the UI.
-     * Even when sync is false, this method may block while waiting for current
-     * input events to be dispatched.
-     *
-     * @param ev A motion event describing the pointer (touch) action.  (As noted in
-     * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
-     * {@link SystemClock#uptimeMillis()} as the timebase.)
-     * @param sync If true, wait for the event to be completed before returning to the caller.
-     * @return Returns true if event was dispatched, false if it was dropped for any reason
-     */
-    public boolean injectPointerEvent(MotionEvent ev, boolean sync) {
-        final int pid = Binder.getCallingPid();
-        final int uid = Binder.getCallingUid();
-        final long ident = Binder.clearCallingIdentity();
-        
-        MotionEvent newEvent = MotionEvent.obtain(ev);
-        if ((newEvent.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
-            newEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
-        }
-        
-        final int result = mInputManager.injectInputEvent(newEvent, pid, uid,
-                sync ? InputManagerService.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH
-                        : InputManagerService.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
-                INJECTION_TIMEOUT_MILLIS);
-        
-        Binder.restoreCallingIdentity(ident);
-        return reportInjectionResult(result, pid);
-    }
-
-    /**
-     * Inject a trackball (navigation device) event into the UI.
-     * Even when sync is false, this method may block while waiting for current
-     * input events to be dispatched.
-     *
-     * @param ev A motion event describing the trackball action.  (As noted in
-     * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
-     * {@link SystemClock#uptimeMillis()} as the timebase.)
-     * @param sync If true, wait for the event to be completed before returning to the caller.
-     * @return Returns true if event was dispatched, false if it was dropped for any reason
-     */
-    public boolean injectTrackballEvent(MotionEvent ev, boolean sync) {
-        final int pid = Binder.getCallingPid();
-        final int uid = Binder.getCallingUid();
-        final long ident = Binder.clearCallingIdentity();
-        
-        MotionEvent newEvent = MotionEvent.obtain(ev);
-        if ((newEvent.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) {
-            newEvent.setSource(InputDevice.SOURCE_TRACKBALL);
-        }
-        
-        final int result = mInputManager.injectInputEvent(newEvent, pid, uid,
-                sync ? InputManagerService.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_FINISH
-                        : InputManagerService.INPUT_EVENT_INJECTION_SYNC_WAIT_FOR_RESULT,
-                INJECTION_TIMEOUT_MILLIS);
-        
-        Binder.restoreCallingIdentity(ident);
-        return reportInjectionResult(result, pid);
-    }
-    
-    /**
-     * Inject an input event into the UI without waiting for dispatch to commence.
-     * This variant is useful for fire-and-forget input event injection.  It does not
-     * block any longer than it takes to enqueue the input event.
-     *
-     * @param ev An input event.  (Be sure to set the input source correctly.)
-     * @return Returns true if event was dispatched, false if it was dropped for any reason
-     */
-    public boolean injectInputEventNoWait(InputEvent ev) {
-        final int pid = Binder.getCallingPid();
-        final int uid = Binder.getCallingUid();
-        final long ident = Binder.clearCallingIdentity();
-        
-        final int result = mInputManager.injectInputEvent(ev, pid, uid,
-                InputManagerService.INPUT_EVENT_INJECTION_SYNC_NONE,
-                INJECTION_TIMEOUT_MILLIS);
-        
-        Binder.restoreCallingIdentity(ident);
-        return reportInjectionResult(result, pid);
-    }
-    
-    private boolean reportInjectionResult(int result, int pid) {
-        switch (result) {
-            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 InputManagerService.INPUT_EVENT_INJECTION_SUCCEEDED:
-                return true;
-            case InputManagerService.INPUT_EVENT_INJECTION_TIMED_OUT:
-                Slog.w(TAG, "Input event injection from pid " + pid + " timed out.");
-                return false;
-            case InputManagerService.INPUT_EVENT_INJECTION_FAILED:
-            default:
-                Slog.w(TAG, "Input event injection from pid " + pid + " failed.");
-                return false;
-        }
-    }
-
-    /**
-     * Temporarily set the pointer speed.  Does not save the new setting.
-     * Used by the settings application.
-     */
-    public void setPointerSpeed(int speed) {
-        if (!checkCallingPermission(android.Manifest.permission.SET_POINTER_SPEED,
-                "setPointerSpeed()")) {
-            throw new SecurityException("Requires SET_POINTER_SPEED permission");
-        }
-
-        mInputManager.setPointerSpeed(speed);
-    }
-
     private WindowState getFocusedWindow() {
         synchronized (mWindowMap) {
             return getFocusedWindowLocked();
@@ -6616,11 +6327,29 @@
         if (!mInputMonitor.waitForInputDevicesReady(
                 INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS)) {
             Slog.w(TAG, "Devices still not ready after waiting "
-                    + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
-                    + " milliseconds before attempting to detect safe mode.");
+                   + INPUT_DEVICES_READY_FOR_SAFE_MODE_DETECTION_TIMEOUT_MILLIS
+                   + " milliseconds before attempting to detect safe mode.");
         }
 
-        mSafeMode = mPolicy.detectSafeMode();
+        final int BTN_MOUSE = 0x110;
+        int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
+                KeyEvent.KEYCODE_MENU);
+        int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S);
+        int dpadState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD,
+                KeyEvent.KEYCODE_DPAD_CENTER);
+        int trackballState = mInputManager.getScanCodeState(-1, InputDevice.SOURCE_TRACKBALL,
+                BTN_MOUSE);
+        int volumeDownState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY,
+                KeyEvent.KEYCODE_VOLUME_DOWN);
+        mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
+                || volumeDownState > 0;
+        if (mSafeMode) {
+            Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
+                    + " dpad=" + dpadState + " trackball=" + trackballState + ")");
+        } else {
+            Log.i(TAG, "SAFE MODE not enabled");
+        }
+        mPolicy.setSafeMode(mSafeMode);
         return mSafeMode;
     }
 
@@ -6724,6 +6453,7 @@
         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;
+        public static final int SET_MOVE_ANIMATION = ANIMATOR_WHAT_OFFSET + 4;
 
         private Session mLastReportedHold;
 
@@ -7162,33 +6892,37 @@
 
                 // Animation messages. Move to Window{State}Animator
                 case SET_TRANSPARENT_REGION: {
-                    // TODO(cmautner): Remove sync.
-                    synchronized (mAnimator) {
-                        Pair<WindowStateAnimator, Region> pair =
+                    Pair<WindowStateAnimator, Region> pair =
                                 (Pair<WindowStateAnimator, Region>) msg.obj;
-                        final WindowStateAnimator winAnimator = pair.first;
-                        winAnimator.setTransparentRegionHint(pair.second);
-                    }
+                    final WindowStateAnimator winAnimator = pair.first;
+                    winAnimator.setTransparentRegionHint(pair.second);
 
                     scheduleAnimationLocked();
                     break;
                 }
 
                 case SET_WALLPAPER_OFFSET: {
-                    // TODO(cmautner): Remove sync.
-                    synchronized (mAnimator) {
-                        final WindowStateAnimator winAnimator = (WindowStateAnimator) msg.obj;
-                        winAnimator.setWallpaperOffset(msg.arg1, msg.arg2);
-                    }
+                    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;
-                    }
+                    mAnimator.mDimParams = (DimAnimator.Parameters) msg.obj;
+
+                    scheduleAnimationLocked();
+                    break;
+                }
+
+                case SET_MOVE_ANIMATION: {
+                    WindowAnimator.SetAnimationParams params =
+                            (WindowAnimator.SetAnimationParams) msg.obj;
+                    WindowStateAnimator winAnimator = params.mWinAnimator;
+                    winAnimator.setAnimation(params.mAnimation);
+                    winAnimator.mAnimDw = params.mAnimDw;
+                    winAnimator.mAnimDh = params.mAnimDh;
 
                     scheduleAnimationLocked();
                     break;
@@ -7972,20 +7706,19 @@
             AppWindowToken topOpeningApp = null;
             int topOpeningLayer = 0;
 
+            // TODO(cmautner): Move to animation side.
             NN = mOpeningApps.size();
             for (i=0; i<NN; i++) {
                 AppWindowToken wtoken = mOpeningApps.get(i);
-                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
-                        "Now opening app" + wtoken);
+                if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Now opening app" + wtoken);
                 wtoken.mAppAnimator.clearThumbnail();
                 wtoken.reportedVisible = false;
                 wtoken.inPendingTransaction = false;
                 wtoken.mAppAnimator.animation = null;
-                setTokenVisibilityLocked(wtoken, animLp, true,
-                        transit, false);
+                setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
                 wtoken.updateReportedVisibilityLocked();
                 wtoken.waitingToShow = false;
-                mAnimator.mAnimating |= wtoken.showAllWindowsLocked();
+                mAnimator.mAnimating |= wtoken.mAppAnimator.showAllWindowsLocked();
                 if (animLp != null) {
                     int layer = -1;
                     for (int j=0; j<wtoken.windows.size(); j++) {
@@ -8406,8 +8139,6 @@
             final int N = mWindows.size();
             for (i=N-1; i>=0; i--) {
                 WindowState w = mWindows.get(i);
-                //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
-                w.mContentChanged = false;
 
                 if (someoneLosingFocus && w == mCurrentFocus && w.isDisplayedLw()) {
                     focusDisplayed = true;
@@ -8428,7 +8159,7 @@
                     updateWallpaperVisibilityLocked();
                 }
             }
-            if (!mInnerFields.mDimming) {
+            if (!mInnerFields.mDimming && mAnimator.mDimParams != null) {
                 mAnimator.stopDimming();
             }
         } catch (RuntimeException e) {
@@ -8509,6 +8240,27 @@
         for (i=N-1; i>=0; i--) {
             final WindowState w = mWindows.get(i);
             final WindowStateAnimator winAnimator = w.mWinAnimator; 
+            
+            // If the window has moved due to its containing
+            // content frame changing, then we'd like to animate
+            // it.
+            if (w.mHasSurface && w.shouldAnimateMove()) {
+                // Frame has moved, containing content frame
+                // has also moved, and we're not currently animating...
+                // let's do something.
+                Animation a = AnimationUtils.loadAnimation(mContext,
+                        com.android.internal.R.anim.window_move_from_decor);
+                winAnimator.setAnimation(a);
+                winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left;
+                winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top;
+            } else {
+                winAnimator.mAnimDw = innerDw;
+                winAnimator.mAnimDh = innerDh;
+            }
+
+            //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
+            w.mContentChanged = false;
+            
             // TODO(cmautner): Can this move up to the loop at the end of try/catch above?
             updateResizingWindows(w);
 
@@ -8528,24 +8280,6 @@
                         }
                     }
                 }
-    
-                // If the window has moved due to its containing
-                // content frame changing, then we'd like to animate
-                // it.  The checks here are ordered by what is least
-                // likely to be true first.
-                if (w.shouldAnimateMove()) {
-                    // Frame has moved, containing content frame
-                    // has also moved, and we're not currently animating...
-                    // let's do something.
-                    Animation a = AnimationUtils.loadAnimation(mContext,
-                            com.android.internal.R.anim.window_move_from_decor);
-                    winAnimator.setAnimation(a);
-                    winAnimator.mAnimDw = w.mLastFrame.left - w.mFrame.left;
-                    winAnimator.mAnimDh = w.mLastFrame.top - w.mFrame.top;
-                } else {
-                    winAnimator.mAnimDw = innerDw;
-                    winAnimator.mAnimDh = innerDh;
-                }
             }
         }
 
@@ -8843,6 +8577,7 @@
                         wsa.mSurfaceShown = false;
                         wsa.mSurface = null;
                         ws.mHasSurface = false;
+                        mAnimator.mWinAnimators.remove(wsa);
                         mForceRemoves.add(ws);
                         i--;
                         N--;
@@ -8856,6 +8591,7 @@
                         wsa.mSurfaceShown = false;
                         wsa.mSurface = null;
                         ws.mHasSurface = false;
+                        mAnimator.mWinAnimators.remove(wsa);
                         leakedSurface = true;
                     }
                 }
@@ -8895,6 +8631,7 @@
                     winAnimator.mSurfaceShown = false;
                     winAnimator.mSurface = null;
                     winAnimator.mWin.mHasSurface = false;
+                    mAnimator.mWinAnimators.remove(winAnimator);
                 }
 
                 try {
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index 6d0921e..220f5e0 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -121,6 +121,9 @@
     /** Was this window last hidden? */
     boolean mLastHidden;
 
+    int mAttrFlags;
+    int mAttrType;
+
     public WindowStateAnimator(final WindowManagerService service, final WindowState win,
                                final WindowState attachedWindow) {
         mService = service;
@@ -130,11 +133,12 @@
         mSession = win.mSession;
         mPolicy = mService.mPolicy;
         mContext = mService.mContext;
+        mAttrFlags = win.mAttrs.flags;
+        mAttrType = win.mAttrs.type;
     }
 
     public void setAnimation(Animation anim) {
-        if (localLOGV) Slog.v(
-            TAG, "Setting animation in " + this + ": " + anim);
+        if (localLOGV) Slog.v(TAG, "Setting animation in " + this + ": " + anim);
         mAnimating = false;
         mLocalAnimating = false;
         mAnimation = anim;
@@ -453,6 +457,7 @@
                         attrs.getTitle().toString(),
                         0, w, h, format, flags);
                 mWin.mHasSurface = true;
+                mAnimator.mWinAnimators.add(this);
                 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG,
                         "  CREATE SURFACE "
                         + mSurface + " IN SESSION "
@@ -463,12 +468,14 @@
                         + " / " + this);
             } catch (Surface.OutOfResourcesException e) {
                 mWin.mHasSurface = false;
+                mAnimator.mWinAnimators.remove(this);
                 Slog.w(TAG, "OutOfResourcesException creating surface");
                 mService.reclaimSomeSurfaceMemoryLocked(this, "create", true);
                 mDrawState = NO_SURFACE;
                 return null;
             } catch (Exception e) {
                 mWin.mHasSurface = false;
+                mAnimator.mWinAnimators.remove(this);
                 Slog.e(TAG, "Exception creating surface", e);
                 mDrawState = NO_SURFACE;
                 return null;
@@ -586,6 +593,7 @@
             mSurfaceShown = false;
             mSurface = null;
             mWin.mHasSurface =false;
+            mAnimator.mWinAnimators.remove(this);
         }
     }
 
diff --git a/services/jni/com_android_server_input_InputManagerService.cpp b/services/jni/com_android_server_input_InputManagerService.cpp
index 22795bf..c137a78 100644
--- a/services/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/jni/com_android_server_input_InputManagerService.cpp
@@ -95,6 +95,7 @@
 
     jfieldID mId;
     jfieldID mName;
+    jfieldID mDescriptor;
     jfieldID mSources;
     jfieldID mKeyboardType;
     jfieldID mKeyCharacterMapFile;
@@ -509,8 +510,9 @@
 
     switch (switchCode) {
     case SW_LID:
+        // When switch value is set indicates lid is closed.
         env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyLidSwitchChanged,
-                when, switchValue == 0);
+                when, switchValue == 0 /*lidOpen*/);
         checkAndClearExceptionFromCallback(env, "notifyLidSwitchChanged");
         break;
     }
@@ -949,8 +951,9 @@
 
 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);
+    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
+    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
+            messageQueue->getLooper());
     im->incStrong(serviceObj);
     return reinterpret_cast<jint>(im);
 }
@@ -1169,12 +1172,17 @@
     }
 
     jobject deviceObj = env->NewObject(gInputDeviceClassInfo.clazz, gInputDeviceClassInfo.ctor);
-    if (! deviceObj) {
+    if (!deviceObj) {
         return NULL;
     }
 
     jstring deviceNameObj = env->NewStringUTF(deviceInfo.getName().string());
-    if (! deviceNameObj) {
+    if (!deviceNameObj) {
+        return NULL;
+    }
+
+    jstring deviceDescriptorObj = env->NewStringUTF(deviceInfo.getDescriptor().string());
+    if (!deviceDescriptorObj) {
         return NULL;
     }
 
@@ -1185,6 +1193,7 @@
 
     env->SetIntField(deviceObj, gInputDeviceClassInfo.mId, deviceInfo.getId());
     env->SetObjectField(deviceObj, gInputDeviceClassInfo.mName, deviceNameObj);
+    env->SetObjectField(deviceObj, gInputDeviceClassInfo.mDescriptor, deviceDescriptorObj);
     env->SetIntField(deviceObj, gInputDeviceClassInfo.mSources, deviceInfo.getSources());
     env->SetIntField(deviceObj, gInputDeviceClassInfo.mKeyboardType, deviceInfo.getKeyboardType());
     env->SetObjectField(deviceObj, gInputDeviceClassInfo.mKeyCharacterMapFile, fileStr);
@@ -1445,6 +1454,9 @@
     GET_FIELD_ID(gInputDeviceClassInfo.mName, gInputDeviceClassInfo.clazz,
             "mName", "Ljava/lang/String;");
 
+    GET_FIELD_ID(gInputDeviceClassInfo.mDescriptor, gInputDeviceClassInfo.clazz,
+            "mDescriptor", "Ljava/lang/String;");
+
     GET_FIELD_ID(gInputDeviceClassInfo.mSources, gInputDeviceClassInfo.clazz,
             "mSources", "I");
 
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 1773e33..ba3fd3c 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -70,7 +70,6 @@
 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;
@@ -628,8 +627,8 @@
         // pretend that 512 bytes total have happened
         stats = new NetworkStats(getElapsedRealtime(), 1)
                 .addIfaceValues(TEST_IFACE, 256L, 2L, 256L, 2L);
-        expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
-                .andReturn(stats).atLeastOnce();
+        expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
+                .andReturn(stats.getTotalBytes()).atLeastOnce();
         expectPolicyDataEnable(TYPE_WIFI, true);
 
         // TODO: consider making strongly ordered mock
@@ -699,8 +698,8 @@
         {
             expectCurrentTime();
             expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
-            expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
-                    .andReturn(stats).atLeastOnce();
+            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+                    .andReturn(stats.getTotalBytes()).atLeastOnce();
             expectPolicyDataEnable(TYPE_WIFI, true);
 
             expectClearNotifications();
@@ -722,8 +721,8 @@
         {
             expectCurrentTime();
             expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
-            expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
-                    .andReturn(stats).atLeastOnce();
+            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+                    .andReturn(stats.getTotalBytes()).atLeastOnce();
             expectPolicyDataEnable(TYPE_WIFI, true);
 
             expectRemoveInterfaceQuota(TEST_IFACE);
@@ -745,8 +744,8 @@
 
         {
             expectCurrentTime();
-            expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
-                    .andReturn(stats).atLeastOnce();
+            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+                    .andReturn(stats.getTotalBytes()).atLeastOnce();
             expectPolicyDataEnable(TYPE_WIFI, true);
 
             expectForceUpdate();
@@ -766,8 +765,8 @@
 
         {
             expectCurrentTime();
-            expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
-                    .andReturn(stats).atLeastOnce();
+            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+                    .andReturn(stats.getTotalBytes()).atLeastOnce();
             expectPolicyDataEnable(TYPE_WIFI, false);
 
             expectForceUpdate();
@@ -786,8 +785,8 @@
         {
             expectCurrentTime();
             expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
-            expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
-                    .andReturn(stats).atLeastOnce();
+            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+                    .andReturn(stats.getTotalBytes()).atLeastOnce();
             expectPolicyDataEnable(TYPE_WIFI, true);
 
             // snoozed interface still has high quota so background data is
@@ -827,8 +826,8 @@
         {
             expectCurrentTime();
             expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
-            expect(mStatsService.getSummaryForNetwork(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
-                    .andReturn(stats).atLeastOnce();
+            expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+                    .andReturn(stats.getTotalBytes()).atLeastOnce();
             expectPolicyDataEnable(TYPE_WIFI, true);
 
             expectRemoveInterfaceQuota(TEST_IFACE);
@@ -982,7 +981,7 @@
             }
         }
 
-        /** {@inheritDoc} */
+        @Override
         public boolean queueIdle() {
             set(null);
             return false;
diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
index 103d8e1..6d9bb29 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
@@ -54,6 +54,7 @@
 import android.content.Intent;
 import android.net.IConnectivityManager;
 import android.net.INetworkManagementEventObserver;
+import android.net.INetworkStatsSession;
 import android.net.LinkProperties;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
@@ -84,7 +85,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";
@@ -113,6 +114,7 @@
     private IConnectivityManager mConnManager;
 
     private NetworkStatsService mService;
+    private INetworkStatsSession mSession;
     private INetworkManagementEventObserver mNetworkObserver;
 
     @Override
@@ -134,6 +136,7 @@
         mService = new NetworkStatsService(
                 mServiceContext, mNetManager, mAlarmManager, mTime, mStatsDir, mSettings);
         mService.bindConnectivityManager(mConnManager);
+        mSession = mService.openSession();
 
         mElapsedRealtime = 0L;
 
@@ -172,6 +175,7 @@
         mSettings = null;
         mConnManager = null;
 
+        mSession.close();
         mService = null;
 
         super.tearDown();
@@ -349,7 +353,7 @@
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
 
         // verify service recorded history
-        history = mService.getHistoryForNetwork(sTemplateWifi, FIELD_ALL);
+        history = mSession.getHistoryForNetwork(sTemplateWifi, FIELD_ALL);
         assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0);
         assertEquals(HOUR_IN_MILLIS, history.getBucketDuration());
         assertEquals(2, history.size());
@@ -367,7 +371,7 @@
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
 
         // verify identical stats, but spread across 4 buckets now
-        history = mService.getHistoryForNetwork(sTemplateWifi, FIELD_ALL);
+        history = mSession.getHistoryForNetwork(sTemplateWifi, FIELD_ALL);
         assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, 512L, 4L, 512L, 4L, 0);
         assertEquals(30 * MINUTE_IN_MILLIS, history.getBucketDuration());
         assertEquals(4, history.size());
@@ -652,7 +656,7 @@
         mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL));
 
         // first verify entire history present
-        NetworkStats stats = mService.getSummaryForAllUid(
+        NetworkStats stats = mSession.getSummaryForAllUid(
                 sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true);
         assertEquals(3, stats.size());
         assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 1);
@@ -661,7 +665,7 @@
 
         // now verify that recent history only contains one uid
         final long currentTime = currentTimeMillis();
-        stats = mService.getSummaryForAllUid(
+        stats = mSession.getSummaryForAllUid(
                 sTemplateWifi, currentTime - HOUR_IN_MILLIS, currentTime, true);
         assertEquals(1, stats.size());
         assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, 1024L, 8L, 512L, 4L, 0);
@@ -723,7 +727,7 @@
         assertUidTotal(sTemplateWifi, UID_RED, 160L, 4L, 160L, 4L, 2);
 
         // verify entire history present
-        final NetworkStats stats = mService.getSummaryForAllUid(
+        final NetworkStats stats = mSession.getSummaryForAllUid(
                 sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true);
         assertEquals(4, stats.size());
         assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 1);
@@ -775,20 +779,20 @@
     }
 
     private void assertNetworkTotal(NetworkTemplate template, long rxBytes, long rxPackets,
-            long txBytes, long txPackets, int operations) {
-        final NetworkStatsHistory history = mService.getHistoryForNetwork(template, FIELD_ALL);
+            long txBytes, long txPackets, int operations) throws Exception {
+        final NetworkStatsHistory history = mSession.getHistoryForNetwork(template, FIELD_ALL);
         assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, rxPackets, txBytes,
                 txPackets, operations);
     }
 
     private void assertUidTotal(NetworkTemplate template, int uid, long rxBytes, long rxPackets,
-            long txBytes, long txPackets, int operations) {
+            long txBytes, long txPackets, int operations) throws Exception {
         assertUidTotal(template, uid, SET_ALL, rxBytes, rxPackets, txBytes, txPackets, operations);
     }
 
     private void assertUidTotal(NetworkTemplate template, int uid, int set, long rxBytes,
-            long rxPackets, long txBytes, long txPackets, int operations) {
-        final NetworkStatsHistory history = mService.getHistoryForUid(
+            long rxPackets, long txBytes, long txPackets, int operations) throws Exception {
+        final NetworkStatsHistory history = mSession.getHistoryForUid(
                 template, uid, set, TAG_NONE, FIELD_ALL);
         assertValues(history, Long.MIN_VALUE, Long.MAX_VALUE, rxBytes, rxPackets, txBytes,
                 txPackets, operations);
diff --git a/telephony/java/com/android/internal/telephony/IccCard.java b/telephony/java/com/android/internal/telephony/IccCard.java
index 2139917..92024cd 100644
--- a/telephony/java/com/android/internal/telephony/IccCard.java
+++ b/telephony/java/com/android/internal/telephony/IccCard.java
@@ -580,7 +580,9 @@
             mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_ADDED, null));
         }
 
-        if (oldState != State.READY && newState == State.READY) {
+        // Call onReady only when SIM or RUIM card becomes ready (not NV)
+        if (oldState != State.READY && newState == State.READY &&
+                (is3gpp || isSubscriptionFromIccCard)) {
             mIccFileHandler.setAid(getAid());
             mIccRecords.onReady();
         }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index ed0081b..9f6ec71 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -205,6 +205,8 @@
 
         // Sets operator numeric property by retrieving from build-time system property
         String operatorNumeric = SystemProperties.get(PROPERTY_CDMA_HOME_OPERATOR_NUMERIC);
+        log("CDMAPhone: init set 'gsm.sim.operator.numeric' to operator='" +
+                operatorNumeric + "'");
         setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, operatorNumeric);
 
         // Sets iso country property by retrieving from build-time system property
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
index 3855515..2fefa3f 100755
--- a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
@@ -329,11 +329,11 @@
 
     @Override
     protected void onAllRecordsLoaded() {
-        log("RuimRecords: record load complete");
-
         // Further records that can be inserted are Operator/OEM dependent
 
         String operator = getRUIMOperatorNumeric();
+        log("RuimRecords: onAllRecordsLoaded set 'gsm.sim.operator.numeric' to operator='" +
+                operator + "'");
         SystemProperties.set(PROPERTY_ICC_OPERATOR_NUMERIC, operator);
 
         if (mImsi != null) {
diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
index b88af2c..80988fd 100755
--- a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
@@ -228,6 +228,7 @@
 
         adnCache.reset();
 
+        log("SIMRecords: onRadioOffOrNotAvailable set 'gsm.sim.operator.numeric' to operator=null");
         SystemProperties.set(PROPERTY_ICC_OPERATOR_NUMERIC, null);
         SystemProperties.set(PROPERTY_ICC_OPERATOR_ALPHA, null);
         SystemProperties.set(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, null);
@@ -1254,12 +1255,12 @@
     }
 
     protected void onAllRecordsLoaded() {
-        log("record load complete");
-
         String operator = getOperatorNumeric();
 
         // Some fields require more than one SIM record to set
 
+        log("SIMRecords: onAllRecordsLoaded set 'gsm.sim.operator.numeric' to operator='" +
+                operator + "'");
         SystemProperties.set(PROPERTY_ICC_OPERATOR_NUMERIC, operator);
 
         if (imsi != null) {
diff --git a/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java b/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java
index b7e80d4..919e2b3 100644
--- a/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java
+++ b/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java
@@ -17,15 +17,16 @@
 
 import android.content.Context;
 import android.net.INetworkStatsService;
+import android.net.INetworkStatsSession;
+import android.net.NetworkStats;
 import android.net.NetworkStats.Entry;
 import android.net.NetworkTemplate;
-import android.net.NetworkStats;
+import android.net.TrafficStats;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.telephony.TelephonyManager;
 import android.test.InstrumentationTestCase;
-import android.test.InstrumentationTestRunner;
 import android.util.Log;
 
 /**
@@ -71,13 +72,17 @@
      * @param template {link {@link NetworkTemplate} to match.
      */
     private void fetchStats(NetworkTemplate template) {
+        INetworkStatsSession session = null;
         try {
             mStatsService.forceUpdate();
-            NetworkStats stats = mStatsService.getSummaryForAllUid(template, Long.MIN_VALUE,
-                    Long.MAX_VALUE, false);
+            session = mStatsService.openSession();
+            final NetworkStats stats = session.getSummaryForAllUid(
+                    template, Long.MIN_VALUE, Long.MAX_VALUE, false);
             reportStats(stats);
         } catch (RemoteException e) {
             Log.w(LOG_TAG, "Failed to fetch network stats.");
+        } finally {
+            TrafficStats.closeQuietly(session);
         }
     }
 
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 58f65be..1f6279c 100644
--- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
@@ -255,41 +255,6 @@
 	}    
 
     @SmallTest
-    public void testINJECT_EVENTS() {
-        try {
-            mWm.injectKeyEvent(new KeyEvent(0, 0), false);
-            fail("IWindowManager.injectKeyEvent did not throw SecurityException as"
-                    + " expected");
-        } catch (SecurityException e) {
-            // expected
-        } catch (RemoteException e) {
-            fail("Unexpected remote exception");
-        }
-        
-        try {
-            mWm.injectPointerEvent(MotionEvent.obtain(0, 0, 0, 0, 0, 0, 0, 0, 0,
-                    0, 0, 0), false);
-            fail("IWindowManager.injectPointerEvent did not throw SecurityException as"
-                    + " expected");
-        } catch (SecurityException e) {
-            // expected
-        } catch (RemoteException e) {
-            fail("Unexpected remote exception");
-        }
-        
-        try {
-            mWm.injectTrackballEvent(MotionEvent.obtain(0, 0, 0, 0, 0, 0, 0, 0, 0,
-                    0, 0, 0), false);
-            fail("IWindowManager.injectTrackballEvent did not throw SecurityException as"
-                    + " expected");
-        } catch (SecurityException e) {
-            // expected
-        } catch (RemoteException e) {
-            fail("Unexpected remote exception");
-        }
-    }
-    
-    @SmallTest
     public void testDISABLE_KEYGUARD() {
         Binder token = new Binder();
         try {
@@ -347,73 +312,9 @@
     }
     
     @SmallTest
-    public void testREAD_INPUT_STATE() {
-        try {
-            mWm.getSwitchState(0);
-            fail("IWindowManager.getSwitchState did not throw SecurityException as"
-                    + " expected");
-        } catch (SecurityException e) {
-            // expected
-        } catch (RemoteException e) {
-            fail("Unexpected remote exception");
-        }
-        
-        try {
-            mWm.getSwitchStateForDevice(0, 0);
-            fail("IWindowManager.getSwitchStateForDevice did not throw SecurityException as"
-                    + " expected");
-        } catch (SecurityException e) {
-            // expected
-        } catch (RemoteException e) {
-            fail("Unexpected remote exception");
-        }
-        
-        try {
-            mWm.getScancodeState(0);
-            fail("IWindowManager.getScancodeState did not throw SecurityException as"
-                    + " expected");
-        } catch (SecurityException e) {
-            // expected
-        } catch (RemoteException e) {
-            fail("Unexpected remote exception");
-        }
-        
-        try {
-            mWm.getScancodeStateForDevice(0, 0);
-            fail("IWindowManager.getScancodeStateForDevice did not throw SecurityException as"
-                    + " expected");
-        } catch (SecurityException e) {
-            // expected
-        } catch (RemoteException e) {
-            fail("Unexpected remote exception");
-        }
-        
-        try {
-            mWm.getKeycodeState(0);
-            fail("IWindowManager.getKeycodeState did not throw SecurityException as"
-                    + " expected");
-        } catch (SecurityException e) {
-            // expected
-        } catch (RemoteException e) {
-            fail("Unexpected remote exception");
-        }
-        
-        try {
-            mWm.getKeycodeStateForDevice(0, 0);
-            fail("IWindowManager.getKeycodeStateForDevice did not throw SecurityException as"
-                    + " expected");
-        } catch (SecurityException e) {
-            // expected
-        } catch (RemoteException e) {
-            fail("Unexpected remote exception");
-        }
-    }
-    
-    @SmallTest
     public void testSET_ORIENTATION() {
         try {
             mWm.updateRotation(true, false);
-            mWm.getSwitchState(0);
             fail("IWindowManager.updateRotation did not throw SecurityException as"
                     + " expected");
         } catch (SecurityException e) {
@@ -424,7 +325,6 @@
 
         try {
             mWm.freezeRotation(-1);
-            mWm.getSwitchState(0);
             fail("IWindowManager.freezeRotation did not throw SecurityException as"
                     + " expected");
         } catch (SecurityException e) {
@@ -435,7 +335,6 @@
 
         try {
             mWm.thawRotation();
-            mWm.getSwitchState(0);
             fail("IWindowManager.thawRotation did not throw SecurityException as"
                     + " expected");
         } catch (SecurityException e) {
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 198fce4..689aa8e 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -639,6 +639,12 @@
             // If an app requests write storage, they will also get read storage.
             bool hasReadExternalStoragePermission = false;
 
+            // Implement transition to read and write call log.
+            bool hasReadContactsPermission = false;
+            bool hasWriteContactsPermission = false;
+            bool hasReadCallLogPermission = false;
+            bool hasWriteCallLogPermission = false;
+
             // This next group of variables is used to implement a group of
             // backward-compatibility heuristics necessitated by the addition of
             // some new uses-feature constants in 2.1 and 2.2. In most cases, the
@@ -1006,6 +1012,14 @@
                                 hasReadExternalStoragePermission = true;
                             } else if (name == "android.permission.READ_PHONE_STATE") {
                                 hasReadPhoneStatePermission = true;
+                            } else if (name == "android.permission.READ_CONTACTS") {
+                                hasReadContactsPermission = true;
+                            } else if (name == "android.permission.WRITE_CONTACTS") {
+                                hasWriteContactsPermission = true;
+                            } else if (name == "android.permission.READ_CALL_LOG") {
+                                hasReadCallLogPermission = true;
+                            } else if (name == "android.permission.WRITE_CALL_LOG") {
+                                hasWriteCallLogPermission = true;
                             }
                             printf("uses-permission:'%s'\n", name.string());
                         } else {
@@ -1181,6 +1195,16 @@
                 printf("uses-permission:'android.permission.READ_EXTERNAL_STORAGE'\n");
             }
 
+            // Pre-JellyBean call log permission compatibility.
+            if (targetSdk < 16) {
+                if (!hasReadCallLogPermission && hasReadContactsPermission) {
+                    printf("uses-permission:'android.permission.READ_CALL_LOG'\n");
+                }
+                if (!hasWriteCallLogPermission && hasWriteContactsPermission) {
+                    printf("uses-permission:'android.permission.WRITE_CALL_LOG'\n");
+                }
+            }
+
             /* The following blocks handle printing "inferred" uses-features, based
              * on whether related features or permissions are used by the app.
              * Note that the various spec*Feature variables denote whether the
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 0755670..e6c9351 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
@@ -161,92 +161,11 @@
     }
 
     @Override
-    public int getDPadKeycodeState(int arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int getDPadScancodeState(int arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-
-    @Override
-    public InputDevice getInputDevice(int arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public int[] getInputDeviceIds() throws RemoteException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public int getKeycodeState(int arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int getKeycodeStateForDevice(int arg0, int arg1) throws RemoteException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-
-    @Override
     public int getPendingAppTransition() throws RemoteException {
         // TODO Auto-generated method stub
         return 0;
     }
 
-
-    @Override
-    public int getScancodeState(int arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int getScancodeStateForDevice(int arg0, int arg1) throws RemoteException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int getSwitchState(int arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int getSwitchStateForDevice(int arg0, int arg1) throws RemoteException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int getTrackballKeycodeState(int arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int getTrackballScancodeState(int arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public boolean hasKeys(int[] arg0, boolean[] arg1) throws RemoteException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
     @Override
     public boolean inKeyguardRestrictedInputMode() throws RemoteException {
         // TODO Auto-generated method stub
@@ -254,30 +173,6 @@
     }
 
     @Override
-    public boolean injectInputEventNoWait(InputEvent arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean injectKeyEvent(KeyEvent arg0, boolean arg1) throws RemoteException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean injectPointerEvent(MotionEvent arg0, boolean arg1) throws RemoteException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean injectTrackballEvent(MotionEvent arg0, boolean arg1) throws RemoteException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
     public boolean inputMethodClientHasFocus(IInputMethodClient arg0) throws RemoteException {
         // TODO Auto-generated method stub
         return false;
@@ -302,12 +197,6 @@
     }
 
     @Override
-    public InputChannel monitorInput(String arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
     public void moveAppToken(int arg0, IBinder arg1) throws RemoteException {
         // TODO Auto-generated method stub
 
@@ -462,12 +351,6 @@
     }
 
     @Override
-    public void setPointerSpeed(int arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
     public void updateRotation(boolean arg0, boolean arg1) throws RemoteException {
         // TODO Auto-generated method stub
     }
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index c11d082..db73ea8 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -396,11 +396,25 @@
         }
     }
 
+    public boolean startWpsPbc(String iface, String bssid) {
+        if (TextUtils.isEmpty(bssid)) {
+            return doBooleanCommand("WPS_PBC interface=" + iface);
+        } else {
+            return doBooleanCommand("WPS_PBC interface=" + iface + " " + bssid);
+        }
+    }
+
     public boolean startWpsPinKeypad(String pin) {
         if (TextUtils.isEmpty(pin)) return false;
         return doBooleanCommand("WPS_PIN any " + pin);
     }
 
+    public boolean startWpsPinKeypad(String iface, String pin) {
+        if (TextUtils.isEmpty(pin)) return false;
+        return doBooleanCommand("WPS_PIN interface=" + iface + " any " + pin);
+    }
+
+
     public String startWpsPinDisplay(String bssid) {
         if (TextUtils.isEmpty(bssid)) {
             return doStringCommand("WPS_PIN any");
@@ -409,6 +423,14 @@
         }
     }
 
+    public String startWpsPinDisplay(String iface, String bssid) {
+        if (TextUtils.isEmpty(bssid)) {
+            return doStringCommand("WPS_PIN interface=" + iface + " any");
+        } else {
+            return doStringCommand("WPS_PIN interface=" + iface + " " + bssid);
+        }
+    }
+
     /* Configures an access point connection */
     public boolean startWpsRegistrar(String bssid, String pin) {
         if (TextUtils.isEmpty(bssid) || TextUtils.isEmpty(pin)) return false;
@@ -440,6 +462,26 @@
         return doBooleanCommand("SET p2p_ssid_postfix " + postfix);
     }
 
+    public boolean setP2pGroupIdle(String iface, int time) {
+        return doBooleanCommand("SET interface=" + iface + " p2p_group_idle " + time);
+    }
+
+    public boolean setP2pPowerSave(String iface, boolean enabled) {
+        if (enabled) {
+            return doBooleanCommand("P2P_SET interface=" + iface + " ps 1");
+        } else {
+            return doBooleanCommand("P2P_SET interface=" + iface + " ps 0");
+        }
+    }
+
+    /**
+     * "sta" prioritizes STA connection over P2P and "p2p" prioritizes
+     * P2P connection over STA
+     */
+    public boolean setConcurrencyPriority(String s) {
+        return doBooleanCommand("P2P_SET conc_priority " + s);
+    }
+
     public boolean p2pFind() {
         return doBooleanCommand("P2P_FIND");
     }
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 3d3a746..32e1053 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -109,6 +109,9 @@
     /* Set a two minute discover timeout to avoid STA scans from being blocked */
     private static final int DISCOVER_TIMEOUT_S = 120;
 
+    /* Idle time after a peer is gone when the group is torn down */
+    private static final int GROUP_IDLE_TIME_S = 2;
+
     /**
      * Delay between restarts upon failure to setup connection with supplicant
      */
@@ -343,10 +346,21 @@
                 case WifiMonitor.NETWORK_CONNECTION_EVENT:
                 case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
                 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
+                case WifiMonitor.P2P_GROUP_REMOVED_EVENT:
                 case PEER_CONNECTION_USER_ACCEPT:
                 case PEER_CONNECTION_USER_REJECT:
                 case GROUP_CREATING_TIMED_OUT:
                     break;
+                /* unexpected group created, remove */
+                case WifiMonitor.P2P_GROUP_STARTED_EVENT:
+                    mGroup = (WifiP2pGroup) message.obj;
+                    loge("Unexpected group creation, remove " + mGroup);
+                    mWifiNative.p2pGroupRemove(mGroup.getInterface());
+                    break;
+                case WifiMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT:
+                    loge("Unexpected group failure, flush peers");
+                    mWifiNative.p2pFlush();
+                    break;
                 default:
                     loge("Unhandled message " + message);
                     return NOT_HANDLED;
@@ -476,6 +490,7 @@
             if (DBG) logd(getName());
             sendP2pStateChangedBroadcast(true);
             mNetworkInfo.setIsAvailable(true);
+            sendP2pConnectionChangedBroadcast();
             initializeP2pSettings();
         }
 
@@ -561,9 +576,11 @@
                         //If peer is a GO, we do not need to send provisional discovery,
                         //the supplicant takes care of it.
                         if (mWifiNative.isGroupOwner(mSavedPeerConfig.deviceAddress)) {
+                            if (DBG) logd("Sending join to GO");
                             p2pConnectWithPinDisplay(mSavedPeerConfig, JOIN_GROUP);
                             transitionTo(mGroupNegotiationState);
                         } else {
+                            if (DBG) logd("Sending prov disc");
                             transitionTo(mProvisionDiscoveryState);
                         }
                     }
@@ -651,9 +668,7 @@
                case GROUP_CREATING_TIMED_OUT:
                     if (mGroupCreatingTimeoutIndex == message.arg1) {
                         if (DBG) logd("Group negotiation timed out");
-                        updateDeviceStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.FAILED);
-                        mSavedPeerConfig = null;
-                        sendP2pPeersChangedBroadcast();
+                        handleGroupCreationFailure();
                         transitionTo(mInactiveState);
                     }
                     break;
@@ -663,12 +678,15 @@
                             WifiP2pManager.BUSY);
                     break;
                 case WifiP2pManager.CANCEL_CONNECT:
-                    if (mWifiNative.p2pCancelConnect()) {
-                        replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_SUCCEEDED);
-                    } else {
-                        replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_FAILED,
-                                WifiP2pManager.ERROR);
-                    }
+                    //Do a supplicant p2p_cancel which only cancels an ongoing
+                    //group negotiation. This will fail for a pending provision
+                    //discovery or for a pending user action, but at the framework
+                    //level, we always treat cancel as succeded and enter
+                    //an inactive state
+                    mWifiNative.p2pCancelConnect();
+                    handleGroupCreationFailure();
+                    transitionTo(mInactiveState);
+                    replyToMessage(message, WifiP2pManager.CANCEL_CONNECT_SUCCEEDED);
                     break;
                 default:
                     return NOT_HANDLED;
@@ -811,9 +829,7 @@
                 case WifiMonitor.P2P_GO_NEGOTIATION_FAILURE_EVENT:
                 case WifiMonitor.P2P_GROUP_FORMATION_FAILURE_EVENT:
                     if (DBG) logd(getName() + " go failure");
-                    updateDeviceStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.FAILED);
-                    mSavedPeerConfig = null;
-                    sendP2pPeersChangedBroadcast();
+                    handleGroupCreationFailure();
                     transitionTo(mInactiveState);
                     break;
                 default:
@@ -838,6 +854,10 @@
                 setWifiP2pInfoOnGroupFormation(SERVER_ADDRESS);
                 sendP2pConnectionChangedBroadcast();
             }
+
+            if (!mPersistGroup) {
+                mWifiNative.setP2pGroupIdle(mGroup.getInterface(), GROUP_IDLE_TIME_S);
+            }
         }
 
         @Override
@@ -886,6 +906,8 @@
                         if (DBG) logd("DhcpInfo: " + dhcpInfo);
                         setWifiP2pInfoOnGroupFormation(dhcpInfo.serverAddress);
                         sendP2pConnectionChangedBroadcast();
+                        //Turn on power save on client
+                        mWifiNative.setP2pPowerSave(mGroup.getInterface(), true);
                     } else {
                         loge("DHCP failed");
                         mWifiNative.p2pGroupRemove(mGroup.getInterface());
@@ -1258,6 +1280,8 @@
         //The supplicant default is to support everything, but a bug necessitates
         //the framework to specify this explicitly
         mWifiNative.setConfigMethods("keypad display push_button");
+        //STA has higher priority over P2P
+        mWifiNative.setConcurrencyPriority("sta");
 
         mThisDevice.deviceAddress = mWifiNative.p2pGetDeviceAddress();
         updateThisDevice(WifiP2pDevice.AVAILABLE);
@@ -1269,6 +1293,14 @@
         sendThisDeviceChangedBroadcast();
     }
 
+    private void handleGroupCreationFailure() {
+        mSavedPeerConfig = null;
+        /* After cancelling group formation, new connections on existing peers can fail
+         * at supplicant. Flush and restart discovery */
+        mWifiNative.p2pFlush();
+        sendMessage(WifiP2pManager.DISCOVER_PEERS);
+    }
+
     //State machine initiated requests can have replyTo set to null indicating
     //there are no recepients, we ignore those reply actions
     private void replyToMessage(Message msg, int what) {