From da996f390e17e16f2dfa60e972e7ebc4f868f37e Mon Sep 17 00:00:00 2001
From: The Android Open Source Project <initial-contribution@android.com>
Date: Fri, 13 Feb 2009 12:57:50 -0800
Subject: [PATCH] auto import from //branches/cupcake/...@131421

---
 Android.mk                                    |    2 +-
 api/current.xml                               | 1564 +++++++++++--
 core/java/android/app/LauncherActivity.java   |   17 -
 core/java/android/app/SearchDialog.java       |    8 +-
 core/java/android/content/Intent.java         |    2 +
 core/java/android/gadget/GadgetHost.java      |   24 +-
 core/java/android/gadget/GadgetHostView.java  |  206 +-
 core/java/android/gadget/GadgetManager.java   |  170 +-
 core/java/android/gadget/GadgetProvider.java  |   53 +-
 ...adgetInfo.aidl => GadgetProviderInfo.aidl} |    2 +-
 ...adgetInfo.java => GadgetProviderInfo.java} |   58 +-
 core/java/android/gadget/package.html         |  123 +-
 core/java/android/hardware/Camera.java        |   17 +-
 .../InputMethodService.java                   |   85 +-
 .../inputmethodservice/KeyboardView.java      |    4 +
 core/java/android/net/UrlQuerySanitizer.java  |  126 +-
 core/java/android/pim/RecurrenceSet.java      |    1 -
 .../preference/PreferenceGroupAdapter.java    |    3 +
 core/java/android/provider/Settings.java      |   22 +-
 .../server/BluetoothDeviceService.java        |   61 +-
 .../android/server/BluetoothEventLoop.java    |   83 +-
 .../text/method/ArrowKeyMovementMethod.java   |    9 +-
 .../text/method/MetaKeyKeyListener.java       |    8 +-
 .../method/PasswordTransformationMethod.java  |    6 +-
 .../android/view/HapticFeedbackConstants.java |   45 +
 core/java/android/view/IWindowSession.aidl    |    3 +-
 core/java/android/view/View.java              |  105 +-
 core/java/android/view/ViewRoot.java          |   15 +-
 core/java/android/view/WindowManager.java     |    2 +-
 .../android/view/WindowManagerPolicy.java     |   11 +
 .../view/inputmethod/BaseInputConnection.java |   30 +-
 .../view/inputmethod/InputConnection.java     |   26 +-
 .../view/inputmethod/InputMethodManager.java  |   33 +-
 core/java/android/webkit/CookieManager.java   |    9 +-
 core/java/android/webkit/WebView.java         |  126 +-
 core/java/android/webkit/WebViewCore.java     |    6 +-
 core/java/android/webkit/WebViewDatabase.java |   47 +-
 core/java/android/widget/AbsListView.java     |    4 +
 core/java/android/widget/CursorFilter.java    |    5 +-
 core/java/android/widget/DatePicker.java      |   27 +-
 core/java/android/widget/Filter.java          |    6 +
 core/java/android/widget/Gallery.java         |    6 +
 core/java/android/widget/ImageView.java       |    1 +
 core/java/android/widget/RemoteViews.java     |   69 +
 core/java/android/widget/TextView.java        |    2 +-
 core/java/android/widget/ViewAnimator.java    |    3 +
 core/java/android/widget/ViewFlipper.java     |    4 +
 core/java/android/widget/ZoomButton.java      |    2 +
 core/java/android/widget/ZoomRing.java        |  271 ++-
 .../android/widget/ZoomRingController.java    |   64 +-
 .../android/internal/gadget/IGadgetHost.aidl  |    3 +-
 .../internal/gadget/IGadgetService.aidl       |    6 +-
 .../view/IInputConnectionWrapper.java         |   24 +-
 .../android/internal/view/IInputContext.aidl  |    6 +-
 .../internal/view/IInputMethodManager.aidl    |    2 +-
 .../internal/view/InputConnectionWrapper.java |   13 +-
 .../android/internal/widget/NumberPicker.java |   62 +-
 core/jni/android_media_AudioRecord.cpp        |   37 +-
 core/jni/android_media_AudioSystem.cpp        |   16 +-
 core/jni/android_media_AudioTrack.cpp         |   33 +-
 .../jni/android_server_BluetoothEventLoop.cpp |    4 +
 core/jni/android_util_EventLog.cpp            |    2 +-
 core/res/res/drawable/presence_away.png       |  Bin 3500 -> 810 bytes
 core/res/res/drawable/presence_busy.png       |  Bin 3529 -> 811 bytes
 core/res/res/drawable/presence_invisible.png  |  Bin 1084 -> 693 bytes
 core/res/res/drawable/presence_offline.png    |  Bin 3577 -> 767 bytes
 core/res/res/drawable/presence_online.png     |  Bin 3528 -> 812 bytes
 core/res/res/drawable/zoom_ring_trail.xml     |   37 +
 core/res/res/layout/date_picker.xml           |    1 +
 core/res/res/layout/date_picker_dialog.xml    |   14 +-
 core/res/res/layout/number_picker.xml         |   30 +-
 core/res/res/layout/number_picker_edit.xml    |    1 +
 core/res/res/layout/time_picker.xml           |    2 +
 core/res/res/layout/time_picker_dialog.xml    |   14 +-
 core/res/res/layout/time_picker_text.xml      |   27 -
 core/res/res/values-cs-rCZ/strings.xml        | 1112 ---------
 core/res/res/values-cs/strings.xml            |    1 -
 core/res/res/values-de/strings.xml            |    1 -
 core/res/res/values-en-rGB/strings.xml        |  762 +-----
 core/res/res/values-es/strings.xml            |    1 -
 core/res/res/values-fr/strings.xml            |    1 -
 core/res/res/values-it/strings.xml            |    1 -
 core/res/res/values-ja/strings.xml            |   16 +-
 core/res/res/values-ko/strings.xml            |    1 -
 core/res/res/values-nb/strings.xml            |  162 +-
 core/res/res/values-nl/strings.xml            |    1 -
 core/res/res/values-pl/strings.xml            |    1 -
 core/res/res/values-ru/strings.xml            |    1 -
 core/res/res/values-zh-rCN/strings.xml        |    1 -
 core/res/res/values-zh-rTW/strings.xml        |    1 -
 core/res/res/values/attrs.xml                 |   14 +
 core/res/res/values/public.xml                |    3 +
 core/res/res/values/strings.xml               |    3 +-
 .../graphics/drawable/GradientDrawable.java   |  133 +-
 .../graphics/drawable/RotateDrawable.java     |    7 +
 .../graphics/drawable/ScaleDrawable.java      |    7 +
 include/media/AudioSystem.h                   |   39 +-
 include/media/AudioTrack.h                    |   15 +-
 include/media/IAudioFlinger.h                 |   13 +-
 include/media/IAudioFlingerClient.h           |    2 +-
 include/media/IMediaRecorder.h                |    1 +
 include/media/PVMediaRecorder.h               |    1 +
 include/media/mediarecorder.h                 |    1 +
 include/ui/ISurface.h                         |   12 +-
 include/utils/logger.h                        |   46 -
 libs/audioflinger/AudioFlinger.cpp            | 2069 +++++++++++------
 libs/audioflinger/AudioFlinger.h              |  612 +++--
 libs/surfaceflinger/Android.mk                |    2 -
 libs/surfaceflinger/Layer.cpp                 |    4 +-
 libs/surfaceflinger/LayerBase.cpp             |   17 +-
 libs/surfaceflinger/LayerBase.h               |   23 +-
 libs/surfaceflinger/LayerBuffer.cpp           |   53 +-
 libs/surfaceflinger/LayerBuffer.h             |    6 +-
 libs/surfaceflinger/LayerOrientationAnim.cpp  |    2 +-
 libs/surfaceflinger/LayerScreenshot.cpp       |  110 -
 libs/surfaceflinger/LayerScreenshot.h         |   57 -
 libs/surfaceflinger/RFBServer.cpp             |  722 ------
 libs/surfaceflinger/RFBServer.h               |  316 ---
 libs/surfaceflinger/SurfaceFlinger.cpp        |  141 +-
 libs/surfaceflinger/SurfaceFlinger.h          |    4 +-
 libs/ui/ISurface.cpp                          |    2 +-
 .../location/INetworkLocationManager.java     |    9 +
 media/java/android/media/AudioManager.java    |   15 +-
 media/java/android/media/AudioRecord.java     |   59 +-
 media/java/android/media/AudioService.java    |    4 +-
 media/java/android/media/AudioTrack.java      |    8 +-
 media/java/android/media/MediaRecorder.java   |   62 +-
 media/jni/android_media_MediaRecorder.cpp     |   56 +-
 media/jni/soundpool/SoundPool.cpp             |    9 +-
 media/libmedia/AudioRecord.cpp                |   18 +-
 media/libmedia/AudioSystem.cpp                |  103 +-
 media/libmedia/AudioTrack.cpp                 |   15 +-
 media/libmedia/IAudioFlinger.cpp              |   47 +-
 media/libmedia/IAudioFlingerClient.cpp        |   12 +-
 media/libmedia/IMediaRecorder.cpp             |   29 +-
 media/libmedia/JetPlayer.cpp                  |    2 +-
 media/libmedia/ToneGenerator.cpp              |    8 +-
 media/libmedia/mediaplayer.cpp                |    2 +-
 media/libmedia/mediarecorder.cpp              |   32 +-
 .../MediaPlayerService.cpp                    |   10 +-
 .../MediaRecorderClient.cpp                   |   11 +
 .../MediaRecorderClient.h                     |    1 +
 media/libmediaplayerservice/MidiFile.cpp      |    2 +-
 media/libmediaplayerservice/VorbisPlayer.cpp  |    2 +-
 preloaded-classes                             |    2 +-
 .../com/android/server/GadgetService.java     |  137 +-
 .../server/InputMethodManagerService.java     |  479 ++--
 .../server/LocationManagerService.java        |   30 +-
 .../android/server/PackageManagerService.java |    7 +-
 .../android/server/PowerManagerService.java   |    8 +-
 .../java/com/android/server/WifiService.java  |   17 +-
 .../android/server/WindowManagerService.java  |  232 +-
 .../server/am/ActivityManagerService.java     |   76 +-
 .../android/server/am/UsageStatsService.java  |  410 +++-
 tests/AndroidTests/AndroidManifest.xml        |    1 +
 .../src/com/android/unit_tests/MenuTest.java  |   15 +-
 .../com/android/unit_tests/TextUtilsTest.java |    2 +-
 .../DumpRenderTree/compare_layout_results.py  |   33 +-
 tests/DumpRenderTree/run_layout_tests.py      |  108 +-
 .../dumprendertree/HTMLHostActivity.java      |   19 +-
 tests/ImfTest/AndroidManifest.xml             |   18 +-
 tests/ImfTest/res/values/config.xml           |   21 +
 ...stmentBigEditTextNonScrollablePanScan.java |   35 -
 ...ustmentBigEditTextNonScrollableResize.java |   35 -
 ...gEditTextActivityNonScrollablePanScan.java |   49 +
 ...igEditTextActivityNonScrollableResize.java |   49 +
 ...BigEditTextActivityScrollablePanScan.java} |   31 +-
 ... BigEditTextActivityScrollableResize.java} |   31 +-
 .../BottomEditTextActivityPanScan.java        |   25 +-
 .../samples/BottomEditTextActivityResize.java |   25 +-
 .../imftest/samples/ButtonActivity.java       |   12 +-
 ...ialog.java => EditTextActivityDialog.java} |   10 +-
 .../EditTextActivityNoScrollPanScan.java      |   38 -
 .../ManyEditTextActivityNoScrollPanScan.java  |   43 +-
 .../ManyEditTextActivityScrollPanScan.java    |   51 +-
 .../ManyEditTextActivityScrollResize.java     |   24 +-
 .../OneEditTextActivityNotSelected.java       |   48 +-
 .../samples/OneEditTextActivitySelected.java  |   40 +-
 tests/ImfTest/tests/Android.mk                |   16 +
 tests/ImfTest/tests/AndroidManifest.xml       |   34 +
 ...TextActivityNonScrollablePanScanTests.java |   49 +
 ...tTextActivityNonScrollableResizeTests.java |   48 +
 ...ditTextActivityScrollablePanScanTests.java |   48 +
 ...EditTextActivityScrollableResizeTests.java |   49 +
 .../BottomEditTextActivityPanScanTests.java   |   49 +
 .../BottomEditTextActivityResizeTests.java    |   49 +
 .../imftest/samples/ButtonActivityTest.java   |   58 +
 .../imftest/samples/ImfBaseTestCase.java      |  135 ++
 .../ManyEditTextActivityBaseTestCase.java     |   40 +
 ...yEditTextActivityNoScrollPanScanTests.java |   36 +
 ...anyEditTextActivityScrollPanScanTests.java |   37 +
 ...ManyEditTextActivityScrollResizeTests.java |   37 +
 .../OneEditTextActivityNotSelectedTests.java  |   50 +
 .../OneEditTextActivitySelectedTests.java     |   53 +
 .../GadgetHostTest/AndroidManifest.xml        |   14 +-
 .../GadgetHostTest/res/xml/gadget_info.xml    |    4 +-
 .../tests/gadgethost/GadgetHostActivity.java  |   22 +-
 .../tests/gadgethost/TestGadgetProvider.java  |    8 +-
 .../res/xml/gadget_info.xml                   |    2 +-
 .../gadgetprovider/TestGadgetProvider.java    |    6 +-
 .../com/android/layoutlib/bridge/Bridge.java  |    6 +
 .../android/net/wifi/WifiStateTracker.java    |    1 +
 202 files changed, 7660 insertions(+), 6278 deletions(-)
 rename core/java/android/gadget/{GadgetInfo.aidl => GadgetProviderInfo.aidl} (95%)
 rename core/java/android/gadget/{GadgetInfo.java => GadgetProviderInfo.java} (56%)
 create mode 100644 core/java/android/view/HapticFeedbackConstants.java
 create mode 100644 core/res/res/drawable/zoom_ring_trail.xml
 delete mode 100644 core/res/res/layout/time_picker_text.xml
 delete mode 100644 core/res/res/values-cs-rCZ/strings.xml
 delete mode 100644 include/utils/logger.h
 delete mode 100644 libs/surfaceflinger/LayerScreenshot.cpp
 delete mode 100644 libs/surfaceflinger/LayerScreenshot.h
 delete mode 100644 libs/surfaceflinger/RFBServer.cpp
 delete mode 100644 libs/surfaceflinger/RFBServer.h
 create mode 100644 tests/ImfTest/res/values/config.xml
 delete mode 100644 tests/ImfTest/src/com/android/imftest/samples/AppAdjustmentBigEditTextNonScrollablePanScan.java
 delete mode 100644 tests/ImfTest/src/com/android/imftest/samples/AppAdjustmentBigEditTextNonScrollableResize.java
 create mode 100644 tests/ImfTest/src/com/android/imftest/samples/BigEditTextActivityNonScrollablePanScan.java
 create mode 100644 tests/ImfTest/src/com/android/imftest/samples/BigEditTextActivityNonScrollableResize.java
 rename tests/ImfTest/src/com/android/imftest/samples/{AppAdjustmentBigEditTextScrollablePanScan.java => BigEditTextActivityScrollablePanScan.java} (54%)
 rename tests/ImfTest/src/com/android/imftest/samples/{AppAdjustmentBigEditTextScrollableResize.java => BigEditTextActivityScrollableResize.java} (54%)
 rename tests/ImfTest/src/com/android/imftest/samples/{AppAdjustmentEditTextDialog.java => EditTextActivityDialog.java} (88%)
 delete mode 100644 tests/ImfTest/src/com/android/imftest/samples/EditTextActivityNoScrollPanScan.java
 create mode 100755 tests/ImfTest/tests/Android.mk
 create mode 100755 tests/ImfTest/tests/AndroidManifest.xml
 create mode 100755 tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollablePanScanTests.java
 create mode 100755 tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollableResizeTests.java
 create mode 100755 tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollablePanScanTests.java
 create mode 100755 tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollableResizeTests.java
 create mode 100755 tests/ImfTest/tests/src/com/android/imftest/samples/BottomEditTextActivityPanScanTests.java
 create mode 100755 tests/ImfTest/tests/src/com/android/imftest/samples/BottomEditTextActivityResizeTests.java
 create mode 100755 tests/ImfTest/tests/src/com/android/imftest/samples/ButtonActivityTest.java
 create mode 100755 tests/ImfTest/tests/src/com/android/imftest/samples/ImfBaseTestCase.java
 create mode 100755 tests/ImfTest/tests/src/com/android/imftest/samples/ManyEditTextActivityBaseTestCase.java
 create mode 100755 tests/ImfTest/tests/src/com/android/imftest/samples/ManyEditTextActivityNoScrollPanScanTests.java
 create mode 100755 tests/ImfTest/tests/src/com/android/imftest/samples/ManyEditTextActivityScrollPanScanTests.java
 create mode 100755 tests/ImfTest/tests/src/com/android/imftest/samples/ManyEditTextActivityScrollResizeTests.java
 create mode 100755 tests/ImfTest/tests/src/com/android/imftest/samples/OneEditTextActivityNotSelectedTests.java
 create mode 100755 tests/ImfTest/tests/src/com/android/imftest/samples/OneEditTextActivitySelectedTests.java

diff --git a/Android.mk b/Android.mk
index 764e88b39450..45f0f18cfe89 100644
--- a/Android.mk
+++ b/Android.mk
@@ -167,7 +167,7 @@ aidl_files := \
 	frameworks/base/core/java/android/content/Intent.aidl \
 	frameworks/base/core/java/android/content/SyncStats.aidl \
 	frameworks/base/core/java/android/content/res/Configuration.aidl \
-	frameworks/base/core/java/android/gadget/GadgetInfo.aidl \
+	frameworks/base/core/java/android/gadget/GadgetProviderInfo.aidl \
 	frameworks/base/core/java/android/net/Uri.aidl \
 	frameworks/base/core/java/android/os/Bundle.aidl \
 	frameworks/base/core/java/android/os/ParcelFileDescriptor.aidl \
diff --git a/api/current.xml b/api/current.xml
index 55994fb6f1d0..2e8db511df36 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -3562,6 +3562,17 @@
  visibility="public"
 >
 </field>
+<field name="hapticFeedbackEnabled"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843358"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="hasCode"
  type="int"
  transient="false"
@@ -3859,6 +3870,17 @@
  visibility="public"
 >
 </field>
+<field name="innerRadius"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843359"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="innerRadiusRatio"
  type="int"
  transient="false"
@@ -7434,6 +7456,17 @@
  visibility="public"
 >
 </field>
+<field name="thickness"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843360"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="thicknessRatio"
  type="int"
  transient="false"
@@ -41922,6 +41955,757 @@
 </method>
 </class>
 </package>
+<package name="android.gadget"
+>
+<class name="GadgetHost"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GadgetHost"
+ type="android.gadget.GadgetHost"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="hostId" type="int">
+</parameter>
+</constructor>
+<method name="allocateGadgetId"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="createView"
+ return="android.gadget.GadgetHostView"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="gadgetId" type="int">
+</parameter>
+<parameter name="gadget" type="android.gadget.GadgetProviderInfo">
+</parameter>
+</method>
+<method name="deleteAllHosts"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="deleteGadgetId"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gadgetId" type="int">
+</parameter>
+</method>
+<method name="deleteHost"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onCreateView"
+ return="android.gadget.GadgetHostView"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="gadgetId" type="int">
+</parameter>
+<parameter name="gadget" type="android.gadget.GadgetProviderInfo">
+</parameter>
+</method>
+<method name="onProviderChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="gadgetId" type="int">
+</parameter>
+<parameter name="gadget" type="android.gadget.GadgetProviderInfo">
+</parameter>
+</method>
+<method name="startListening"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="stopListening"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="GadgetHostView"
+ extends="android.widget.ViewAnimator"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.view.animation.Animation.AnimationListener">
+</implements>
+<constructor name="GadgetHostView"
+ type="android.gadget.GadgetHostView"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<constructor name="GadgetHostView"
+ type="android.gadget.GadgetHostView"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="animationIn" type="int">
+</parameter>
+<parameter name="animationOut" type="int">
+</parameter>
+</constructor>
+<method name="getDefaultView"
+ return="android.view.View"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="getErrorView"
+ return="android.view.View"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
+<method name="getGadgetId"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getGadgetInfo"
+ return="android.gadget.GadgetProviderInfo"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onAnimationEnd"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="animation" type="android.view.animation.Animation">
+</parameter>
+</method>
+<method name="onAnimationRepeat"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="animation" type="android.view.animation.Animation">
+</parameter>
+</method>
+<method name="onAnimationStart"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="animation" type="android.view.animation.Animation">
+</parameter>
+</method>
+<method name="prepareView"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="view" type="android.view.View">
+</parameter>
+</method>
+<method name="setGadget"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gadgetId" type="int">
+</parameter>
+<parameter name="info" type="android.gadget.GadgetProviderInfo">
+</parameter>
+</method>
+<method name="updateGadget"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="remoteViews" type="android.widget.RemoteViews">
+</parameter>
+</method>
+</class>
+<class name="GadgetManager"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="bindGadgetId"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gadgetId" type="int">
+</parameter>
+<parameter name="provider" type="android.content.ComponentName">
+</parameter>
+</method>
+<method name="getGadgetInfo"
+ return="android.gadget.GadgetProviderInfo"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gadgetId" type="int">
+</parameter>
+</method>
+<method name="getInstalledProviders"
+ return="java.util.List&lt;android.gadget.GadgetProviderInfo&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getInstance"
+ return="android.gadget.GadgetManager"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</method>
+<method name="updateGadget"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gadgetIds" type="int[]">
+</parameter>
+<parameter name="views" type="android.widget.RemoteViews">
+</parameter>
+</method>
+<method name="updateGadget"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gadgetId" type="int">
+</parameter>
+<parameter name="views" type="android.widget.RemoteViews">
+</parameter>
+</method>
+<method name="updateGadget"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="provider" type="android.content.ComponentName">
+</parameter>
+<parameter name="views" type="android.widget.RemoteViews">
+</parameter>
+</method>
+<field name="ACTION_GADGET_CONFIGURE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.gadget.action.GADGET_CONFIGURE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_GADGET_DELETED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.gadget.action.GADGET_DELETED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_GADGET_DISABLED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.gadget.action.GADGET_DISABLED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_GADGET_ENABLED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.gadget.action.GADGET_ENABLED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_GADGET_PICK"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.gadget.action.GADGET_PICK&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_GADGET_UPDATE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.gadget.action.GADGET_UPDATE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_GADGET_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;gadgetId&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_GADGET_IDS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;gadgetIds&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="INVALID_GADGET_ID"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="META_DATA_GADGET_PROVIDER"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.gadget.provider&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="GadgetProvider"
+ extends="android.content.BroadcastReceiver"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GadgetProvider"
+ type="android.gadget.GadgetProvider"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="onDeleted"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="gadgetIds" type="int[]">
+</parameter>
+</method>
+<method name="onDisabled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</method>
+<method name="onEnabled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</method>
+<method name="onReceive"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+</method>
+<method name="onUpdate"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="gadgetManager" type="android.gadget.GadgetManager">
+</parameter>
+<parameter name="gadgetIds" type="int[]">
+</parameter>
+</method>
+</class>
+<class name="GadgetProviderInfo"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<constructor name="GadgetProviderInfo"
+ type="android.gadget.GadgetProviderInfo"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="GadgetProviderInfo"
+ type="android.gadget.GadgetProviderInfo"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="in" type="android.os.Parcel">
+</parameter>
+</constructor>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="out" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="configure"
+ type="android.content.ComponentName"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="icon"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="initialLayout"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="label"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="minHeight"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="minWidth"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="provider"
+ type="android.content.ComponentName"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="updatePeriodMillis"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+</package>
 <package name="android.graphics"
 >
 <class name="AvoidXfermode"
@@ -54280,50 +55064,143 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="cf" type="android.graphics.ColorFilter">
-</parameter>
-</method>
-</class>
-<class name="PaintDrawable"
- extends="android.graphics.drawable.ShapeDrawable"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="PaintDrawable"
- type="android.graphics.drawable.PaintDrawable"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<constructor name="PaintDrawable"
- type="android.graphics.drawable.PaintDrawable"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="color" type="int">
-</parameter>
-</constructor>
-<method name="setCornerRadii"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="radii" type="float[]">
+<parameter name="cf" type="android.graphics.ColorFilter">
+</parameter>
+</method>
+</class>
+<class name="PaintDrawable"
+ extends="android.graphics.drawable.ShapeDrawable"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="PaintDrawable"
+ type="android.graphics.drawable.PaintDrawable"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<constructor name="PaintDrawable"
+ type="android.graphics.drawable.PaintDrawable"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="color" type="int">
+</parameter>
+</constructor>
+<method name="setCornerRadii"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="radii" type="float[]">
+</parameter>
+</method>
+<method name="setCornerRadius"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="radius" type="float">
+</parameter>
+</method>
+</class>
+<class name="PictureDrawable"
+ extends="android.graphics.drawable.Drawable"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="PictureDrawable"
+ type="android.graphics.drawable.PictureDrawable"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="picture" type="android.graphics.Picture">
+</parameter>
+</constructor>
+<method name="draw"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="canvas" type="android.graphics.Canvas">
+</parameter>
+</method>
+<method name="getOpacity"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPicture"
+ return="android.graphics.Picture"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setAlpha"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="alpha" type="int">
+</parameter>
+</method>
+<method name="setColorFilter"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="colorFilter" type="android.graphics.ColorFilter">
 </parameter>
 </method>
-<method name="setCornerRadius"
+<method name="setPicture"
  return="void"
  abstract="false"
  native="false"
@@ -54333,11 +55210,11 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="radius" type="float">
+<parameter name="picture" type="android.graphics.Picture">
 </parameter>
 </method>
 </class>
-<class name="PictureDrawable"
+<class name="RotateDrawable"
  extends="android.graphics.drawable.Drawable"
  abstract="false"
  static="false"
@@ -54345,15 +55222,15 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<constructor name="PictureDrawable"
- type="android.graphics.drawable.PictureDrawable"
+<implements name="android.graphics.drawable.Drawable.Callback">
+</implements>
+<constructor name="RotateDrawable"
+ type="android.graphics.drawable.RotateDrawable"
  static="false"
  final="false"
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="picture" type="android.graphics.Picture">
-</parameter>
 </constructor>
 <method name="draw"
  return="void"
@@ -54368,88 +55245,8 @@
 <parameter name="canvas" type="android.graphics.Canvas">
 </parameter>
 </method>
-<method name="getOpacity"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getPicture"
- return="android.graphics.Picture"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="setAlpha"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="alpha" type="int">
-</parameter>
-</method>
-<method name="setColorFilter"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="colorFilter" type="android.graphics.ColorFilter">
-</parameter>
-</method>
-<method name="setPicture"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="picture" type="android.graphics.Picture">
-</parameter>
-</method>
-</class>
-<class name="RotateDrawable"
- extends="android.graphics.drawable.Drawable"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<implements name="android.graphics.drawable.Drawable.Callback">
-</implements>
-<constructor name="RotateDrawable"
- type="android.graphics.drawable.RotateDrawable"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<method name="draw"
- return="void"
+<method name="getDrawable"
+ return="android.graphics.drawable.Drawable"
  abstract="false"
  native="false"
  synchronized="false"
@@ -54458,8 +55255,6 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="canvas" type="android.graphics.Canvas">
-</parameter>
 </method>
 <method name="getOpacity"
  return="int"
@@ -54583,6 +55378,17 @@
 <parameter name="canvas" type="android.graphics.Canvas">
 </parameter>
 </method>
+<method name="getDrawable"
+ return="android.graphics.drawable.Drawable"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getOpacity"
  return="int"
  abstract="false"
@@ -57537,6 +58343,17 @@
  visibility="public"
 >
 </method>
+<method name="hideStatusIcon"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="hideWindow"
  return="void"
  abstract="false"
@@ -57992,6 +58809,28 @@
 <parameter name="candidatesEnd" type="int">
 </parameter>
 </method>
+<method name="onWindowHidden"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="onWindowShown"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="setCandidatesView"
  return="void"
  abstract="false"
@@ -58044,7 +58883,7 @@
 <parameter name="view" type="android.view.View">
 </parameter>
 </method>
-<method name="setStatusIcon"
+<method name="showStatusIcon"
  return="void"
  abstract="false"
  native="false"
@@ -58370,6 +59209,16 @@
  visibility="public"
 >
 </field>
+<field name="contentTopInsets"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="touchableInsets"
  type="int"
  transient="false"
@@ -58380,6 +59229,16 @@
  visibility="public"
 >
 </field>
+<field name="visibleTopInsets"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="Keyboard"
  extends="java.lang.Object"
@@ -64898,7 +65757,7 @@
 <method name="prepare"
  return="void"
  abstract="false"
- native="true"
+ native="false"
  synchronized="false"
  static="false"
  final="false"
@@ -64962,7 +65821,7 @@
 <exception name="IllegalStateException" type="java.lang.IllegalStateException">
 </exception>
 </method>
-<method name="setOutputFile"
+<method name="setCamera"
  return="void"
  abstract="false"
  native="true"
@@ -64972,6 +65831,34 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="c" type="android.hardware.Camera">
+</parameter>
+</method>
+<method name="setOutputFile"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fd" type="java.io.FileDescriptor">
+</parameter>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+</method>
+<method name="setOutputFile"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
 <parameter name="path" type="java.lang.String">
 </parameter>
 <exception name="IllegalStateException" type="java.lang.IllegalStateException">
@@ -65005,6 +65892,68 @@
 <parameter name="sv" type="android.view.Surface">
 </parameter>
 </method>
+<method name="setVideoEncoder"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="video_encoder" type="int">
+</parameter>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+</method>
+<method name="setVideoFrameRate"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="rate" type="int">
+</parameter>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+</method>
+<method name="setVideoSize"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+</method>
+<method name="setVideoSource"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="video_source" type="int">
+</parameter>
+<exception name="IllegalStateException" type="java.lang.IllegalStateException">
+</exception>
+</method>
 <method name="start"
  return="void"
  abstract="false"
@@ -65147,6 +66096,90 @@
 >
 </field>
 </class>
+<class name="MediaRecorder.VideoEncoder"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="DEFAULT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="H263"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="H264"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="MPEG_4_SP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="MediaRecorder.VideoSource"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="CAMERA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DEFAULT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="MediaScannerConnection"
  extends="java.lang.Object"
  abstract="false"
@@ -90383,6 +91416,17 @@
  visibility="public"
 >
 </field>
+<field name="HAPTIC_FEEDBACK_ENABLED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;haptic_feedback_enabled&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="HTTP_PROXY"
  type="java.lang.String"
  transient="false"
@@ -116836,6 +117880,48 @@
 >
 </field>
 </class>
+<class name="HapticFeedbackConstants"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="FLAG_IGNORE_GLOBAL_SETTING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FLAG_IGNORE_VIEW_SETTING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="LONG_PRESS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="InflateException"
  extends="java.lang.RuntimeException"
  abstract="false"
@@ -123480,6 +124566,17 @@
  visibility="public"
 >
 </method>
+<method name="isHapticFeedbackEnabled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isHorizontalFadingEdgeEnabled"
  return="boolean"
  abstract="false"
@@ -124095,6 +125192,34 @@
  visibility="public"
 >
 </method>
+<method name="performHapticFeedback"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="feedbackConstant" type="int">
+</parameter>
+</method>
+<method name="performHapticFeedback"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="feedbackConstant" type="int">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
 <method name="performLongClick"
  return="boolean"
  abstract="false"
@@ -124114,7 +125239,7 @@
  static="false"
  final="false"
  deprecated="not deprecated"
- visibility="protected"
+ visibility="public"
 >
 <parameter name="soundConstant" type="int">
 </parameter>
@@ -124581,6 +125706,19 @@
 <parameter name="focusableInTouchMode" type="boolean">
 </parameter>
 </method>
+<method name="setHapticFeedbackEnabled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="hapticFeedbackEnabled" type="boolean">
+</parameter>
+</method>
 <method name="setHorizontalFadingEdgeEnabled"
  return="void"
  abstract="false"
@@ -125358,6 +126496,17 @@
  visibility="public"
 >
 </field>
+<field name="HAPTIC_FEEDBACK_ENABLED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="268435456"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="INVISIBLE"
  type="int"
  transient="false"
@@ -133630,17 +134779,6 @@
 <parameter name="flags" type="int">
 </parameter>
 </method>
-<method name="hideStatusIcon"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="performContextMenuAction"
  return="boolean"
  abstract="false"
@@ -133682,6 +134820,19 @@
 <parameter name="text" type="android.text.Spannable">
 </parameter>
 </method>
+<method name="reportFullscreenMode"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enabled" type="boolean">
+</parameter>
+</method>
 <method name="sendKeyEvent"
  return="boolean"
  abstract="false"
@@ -133738,21 +134889,6 @@
 <parameter name="end" type="int">
 </parameter>
 </method>
-<method name="showStatusIcon"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="packageName" type="java.lang.String">
-</parameter>
-<parameter name="resId" type="int">
-</parameter>
-</method>
 </class>
 <class name="CompletionInfo"
  extends="java.lang.Object"
@@ -134561,7 +135697,7 @@
 <parameter name="flags" type="int">
 </parameter>
 </method>
-<method name="hideStatusIcon"
+<method name="performContextMenuAction"
  return="boolean"
  abstract="true"
  native="false"
@@ -134571,8 +135707,10 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="id" type="int">
+</parameter>
 </method>
-<method name="performContextMenuAction"
+<method name="performPrivateCommand"
  return="boolean"
  abstract="true"
  native="false"
@@ -134582,10 +135720,12 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="id" type="int">
+<parameter name="action" type="java.lang.String">
+</parameter>
+<parameter name="data" type="android.os.Bundle">
 </parameter>
 </method>
-<method name="performPrivateCommand"
+<method name="reportFullscreenMode"
  return="boolean"
  abstract="true"
  native="false"
@@ -134595,9 +135735,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="action" type="java.lang.String">
-</parameter>
-<parameter name="data" type="android.os.Bundle">
+<parameter name="enabled" type="boolean">
 </parameter>
 </method>
 <method name="sendKeyEvent"
@@ -134643,21 +135781,6 @@
 <parameter name="end" type="int">
 </parameter>
 </method>
-<method name="showStatusIcon"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="packageName" type="java.lang.String">
-</parameter>
-<parameter name="resId" type="int">
-</parameter>
-</method>
 <field name="GET_EXTRACTED_TEXT_MONITOR"
  type="int"
  transient="false"
@@ -135158,6 +136281,19 @@
 <parameter name="flags" type="int">
 </parameter>
 </method>
+<method name="hideStatusIcon"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="imeToken" type="android.os.IBinder">
+</parameter>
+</method>
 <method name="isAcceptingText"
  return="boolean"
  abstract="false"
@@ -135193,6 +136329,17 @@
  visibility="public"
 >
 </method>
+<method name="isFullscreenMode"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isWatchingCursor"
  return="boolean"
  abstract="false"
@@ -135277,6 +136424,23 @@
 <parameter name="flags" type="int">
 </parameter>
 </method>
+<method name="showStatusIcon"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="imeToken" type="android.os.IBinder">
+</parameter>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+<parameter name="iconId" type="int">
+</parameter>
+</method>
 <method name="updateCursor"
  return="void"
  abstract="false"
@@ -135336,21 +136500,6 @@
 <parameter name="candidatesEnd" type="int">
 </parameter>
 </method>
-<method name="updateStatusIcon"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="iconId" type="int">
-</parameter>
-<parameter name="iconPackage" type="java.lang.String">
-</parameter>
-</method>
 <field name="HIDE_IMPLICIT_ONLY"
  type="int"
  transient="false"
@@ -150635,6 +151784,23 @@
 <parameter name="level" type="int">
 </parameter>
 </method>
+<method name="setFlipping"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="viewId" type="int">
+</parameter>
+<parameter name="flipping" type="boolean">
+</parameter>
+<parameter name="milliseconds" type="int">
+</parameter>
+</method>
 <method name="setImageViewBitmap"
  return="void"
  abstract="false"
diff --git a/core/java/android/app/LauncherActivity.java b/core/java/android/app/LauncherActivity.java
index c363f04bd396..d6fcbb1a6aa7 100644
--- a/core/java/android/app/LauncherActivity.java
+++ b/core/java/android/app/LauncherActivity.java
@@ -18,7 +18,6 @@ package android.app;
 
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
@@ -31,9 +30,7 @@ import android.graphics.Rect;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.PaintDrawable;
-import android.os.AsyncTask;
 import android.os.Bundle;
-import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -145,17 +142,6 @@ public abstract class LauncherActivity extends ListActivity {
             return view;
         }
 
-        private char getCandidateLetter(ResolveInfo info) {
-            PackageManager pm = LauncherActivity.this.getPackageManager();
-            CharSequence label = info.loadLabel(pm);
-
-            if (label == null) {
-                label = info.activityInfo.name;
-            }
-
-            return Character.toLowerCase(label.charAt(0));
-        }
-
         private void bindView(View view, ListItem item) {
             TextView text = (TextView) view;
             text.setText(item.label);
@@ -191,7 +177,6 @@ public abstract class LauncherActivity extends ListActivity {
                         results.count = list.size();
                     }
                 } else {
-                    final PackageManager pm = LauncherActivity.this.getPackageManager();
                     final String prefixString = prefix.toString().toLowerCase();
 
                     ArrayList<ListItem> values = mOriginalValues;
@@ -243,8 +228,6 @@ public abstract class LauncherActivity extends ListActivity {
         private int mIconWidth = -1;
         private int mIconHeight = -1;
 
-        private final Paint mPaint = new Paint();
-        private final Rect mBounds = new Rect();
         private final Rect mOldBounds = new Rect();
         private Canvas mCanvas = new Canvas();
         
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 64f1ba221474..5744ddca792b 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -835,9 +835,6 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
         // also guard against possible race conditions (late arrival after dismiss)
         if (mSearchable != null) {
             handled = doSuggestionsKey(v, keyCode, event);
-            if (!handled) {
-                handled = refocusingKeyListener(v, keyCode, event);
-            }
         }
         return handled;
     }
@@ -1024,6 +1021,11 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
      * @param jamQuery True means to set the query, false means to reset it to the user's choice
      */
     private void jamSuggestionQuery(boolean jamQuery, AdapterView<?> parent, int position) {
+        // quick check against race conditions
+        if (mSearchable == null) {
+            return;
+        }
+        
         mSuggestionsAdapter.setNonUserQuery(true);       // disables any suggestions processing
         if (jamQuery) {
             CursorAdapter ca = getSuggestionsAdapter(parent);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 52aae0d3b437..c4d3f9d2ecee 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1112,6 +1112,8 @@ public class Intent implements Parcelable {
      * <p>My include the following extras:
      * <ul>
      * <li> {@link #EXTRA_UID} containing the integer uid assigned to the new package.
+     * <li> {@link #EXTRA_REPLACING} is set to true if this is following
+     * an {@link #ACTION_PACKAGE_REMOVED} broadcast for the same package.
      * </ul>
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
diff --git a/core/java/android/gadget/GadgetHost.java b/core/java/android/gadget/GadgetHost.java
index 9176d1829853..31aed32a1e2b 100644
--- a/core/java/android/gadget/GadgetHost.java
+++ b/core/java/android/gadget/GadgetHost.java
@@ -38,6 +38,7 @@ import com.android.internal.gadget.IGadgetService;
 public class GadgetHost {
 
     static final int HANDLE_UPDATE = 1;
+    static final int HANDLE_PROVIDER_CHANGED = 2;
 
     static Object sServiceLock = new Object();
     static IGadgetService sService;
@@ -52,6 +53,13 @@ public class GadgetHost {
             msg.obj = views;
             msg.sendToTarget();
         }
+
+        public void providerChanged(int gadgetId, GadgetProviderInfo info) {
+            Message msg = mHandler.obtainMessage(HANDLE_PROVIDER_CHANGED);
+            msg.arg1 = gadgetId;
+            msg.obj = info;
+            msg.sendToTarget();
+        }
     }
 
     Handler mHandler = new Handler() {
@@ -61,6 +69,10 @@ public class GadgetHost {
                     updateGadgetView(msg.arg1, (RemoteViews)msg.obj);
                     break;
                 }
+                case HANDLE_PROVIDER_CHANGED: {
+                    onProviderChanged(msg.arg1, (GadgetProviderInfo)msg.obj);
+                    break;
+                }
             }
         }
     };
@@ -183,7 +195,8 @@ public class GadgetHost {
         }
     }
 
-    public final GadgetHostView createView(Context context, int gadgetId, GadgetInfo gadget) {
+    public final GadgetHostView createView(Context context, int gadgetId,
+            GadgetProviderInfo gadget) {
         GadgetHostView view = onCreateView(context, gadgetId, gadget);
         view.setGadget(gadgetId, gadget);
         synchronized (mViews) {
@@ -203,9 +216,16 @@ public class GadgetHost {
      * Called to create the GadgetHostView.  Override to return a custom subclass if you
      * need it.  {@more}
      */
-    protected GadgetHostView onCreateView(Context context, int gadgetId, GadgetInfo gadget) {
+    protected GadgetHostView onCreateView(Context context, int gadgetId,
+            GadgetProviderInfo gadget) {
         return new GadgetHostView(context);
     }
+    
+    /**
+     * Called when the gadget provider for a gadget has been upgraded to a new apk.
+     */
+    protected void onProviderChanged(int gadgetId, GadgetProviderInfo gadget) {
+    }
 
     void updateGadgetView(int gadgetId, RemoteViews views) {
         GadgetHostView v;
diff --git a/core/java/android/gadget/GadgetHostView.java b/core/java/android/gadget/GadgetHostView.java
index d92c1236f078..a985bd415559 100644
--- a/core/java/android/gadget/GadgetHostView.java
+++ b/core/java/android/gadget/GadgetHostView.java
@@ -18,7 +18,6 @@ package android.gadget;
 
 import android.content.Context;
 import android.content.pm.PackageManager;
-import android.gadget.GadgetInfo;
 import android.graphics.Color;
 import android.util.Config;
 import android.util.Log;
@@ -26,12 +25,18 @@ import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.animation.Animation;
 import android.widget.FrameLayout;
 import android.widget.RemoteViews;
 import android.widget.TextView;
 import android.widget.ViewAnimator;
 
-public class GadgetHostView extends ViewAnimator {
+/**
+ * Provides the glue to show gadget views. This class offers automatic animation
+ * between updates, and will try recycling old views for each incoming
+ * {@link RemoteViews}.
+ */
+public class GadgetHostView extends ViewAnimator implements Animation.AnimationListener {
     static final String TAG = "GadgetHostView";
     static final boolean LOGD = Config.LOGD || true;
 
@@ -42,57 +47,93 @@ public class GadgetHostView extends ViewAnimator {
             return clazz.isAnnotationPresent(RemoteViews.RemoteView.class);
         }
     };
-
+    
+    Context mLocalContext;
+    
     int mGadgetId;
-    GadgetInfo mInfo;
-    View mActiveView;
-    View mStaleView;
+    GadgetProviderInfo mInfo;
     
-    protected int mDefaultGravity = Gravity.CENTER;
-
+    View mActiveView = null;
+    View mStaleView = null;
+    
+    int mActiveLayoutId = -1;
+    int mStaleLayoutId = -1;
+    
+    /**
+     * Last set of {@link RemoteViews} applied to {@link #mActiveView}
+     */
+    RemoteViews mActiveActions = null;
+    
+    /**
+     * Flag indicating that {@link #mActiveActions} has been applied to
+     * {@link #mStaleView}, meaning it's readyto recycle.
+     */
+    boolean mStalePrepared = false;
+    
+    /**
+     * Create a host view.  Uses default fade animations.
+     */
     public GadgetHostView(Context context) {
-        super(context);
+        this(context, android.R.anim.fade_in, android.R.anim.fade_out);
     }
 
-    public void setGadget(int gadgetId, GadgetInfo info) {
-        if (LOGD) Log.d(TAG, "setGadget is incoming with info=" + info);
+    /**
+     * Create a host view. Uses specified animations when pushing
+     * {@link #updateGadget(RemoteViews)}.
+     * 
+     * @param animationIn Resource ID of in animation to use
+     * @param animationOut Resource ID of out animation to use
+     */
+    public GadgetHostView(Context context, int animationIn, int animationOut) {
+        super(context);
+        mLocalContext = context;
+        
+        // Prepare our default transition animations
+        setAnimateFirstView(true);
+        setInAnimation(context, animationIn);
+        setOutAnimation(context, animationOut);
+
+        // Watch for animation events to prepare recycling
+        Animation inAnimation = getInAnimation();
+        if (inAnimation != null) {
+            inAnimation.setAnimationListener(this);
+        }
+    }
+    
+    /**
+     * Set the gadget that will be displayed by this view.
+     */
+    public void setGadget(int gadgetId, GadgetProviderInfo info) {
         if (mInfo != null) {
             // TODO: remove the old view, or whatever
         }
         mGadgetId = gadgetId;
         mInfo = info;
-        
-        View defaultView = getDefaultView();
-        flipUpdate(defaultView);
     }
     
-    /**
-     * Trigger actual animation between current and new content in the
-     * {@link ViewAnimator}.
-     */
-    protected void flipUpdate(View newContent) {
-        if (LOGD) Log.d(TAG, "pushing an update to surface");
-        
-        // Take requested dimensions from parent, but apply default gravity.
-        ViewGroup.LayoutParams requested = newContent.getLayoutParams();
-        if (requested == null) {
-            requested = new FrameLayout.LayoutParams(LayoutParams.FILL_PARENT,
-                    LayoutParams.FILL_PARENT);
+    public int getGadgetId() {
+        return mGadgetId;
+    }
+    
+    public GadgetProviderInfo getGadgetInfo() {
+        return mInfo;
+    }
+
+    public void onAnimationEnd(Animation animation) {
+        // When our transition animation finishes, we should try bringing our
+        // newly-stale view up to the current view.
+        if (mActiveActions != null &&
+                mStaleLayoutId == mActiveActions.getLayoutId()) {
+            if (LOGD) Log.d(TAG, "after animation, layoutId matched so we're recycling old view");
+            mActiveActions.reapply(mLocalContext, mStaleView);
+            mStalePrepared = true;
         }
-        
-        FrameLayout.LayoutParams params =
-            new FrameLayout.LayoutParams(requested.width, requested.height);
-        params.gravity = mDefaultGravity;
-        newContent.setLayoutParams(params);
-        
-        // Add new content and animate to it
-        addView(newContent);
-        showNext();
-        
-        // Dispose old stale view
-        removeView(mStaleView);
-        mStaleView = mActiveView;
-        mActiveView = newContent;
+    }
+
+    public void onAnimationRepeat(Animation animation) {
+    }
+
+    public void onAnimationStart(Animation animation) {
     }
 
     /**
@@ -100,26 +141,42 @@ public class GadgetHostView extends ViewAnimator {
      * gadget provider. Will animate into these new views as needed.
      */
     public void updateGadget(RemoteViews remoteViews) {
-        if (LOGD) Log.d(TAG, "updateGadget() with remoteViews = " + remoteViews);
+        if (LOGD) Log.d(TAG, "updateGadget called");
         
+        boolean recycled = false;
         View newContent = null;
         Exception exception = null;
         
-        try {
-            if (remoteViews == null) {
-                // there is no remoteViews (yet), so use the initial layout
-                newContent = getDefaultView();
-            } else {
-                // use the RemoteViews
-                // TODO: try applying RemoteViews to existing staleView if available 
-                newContent = remoteViews.apply(mContext, this);
+        if (remoteViews == null) {
+            newContent = getDefaultView();
+        }
+        
+        // If our stale view has been prepared to match active, and the new
+        // layout matches, try recycling it
+        if (newContent == null && mStalePrepared &&
+                remoteViews.getLayoutId() == mStaleLayoutId) {
+            try {
+                remoteViews.reapply(mLocalContext, mStaleView);
+                newContent = mStaleView;
+                recycled = true;
+                if (LOGD) Log.d(TAG, "was able to recycled existing layout");
+            } catch (RuntimeException e) {
+                exception = e;
+            }
+        }
+        
+        // Try normal RemoteView inflation
+        if (newContent == null) {
+            try {
+                newContent = remoteViews.apply(mLocalContext, this);
+                if (LOGD) Log.d(TAG, "had to inflate new layout");
+            } catch (RuntimeException e) {
+                exception = e;
             }
-        } catch (RuntimeException e) {
-            exception = e;
         }
         
         if (exception != null && LOGD) {
-            Log.w(TAG, "Error inflating gadget " + mInfo, exception);
+            Log.w(TAG, "Error inflating gadget " + getGadgetInfo(), exception);
         }
         
         if (newContent == null) {
@@ -128,8 +185,44 @@ public class GadgetHostView extends ViewAnimator {
             if (LOGD) Log.d(TAG, "updateGadget couldn't find any view, so inflating error");
             newContent = getErrorView();
         }
-
-        flipUpdate(newContent);
+        
+        if (!recycled) {
+            prepareView(newContent);
+            addView(newContent);
+        }
+        
+        showNext();
+        
+        if (!recycled) {
+            removeView(mStaleView);
+        }
+        
+        mStalePrepared = false;
+        mActiveActions = remoteViews;
+        
+        mStaleView = mActiveView;
+        mActiveView = newContent;
+        
+        mStaleLayoutId = mActiveLayoutId;
+        mActiveLayoutId = (remoteViews == null) ? -1 : remoteViews.getLayoutId();
+    }
+    
+    /**
+     * Prepare the given view to be shown. This might include adjusting
+     * {@link FrameLayout.LayoutParams} before inserting.
+     */
+    protected void prepareView(View view) {
+        // Take requested dimensions from parent, but apply default gravity.
+        ViewGroup.LayoutParams requested = view.getLayoutParams();
+        if (requested == null) {
+            requested = new FrameLayout.LayoutParams(LayoutParams.FILL_PARENT,
+                    LayoutParams.FILL_PARENT);
+        }
+        
+        FrameLayout.LayoutParams params =
+            new FrameLayout.LayoutParams(requested.width, requested.height);
+        params.gravity = Gravity.CENTER;
+        view.setLayoutParams(params);
     }
     
     /**
@@ -141,7 +234,7 @@ public class GadgetHostView extends ViewAnimator {
         
         try {
             if (mInfo != null) {
-                Context theirContext = mContext.createPackageContext(
+                Context theirContext = mLocalContext.createPackageContext(
                         mInfo.provider.getPackageName(), 0 /* no flags */);
                 LayoutInflater inflater = (LayoutInflater)
                         theirContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@@ -173,11 +266,10 @@ public class GadgetHostView extends ViewAnimator {
      * Inflate and return a view that represents an error state.
      */
     protected View getErrorView() {
-        TextView tv = new TextView(mContext);
+        TextView tv = new TextView(mLocalContext);
         // TODO: move this error string and background color into resources
         tv.setText("Error inflating gadget");
         tv.setBackgroundColor(Color.argb(127, 0, 0, 0));
         return tv;
     }
 }
-
diff --git a/core/java/android/gadget/GadgetManager.java b/core/java/android/gadget/GadgetManager.java
index 20f40140cbdb..a9a2c8010596 100644
--- a/core/java/android/gadget/GadgetManager.java
+++ b/core/java/android/gadget/GadgetManager.java
@@ -38,68 +38,142 @@ public class GadgetManager {
     static final String TAG = "GadgetManager";
 
     /**
-     * Send this when you want to pick a gadget to display.
+     * Send this from your gadget host activity when you want to pick a gadget to display.
+     * The gadget picker activity will be launched.
+     * <p>
+     * You must supply the following extras:
+     * <table>
+     *   <tr>
+     *     <td>{@link #EXTRA_GADGET_ID}</td>
+     *     <td>A newly allocated gadgetId, which will be bound to the gadget provider
+     *         once the user has selected one.</td>
+     *  </tr>
+     * </table>
      *
      * <p>
      * The system will respond with an onActivityResult call with the following extras in
      * the intent:
-     * <ul>
-     *   <li><b>gadgetIds</b></li>
-     *   <li><b>hostId</b></li>
-     * </ul>
-     * TODO: Add constants for these.
-     * TODO: Where does this go?
+     * <table>
+     *   <tr>
+     *     <td>{@link #EXTRA_GADGET_ID}</td>
+     *     <td>The gadgetId that you supplied in the original intent.</td>
+     *  </tr>
+     * </table>
+     * <p>
+     * When you receive the result from the gadget pick activity, if the resultCode is
+     * {@link android.app.Activity#RESULT_OK}, a gadget has been selected.  You should then
+     * check the GadgetProviderInfo for the returned gadget, and if it has one, launch its configuration
+     * activity.  If {@link android.app.Activity#RESULT_CANCELED} is returned, you should delete
+     * the gadgetId.
+     *
+     * @see #ACTION_GADGET_CONFIGURE
+     */
+    public static final String ACTION_GADGET_PICK = "android.gadget.action.GADGET_PICK";
+
+    /**
+     * Sent when it is time to configure your gadget while it is being added to a host.
+     * This action is not sent as a broadcast to the gadget provider, but as a startActivity
+     * to the activity specified in the {@link GadgetProviderInfo GadgetProviderInfo meta-data}.
+     *
+     * <p>
+     * The intent will contain the following extras:
+     * <table>
+     *   <tr>
+     *     <td>{@link #EXTRA_GADGET_ID}</td>
+     *     <td>The gadgetId to configure.</td>
+     *  </tr>
+     * </table>
+     *
+     * <p>If you return {@link android.app.Activity#RESULT_OK} using
+     * {@link android.app.Activity#setResult Activity.setResult()}, the gadget will be added,
+     * and you will receive an {@link #ACTION_GADGET_UPDATE} broadcast for this gadget.
+     * If you return {@link android.app.Activity#RESULT_CANCELED}, the host will cancel the add
+     * and not display this gadget, and you will receive a {@link #ACTION_GADGET_DELETED} broadcast.
      */
-    public static final String GADGET_PICK_ACTION = "android.gadget.action.PICK_GADGET";
+    public static final String ACTION_GADGET_CONFIGURE = "android.gadget.action.GADGET_CONFIGURE";
 
+    /**
+     * An intent extra that contains one gadgetId.
+     * <p>
+     * The value will be an int that can be retrieved like this:
+     * {@sample frameworks/base/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/GadgetHostActivity.java getExtra_EXTRA_GADGET_ID}
+     */
     public static final String EXTRA_GADGET_ID = "gadgetId";
+
+    /**
+     * An intent extra that contains multiple gadgetIds.
+     * <p>
+     * The value will be an int array that can be retrieved like this:
+     * {@sample frameworks/base/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/TestGadgetProvider.java getExtra_EXTRA_GADGET_IDS}
+     */
     public static final String EXTRA_GADGET_IDS = "gadgetIds";
-    public static final String EXTRA_HOST_ID = "hostId";
+
+    /**
+     * A sentiel value that the gadget manager will never return as a gadgetId.
+     */
+    public static final int INVALID_GADGET_ID = 0;
 
     /**
      * Sent when it is time to update your gadget.
      *
      * <p>This may be sent in response to a new instance for this gadget provider having
-     * been instantiated, the requested {@link GadgetInfo#updatePeriodMillis update interval}
+     * been instantiated, the requested {@link GadgetProviderInfo#updatePeriodMillis update interval}
      * having lapsed, or the system booting.
-     */
-    public static final String GADGET_UPDATE_ACTION = "android.gadget.action.GADGET_UPDATE";
-
-    /**
-     * Sent when it is time to configure your gadget.  This action is not sent as a broadcast
-     * to the gadget provider, but as a startActivity to the activity specified in the
-     * {@link GadgetInfo GadgetInfo meta-data}.
      *
-     * <p>The {@link #EXTRA_GADGET_ID} extra contains the gadget ID.
+     * <p>
+     * The intent will contain the following extras:
+     * <table>
+     *   <tr>
+     *     <td>{@link #EXTRA_GADGET_IDS}</td>
+     *     <td>The gadgetIds to update.  This may be all of the gadgets created for this
+     *     provider, or just a subset.  The system tries to send updates for as few gadget
+     *     instances as possible.</td>
+     *  </tr>
+     * </table>
+     * 
+     * @see GadgetProvider#onUpdate GadgetProvider.onUpdate(Context context, GadgetManager gadgetManager, int[] gadgetIds)
      */
-    public static final String GADGET_CONFIGURE_ACTION = "android.gadget.action.GADGET_CONFIGURE";
+    public static final String ACTION_GADGET_UPDATE = "android.gadget.action.GADGET_UPDATE";
 
     /**
-     * Sent when the gadget is added to a host for the first time.  This broadcast is sent at
-     * boot time if there is a gadget host installed with an instance for this provider.
+     * Sent when an instance of a gadget is deleted from its host.
+     *
+     * @see GadgetProvider#onDeleted GadgetProvider.onDeleted(Context context, int[] gadgetIds)
      */
-    public static final String GADGET_ENABLED_ACTION = "android.gadget.action.GADGET_ENABLED";
+    public static final String ACTION_GADGET_DELETED = "android.gadget.action.GADGET_DELETED";
 
     /**
-     * Sent when an instances of a gadget is deleted from the host.
+     * Sent when an instance of a gadget is removed from the last host.
+     * 
+     * @see GadgetProvider#onEnabled GadgetProvider.onEnabled(Context context)
      */
-    public static final String GADGET_DELETED_ACTION = "android.gadget.action.GADGET_DELETED";
+    public static final String ACTION_GADGET_DISABLED = "android.gadget.action.GADGET_DISABLED";
 
     /**
-     * Sent when the gadget is removed from the last host.
+     * Sent when an instance of a gadget is added to a host for the first time.
+     * This broadcast is sent at boot time if there is a gadget host installed with
+     * an instance for this provider.
+     * 
+     * @see GadgetProvider#onEnabled GadgetProvider.onEnabled(Context context)
      */
-    public static final String GADGET_DISABLED_ACTION = "android.gadget.action.GADGET_DISABLED";
+    public static final String ACTION_GADGET_ENABLED = "android.gadget.action.GADGET_ENABLED";
 
     /**
      * Field for the manifest meta-data tag.
+     *
+     * @see GadgetProviderInfo
      */
-    public static final String GADGET_PROVIDER_META_DATA = "android.gadget.provider";
+    public static final String META_DATA_GADGET_PROVIDER = "android.gadget.provider";
 
     static WeakHashMap<Context, WeakReference<GadgetManager>> sManagerCache = new WeakHashMap();
     static IGadgetService sService;
     
     Context mContext;
 
+    /**
+     * Get the GadgetManager instance to use for the supplied {@link android.content.Context
+     * Context} object.
+     */
     public static GadgetManager getInstance(Context context) {
         synchronized (sManagerCache) {
             if (sService == null) {
@@ -125,9 +199,11 @@ public class GadgetManager {
     }
 
     /**
-     * Call this with the new RemoteViews for your gadget whenever you need to.
+     * Set the RemoteViews to use for the specified gadgetIds.
      *
      * <p>
+     * It is okay to call this method both inside an {@link #ACTION_GADGET_UPDATE} broadcast,
+     * and outside of the handler.
      * This method will only work when called from the uid that owns the gadget provider.
      *
      * @param gadgetIds     The gadget instances for which to set the RemoteViews.
@@ -143,9 +219,26 @@ public class GadgetManager {
     }
 
     /**
-     * Call this with the new RemoteViews for your gadget whenever you need to.
+     * Set the RemoteViews to use for the specified gadgetId.
      *
      * <p>
+     * It is okay to call this method both inside an {@link #ACTION_GADGET_UPDATE} broadcast,
+     * and outside of the handler.
+     * This method will only work when called from the uid that owns the gadget provider.
+     *
+     * @param gadgetId      The gadget instance for which to set the RemoteViews.
+     * @param views         The RemoteViews object to show.
+     */
+    public void updateGadget(int gadgetId, RemoteViews views) {
+        updateGadget(new int[] { gadgetId }, views);
+    }
+
+    /**
+     * Set the RemoteViews to use for all gadget instances for the supplied gadget provider.
+     *
+     * <p>
+     * It is okay to call this method both inside an {@link #ACTION_GADGET_UPDATE} broadcast,
+     * and outside of the handler.
      * This method will only work when called from the uid that owns the gadget provider.
      *
      * @param provider      The {@link ComponentName} for the {@link
@@ -165,7 +258,7 @@ public class GadgetManager {
     /**
      * Return a list of the gadget providers that are currently installed.
      */
-    public List<GadgetInfo> getInstalledProviders() {
+    public List<GadgetProviderInfo> getInstalledProviders() {
         try {
             return sService.getInstalledProviders();
         }
@@ -175,12 +268,12 @@ public class GadgetManager {
     }
 
     /**
-     * Get the available info about the gadget.  If the gadgetId has not been bound yet,
-     * this method will return null.
+     * Get the available info about the gadget.
      *
-     * TODO: throws GadgetNotFoundException ??? if not valid
+     * @return A gadgetId.  If the gadgetId has not been bound to a provider yet, or
+     * you don't have access to that gadgetId, null is returned.
      */
-    public GadgetInfo getGadgetInfo(int gadgetId) {
+    public GadgetProviderInfo getGadgetInfo(int gadgetId) {
         try {
             return sService.getGadgetInfo(gadgetId);
         }
@@ -190,7 +283,14 @@ public class GadgetManager {
     }
 
     /**
-     * Set the component for a given gadgetId.  You need the GADGET_LIST permission.
+     * Set the component for a given gadgetId.
+     *
+     * <p class="note">You need the GADGET_LIST permission.  This method is to be used by the
+     * gadget picker.
+     *
+     * @param gadgetId     The gadget instance for which to set the RemoteViews.
+     * @param provider      The {@link android.content.BroadcastReceiver} that will be the gadget
+     *                      provider for this gadget.
      */
     public void bindGadgetId(int gadgetId, ComponentName provider) {
         try {
diff --git a/core/java/android/gadget/GadgetProvider.java b/core/java/android/gadget/GadgetProvider.java
index 1ddfe3f0babf..7e10e7817a2b 100755
--- a/core/java/android/gadget/GadgetProvider.java
+++ b/core/java/android/gadget/GadgetProvider.java
@@ -55,7 +55,7 @@ public class GadgetProvider extends BroadcastReceiver {
         // Protect against rogue update broadcasts (not really a security issue,
         // just filter bad broacasts out so subclasses are less likely to crash).
         String action = intent.getAction();
-        if (GadgetManager.GADGET_UPDATE_ACTION.equals(action)) {
+        if (GadgetManager.ACTION_GADGET_UPDATE.equals(action)) {
             Bundle extras = intent.getExtras();
             if (extras != null) {
                 int[] gadgetIds = extras.getIntArray(GadgetManager.EXTRA_GADGET_IDS);
@@ -64,7 +64,7 @@ public class GadgetProvider extends BroadcastReceiver {
                 }
             }
         }
-        else if (GadgetManager.GADGET_DELETED_ACTION.equals(action)) {
+        else if (GadgetManager.ACTION_GADGET_DELETED.equals(action)) {
             Bundle extras = intent.getExtras();
             if (extras != null) {
                 int[] gadgetIds = extras.getIntArray(GadgetManager.EXTRA_GADGET_IDS);
@@ -73,102 +73,81 @@ public class GadgetProvider extends BroadcastReceiver {
                 }
             }
         }
-        else if (GadgetManager.GADGET_ENABLED_ACTION.equals(action)) {
+        else if (GadgetManager.ACTION_GADGET_ENABLED.equals(action)) {
             this.onEnabled(context);
         }
-        else if (GadgetManager.GADGET_DISABLED_ACTION.equals(action)) {
+        else if (GadgetManager.ACTION_GADGET_DISABLED.equals(action)) {
             this.onDisabled(context);
         }
     }
     // END_INCLUDE(onReceive)
     
     /**
-     * Called in response to the {@link GadgetManager#GADGET_UPDATE_ACTION} broadcast when
+     * Called in response to the {@link GadgetManager#ACTION_GADGET_UPDATE} broadcast when
      * this gadget provider is being asked to provide {@link android.widget.RemoteViews RemoteViews}
      * for a set of gadgets.  Override this method to implement your own gadget functionality.
      *
      * {@more}
-     * <p class="note">If you want this method called, you must declare in an intent-filter in
-     * your AndroidManifest.xml file that you accept the GADGET_UPDATE_ACTION intent action.
-     * For example:
-     * <font color=red>TODO: SAMPLE CODE GOES HERE</font>
-     * </p>
      * 
      * @param context   The {@link android.content.Context Context} in which this receiver is
      *                  running.
      * @param gadgetManager A {@link GadgetManager} object you can call {@link
-     *                  GadgetManager#updateGadgets} on.
+     *                  GadgetManager#updateGadget} on.
      * @param gadgetIds The gadgetsIds for which an update is needed.  Note that this
      *                  may be all of the gadget instances for this provider, or just
      *                  a subset of them.
      *
-     * @see GadgetManager#GADGET_UPDATE_ACTION
+     * @see GadgetManager#ACTION_GADGET_UPDATE
      */
     public void onUpdate(Context context, GadgetManager gadgetManager, int[] gadgetIds) {
     }
     
     /**
-     * Called in response to the {@link GadgetManager#GADGET_DELETED_ACTION} broadcast when
+     * Called in response to the {@link GadgetManager#ACTION_GADGET_DELETED} broadcast when
      * one or more gadget instances have been deleted.  Override this method to implement
      * your own gadget functionality.
      *
      * {@more}
-     * <p class="note">If you want this method called, you must declare in an intent-filter in
-     * your AndroidManifest.xml file that you accept the GADGET_DELETED_ACTION intent action.
-     * For example:
-     * <font color=red>TODO: SAMPLE CODE GOES HERE</font>
-     * </p>
      * 
      * @param context   The {@link android.content.Context Context} in which this receiver is
      *                  running.
      * @param gadgetIds The gadgetsIds that have been deleted from their host.
      *
-     * @see GadgetManager#GADGET_DELETED_ACTION
+     * @see GadgetManager#ACTION_GADGET_DELETED
      */
     public void onDeleted(Context context, int[] gadgetIds) {
     }
 
     /**
-     * Called in response to the {@link GadgetManager#GADGET_ENABLED_ACTION} broadcast when
+     * Called in response to the {@link GadgetManager#ACTION_GADGET_ENABLED} broadcast when
      * the a gadget for this provider is instantiated.  Override this method to implement your
      * own gadget functionality.
      *
      * {@more}
      * When the last gadget for this provider is deleted,
-     * {@link GadgetManager#GADGET_DISABLED_ACTION} is sent and {@link #onDisabled}
-     * is called.  If after that, a gadget for this provider is created again, onEnabled() will
-     * be called again.
+     * {@link GadgetManager#ACTION_GADGET_DISABLED} is sent by the gadget manager, and
+     * {@link #onDisabled} is called.  If after that, a gadget for this provider is created
+     * again, onEnabled() will be called again.
      *
-     * <p class="note">If you want this method called, you must declare in an intent-filter in
-     * your AndroidManifest.xml file that you accept the GADGET_ENABLED_ACTION intent action.
-     * For example:
-     * <font color=red>TODO: SAMPLE CODE GOES HERE</font>
-     * </p>
-     * 
      * @param context   The {@link android.content.Context Context} in which this receiver is
      *                  running.
      *
-     * @see GadgetManager#GADGET_ENABLED_ACTION
+     * @see GadgetManager#ACTION_GADGET_ENABLED
      */
     public void onEnabled(Context context) {
     }
 
     /**
-     * Called in response to the {@link GadgetManager#GADGET_DISABLED_ACTION} broadcast, which
+     * Called in response to the {@link GadgetManager#ACTION_GADGET_DISABLED} broadcast, which
      * is sent when the last gadget instance for this provider is deleted.  Override this method
      * to implement your own gadget functionality.
      *
      * {@more}
-     * <p class="note">If you want this method called, you must declare in an intent-filter in
-     * your AndroidManifest.xml file that you accept the GADGET_DISABLED_ACTION intent action.
-     * For example:
-     * <font color=red>TODO: SAMPLE CODE GOES HERE</font>
-     * </p>
      * 
      * @param context   The {@link android.content.Context Context} in which this receiver is
      *                  running.
      *
-     * @see GadgetManager#GADGET_DISABLED_ACTION
+     * @see GadgetManager#ACTION_GADGET_DISABLED
      */
     public void onDisabled(Context context) {
     }
diff --git a/core/java/android/gadget/GadgetInfo.aidl b/core/java/android/gadget/GadgetProviderInfo.aidl
similarity index 95%
rename from core/java/android/gadget/GadgetInfo.aidl
rename to core/java/android/gadget/GadgetProviderInfo.aidl
index 72315454b6dd..589f886776f4 100644
--- a/core/java/android/gadget/GadgetInfo.aidl
+++ b/core/java/android/gadget/GadgetProviderInfo.aidl
@@ -16,4 +16,4 @@
 
 package android.gadget;
 
-parcelable GadgetInfo;
+parcelable GadgetProviderInfo;
diff --git a/core/java/android/gadget/GadgetInfo.java b/core/java/android/gadget/GadgetProviderInfo.java
similarity index 56%
rename from core/java/android/gadget/GadgetInfo.java
rename to core/java/android/gadget/GadgetProviderInfo.java
index 5ac3da9cf2d1..95c043230ec3 100644
--- a/core/java/android/gadget/GadgetInfo.java
+++ b/core/java/android/gadget/GadgetProviderInfo.java
@@ -21,60 +21,88 @@ import android.os.Parcelable;
 import android.content.ComponentName;
 
 /**
- * Describes the meta data for an installed gadget.
+ * Describes the meta data for an installed gadget provider.  The fields in this class
+ * correspond to the fields in the <code>&lt;gadget-provider&gt;</code> xml tag.
  */
-public class GadgetInfo implements Parcelable {
+public class GadgetProviderInfo implements Parcelable {
     /**
      * Identity of this gadget component.  This component should be a {@link
      * android.content.BroadcastReceiver}, and it will be sent the Gadget intents
      * {@link android.gadget as described in the gadget package documentation}.
+     *
+     * <p>This field corresponds to the <code>android:name</code> attribute in
+     * the <code>&lt;receiver&gt;</code> element in the AndroidManifest.xml file.
      */
     public ComponentName provider;
 
     /**
      * Minimum width of the gadget, in dp.
+     *
+     * <p>This field corresponds to the <code>android:minWidth</code> attribute in
+     * the gadget meta-data file.
      */
     public int minWidth;
 
     /**
      * Minimum height of the gadget, in dp.
+     *
+     * <p>This field corresponds to the <code>android:minHeight</code> attribute in
+     * the gadget meta-data file.
      */
     public int minHeight;
 
     /**
      * How often, in milliseconds, that this gadget wants to be updated.
      * The gadget manager may place a limit on how often a gadget is updated.
+     *
+     * <p>This field corresponds to the <code>android:updatePeriodMillis</code> attribute in
+     * the gadget meta-data file.
      */
     public int updatePeriodMillis;
 
     /**
      * The resource id of the initial layout for this gadget.  This should be
      * displayed until the RemoteViews for the gadget is available.
+     *
+     * <p>This field corresponds to the <code>android:initialLayout</code> attribute in
+     * the gadget meta-data file.
      */
     public int initialLayout;
 
     /**
      * The activity to launch that will configure the gadget.
+     *
+     * <p>This class name of field corresponds to the <code>android:configure</code> attribute in
+     * the gadget meta-data file.  The package name always corresponds to the package containing
+     * the gadget provider.
      */
     public ComponentName configure;
 
     /**
-     * The label to display to the user.
+     * The label to display to the user in the gadget picker.  If not supplied in the
+     * xml, the application label will be used.
+     *
+     * <p>This field corresponds to the <code>android:label</code> attribute in
+     * the <code>&lt;receiver&gt;</code> element in the AndroidManifest.xml file.
      */
     public String label;
 
     /**
-     * The icon to display for this gadget in the picker list.
+     * The icon to display for this gadget in the gadget picker.  If not supplied in the
+     * xml, the application icon will be used.
+     *
+     * <p>This field corresponds to the <code>android:icon</code> attribute in
+     * the <code>&lt;receiver&gt;</code> element in the AndroidManifest.xml file.
      */
     public int icon;
 
-    public GadgetInfo() {
+    public GadgetProviderInfo() {
     }
 
     /**
-     * Unflatten the GadgetInfo from a parcel.
+     * Unflatten the GadgetProviderInfo from a parcel.
      */
-    public GadgetInfo(Parcel in) {
+    public GadgetProviderInfo(Parcel in) {
         if (0 != in.readInt()) {
             this.provider = new ComponentName(in);
         }
@@ -116,24 +144,24 @@ public class GadgetInfo implements Parcelable {
     }
 
     /**
-     * Parcelable.Creator that instantiates GadgetInfo objects
+     * Parcelable.Creator that instantiates GadgetProviderInfo objects
      */
-    public static final Parcelable.Creator<GadgetInfo> CREATOR
-            = new Parcelable.Creator<GadgetInfo>()
+    public static final Parcelable.Creator<GadgetProviderInfo> CREATOR
+            = new Parcelable.Creator<GadgetProviderInfo>()
     {
-        public GadgetInfo createFromParcel(Parcel parcel)
+        public GadgetProviderInfo createFromParcel(Parcel parcel)
         {
-            return new GadgetInfo(parcel);
+            return new GadgetProviderInfo(parcel);
         }
 
-        public GadgetInfo[] newArray(int size)
+        public GadgetProviderInfo[] newArray(int size)
         {
-            return new GadgetInfo[size];
+            return new GadgetProviderInfo[size];
         }
     };
 
     public String toString() {
-        return "GadgetInfo(provider=" + this.provider + ")";
+        return "GadgetProviderInfo(provider=" + this.provider + ")";
     }
 }
 
diff --git a/core/java/android/gadget/package.html b/core/java/android/gadget/package.html
index 4b8b9d9c3d6b..4c04396e8b7e 100644
--- a/core/java/android/gadget/package.html
+++ b/core/java/android/gadget/package.html
@@ -1,41 +1,126 @@
 <body>
-{@hide}
 <p>Android allows applications to publish views to be embedded in other applications.  These
 views are called gadgets, and are published by "gadget providers."  The component that can
-contain gadgets is called a "gadget host."  See the links below for more information.
+contain gadgets is called a "gadget host."
 </p>
-<h3><a href="{@toroot}reference/android/gadget/package-descr.html#providers">Gadget Providers</a></h3>
+<h3><a href="package-descr.html#providers">Gadget Providers</a></h3>
 <ul>
-  <li><a href="{@toroot}reference/android/gadget/package-descr.html#provider_manifest">Declaring a gadget in the AndroidManifest</a></li>
-  <li><a href="{@toroot}reference/android/gadget/package-descr.html#provider_meta_data">Adding the {@link android.gadget.GadgetInfo GadgetInfo} meta-data</a></li>
-  <li><a href="{@toroot}reference/android/gadget/package-descr.html#provider_GadgetProvider">Using the {@link android.gadget.GadgetProvider GadgetProvider} class</a></li>
-  <li><a href="{@toroot}reference/android/gadget/package-descr.html#provider_configuration">Gadget Configuration UI</a></li>
-  <li><a href="{@toroot}reference/android/gadget/package-descr.html#provider_broadcasts">Gadget Broadcast Intents</a></li>
-</ul>
-<h3><a href="{@toroot}reference/android/gadget/package-descr.html#">Gadget Hosts</a></h3>
-<ul>
-  <li><a href="{@toroot}reference/android/gadget/package-descr.html#">asdf</a></li>
+  <li><a href="package-descr.html#provider_manifest">Declaring a gadget in the AndroidManifest</a></li>
+  <li><a href="package-descr.html#provider_meta_data">Adding the GadgetProviderInfo meta-data</a></li>
+  <li><a href="package-descr.html#provider_GadgetProvider">Using the GadgetProvider class</a></li>
+  <li><a href="package-descr.html#provider_configuration">Gadget Configuration UI</a></li>
+  <li><a href="package-descr.html#provider_broadcasts">Gadget Broadcast Intents</a></li>
 </ul>
+<h3><a href="package-descr.html#">Gadget Hosts</a></h3>
+
+
 {@more}
+
+
 <h2><a name="providers"></a>Gadget Providers</h2>
-<p>Any application can publish gadgets.  All an application needs to do to publish a gadget is
+<p>
+Any application can publish gadgets.  All an application needs to do to publish a gadget is
 to have a {@link android.content.BroadcastReceiver} that receives the {@link
-android.gadget.GadgetManager#GADGET_UPDATE_ACTION GadgetManager.GADGET_UPDATE_ACTION} intent,
-and provide some meta-data about the gadget.
+android.gadget.GadgetManager#ACTION_GADGET_UPDATE GadgetManager.ACTION_GADGET_UPDATE} intent,
+and provide some meta-data about the gadget.  Android provides the
+{@link android.gadget.GadgetProvider} class, which extends BroadcastReceiver, as a convenience
+class to aid in handling the broadcasts.
 
 <h3><a name="provider_manifest"></a>Declaring a gadget in the AndroidManifest</h3>
 
-<h3><a name="provider_meta_data"></a>Adding the {@link android.gadget.GadgetInfo GadgetInfo} meta-data</h3>
+<p>
+First, declare the {@link android.content.BroadcastReceiver} in your application's
+<code>AndroidManifest.xml</code> file.
+
+{@sample frameworks/base/tests/gadgets/GadgetHostTest/AndroidManifest.xml GadgetProvider}
+
+<p>
+The <b><code>&lt;receiver&gt;</b> element has the following attributes:
+<ul>
+  <li><b><code>android:name</code> -</b> which specifies the
+        {@link android.content.BroadcastReceiver} or {@link android.gadget.GadgetProvider}
+        class.</li>
+  <li><b><code>android:label</code> -</b> which specifies the string resource that
+        will be shown by the gadget picker as the label.</li>
+  <li><b><code>android:icon</code> -</b> which specifies the drawable resource that
+        will be shown by the gadget picker as the icon.</li>
+</ul>
+
+<p>
+The <b><code>&lt;intent-filter&gt;</b> element tells the {@link android.content.pm.PackageManager}
+that this {@link android.content.BroadcastReceiver} receives the {@link
+android.gadget.GadgetManager#ACTION_GADGET_UPDATE GadgetManager.ACTION_GADGET_UPDATE} broadcast.
+The gadget manager will send other broadcasts directly to your gadget provider as required.
+It is only necessary to explicitly declare that you accept the {@link
+android.gadget.GadgetManager#ACTION_GADGET_UPDATE GadgetManager.ACTION_GADGET_UPDATE} broadcast.
+
+<p>
+The <b><code>&lt;meta-data&gt;</code></b> element tells the gadget manager which xml resource to
+read to find the {@link android.gadget.GadgetProviderInfo} for your gadget provider.  It has the following
+attributes:
+<ul>
+  <li><b><code>android:name="android.gadget.provider"</code> -</b> identifies this meta-data
+        as the {@link android.gadget.GadgetProviderInfo} descriptor.</li>
+  <li><b><code>android:resource</code> -</b> is the xml resource to use as that descriptor.</li>
+</ul>
+
+
+<h3><a name="provider_meta_data"></a>Adding the {@link android.gadget.GadgetProviderInfo GadgetProviderInfo} meta-data</h3>
+
+<p>
+For a gadget, the values in the {@link android.gadget.GadgetProviderInfo} structure are supplied
+in an XML resource.  In the example above, the xml resource is referenced with
+<code>android:resource="@xml/gadget_info"</code>.  That XML file would go in your application's
+directory at <code>res/xml/gadget_info.xml</code>.  Here is a simple example.
+
+{@sample frameworks/base/tests/gadgets/GadgetHostTest/res/xml/gadget_info.xml GadgetProviderInfo}
+
+<p>
+The attributes are as documented in the {@link android.gadget.GadgetProviderInfo GagetInfo} class.  (86400000 milliseconds means once per day)
+
 
 <h3><a name="provider_GadgetProvider"></a>Using the {@link android.gadget.GadgetProvider GadgetProvider} class</h3>
 
+<p>The GadgetProvider class is the easiest way to handle the gadget provider intent broadcasts.
+See the <code>src/com/example/android/apis/gadget/ExampleGadgetProvider.java</code>
+sample class in ApiDemos for an example.
+
+<p class="note">Keep in mind that since the the GadgetProvider is a BroadcastReceiver,
+your process is not guaranteed to keep running after the callback methods return.  See
+<a href="../../../guide/topics/fundamentals.html#broadlife">Application Fundamentals &gt;
+Broadcast Receiver Lifecycle</a> for more information.
+
+
+
 <h3><a name="provider_configuration"></a>Gadget Configuration UI</h3>
 
+<p>
+Gadget hosts have the ability to start a configuration activity when a gadget is instantiated.
+The activity should be declared as normal in AndroidManifest.xml, and it should be listed in
+the GadgetProviderInfo XML file in the <code>android:configure</code> attribute.
+
+<p>The activity you specified will be launched with the {@link
+android.gadget.GadgetManager#ACTION_GADGET_CONFIGURE} action.  See the documentation for that
+action for more info.
+
+<p>See the <code>src/com/example/android/apis/gadget/ExampleGadgetConfigure.java</code>
+sample class in ApiDemos for an example.
+
+
+
 <h3><a name="providers_broadcasts"></a>Gadget Broadcast Intents</h3>
 
-<p>{@link GadgetProvider} is just a convenience class.  If you would like to receive the
-gadget broadcasts directly, you can.  By way of example, the implementation of
-{@link GadgetProvider.onReceive} is quite simple:</p>
+<p>{@link android.gadget.GadgetProvider} is just a convenience class.  If you would like
+to receive the gadget broadcasts directly, you can.  The four intents you need to care about are:
+<ul>
+  <li>{@link android.gadget.GadgetManager#ACTION_GADGET_UPDATE}</li>
+  <li>{@link android.gadget.GadgetManager#ACTION_GADGET_DELETED}</li>
+  <li>{@link android.gadget.GadgetManager#ACTION_GADGET_ENABLED}</li>
+  <li>{@link android.gadget.GadgetManager#ACTION_GADGET_DISABLED}</li>
+</ul>
+
+<p>By way of example, the implementation of
+{@link android.gadget.GadgetProvider#onReceive} is quite simple:</p>
 
 {@sample frameworks/base/core/java/android/gadget/GadgetProvider.java onReceive}
 
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index c09567c7f0a6..40a5b478e5f0 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -18,6 +18,7 @@ package android.hardware;
 
 import java.lang.ref.WeakReference;
 import java.util.HashMap;
+import java.util.StringTokenizer;
 import java.io.IOException;
 
 import android.util.Log;
@@ -494,11 +495,17 @@ public class Camera {
          */
         public void unflatten(String flattened) {
             mMap.clear();
-            String[] pairs = flattened.split(";");
-            for (String p : pairs) {
-                String[] kv = p.split("=");
-                if (kv.length == 2)
-                    mMap.put(kv[0], kv[1]);
+            
+            StringTokenizer tokenizer = new StringTokenizer(flattened, ";");
+            while (tokenizer.hasMoreElements()) {
+                String kv = tokenizer.nextToken();
+                int pos = kv.indexOf('=');
+                if (pos == -1) {
+                    continue;
+                }
+                String k = kv.substring(0, pos);
+                String v = kv.substring(pos + 1);
+                mMap.put(k, v);
             }
         }
         
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index ea5f7414d63d..c8841201f11b 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -206,6 +206,8 @@ public class InputMethodService extends AbstractInputMethodService {
     static final String TAG = "InputMethodService";
     static final boolean DEBUG = false;
     
+    InputMethodManager mImm;
+    
     LayoutInflater mInflater;
     View mRootView;
     SoftInputWindow mWindow;
@@ -293,6 +295,8 @@ public class InputMethodService extends AbstractInputMethodService {
             mInputConnection = binding.getConnection();
             if (DEBUG) Log.v(TAG, "bindInput(): binding=" + binding
                     + " ic=" + mInputConnection);
+            InputConnection ic = getCurrentInputConnection();
+            if (ic != null) ic.reportFullscreenMode(mIsFullscreen);
             initialize();
             onBindInput();
         }
@@ -423,7 +427,7 @@ public class InputMethodService extends AbstractInputMethodService {
          * of the application behind.  This value is relative to the top edge
          * of the input method window.
          */
-        int contentTopInsets;
+        public int contentTopInsets;
         
         /**
          * This is the top part of the UI that is visibly covering the
@@ -436,7 +440,7 @@ public class InputMethodService extends AbstractInputMethodService {
          * needed to make the focus visible.  This value is relative to the top edge
          * of the input method window.
          */
-        int visibleTopInsets;
+        public int visibleTopInsets;
         
         /**
          * Option for {@link #touchableInsets}: the entire window frame
@@ -469,6 +473,7 @@ public class InputMethodService extends AbstractInputMethodService {
     
     @Override public void onCreate() {
         super.onCreate();
+        mImm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
         mInflater = (LayoutInflater)getSystemService(
                 Context.LAYOUT_INFLATER_SERVICE);
         mWindow = new SoftInputWindow(this);
@@ -554,7 +559,6 @@ public class InputMethodService extends AbstractInputMethodService {
         boolean visible = mWindowVisible;
         boolean showingInput = mShowInputRequested;
         boolean showingForced = mShowInputForced;
-        boolean showingCandidates = mCandidatesVisibility == View.VISIBLE;
         initViews();
         mInputViewStarted = false;
         mCandidatesViewStarted = false;
@@ -577,9 +581,6 @@ public class InputMethodService extends AbstractInputMethodService {
                 // Otherwise just put it back for its candidates.
                 showWindow(false);
             }
-            if (showingCandidates) {
-                setCandidatesViewShown(true);
-            }
         }
     }
 
@@ -670,6 +671,8 @@ public class InputMethodService extends AbstractInputMethodService {
         if (mIsFullscreen != isFullscreen || !mFullscreenApplied) {
             changed = true;
             mIsFullscreen = isFullscreen;
+            InputConnection ic = getCurrentInputConnection();
+            if (ic != null) ic.reportFullscreenMode(isFullscreen);
             mFullscreenApplied = true;
             initialize();
             Drawable bg = onCreateBackgroundDrawable();
@@ -860,12 +863,14 @@ public class InputMethodService extends AbstractInputMethodService {
         return isFullscreenMode() ? View.GONE : View.INVISIBLE;
     }
     
-    public void setStatusIcon(int iconResId) {
+    public void showStatusIcon(int iconResId) {
         mStatusIcon = iconResId;
-        InputConnection ic = getCurrentInputConnection();
-        if (ic != null && mWindowVisible) {
-            ic.showStatusIcon(getPackageName(), iconResId);
-        }
+        mImm.showStatusIcon(mToken, getPackageName(), iconResId);
+    }
+    
+    public void hideStatusIcon() {
+        mStatusIcon = 0;
+        mImm.hideStatusIcon(mToken);
     }
     
     /**
@@ -876,8 +881,7 @@ public class InputMethodService extends AbstractInputMethodService {
      * @param id Unique identifier of the new input method ot start.
      */
     public void switchInputMethod(String id) {
-        ((InputMethodManager)getSystemService(INPUT_METHOD_SERVICE))
-                .setInputMethod(mToken, id);
+        mImm.setInputMethod(mToken, id);
     }
     
     public void setExtractView(View view) {
@@ -1149,15 +1153,9 @@ public class InputMethodService extends AbstractInputMethodService {
         
         if (!wasVisible) {
             if (DEBUG) Log.v(TAG, "showWindow: showing!");
+            onWindowShown();
             mWindow.show();
         }
-        
-        if (!wasVisible || !wasCreated) {
-            InputConnection ic = getCurrentInputConnection();
-            if (ic != null) {
-                ic.showStatusIcon(getPackageName(), mStatusIcon);
-            }
-        }
     }
     
     public void hideWindow() {
@@ -1173,13 +1171,25 @@ public class InputMethodService extends AbstractInputMethodService {
         if (mWindowVisible) {
             mWindow.hide();
             mWindowVisible = false;
-            InputConnection ic = getCurrentInputConnection();
-            if (ic != null) {
-                ic.hideStatusIcon();
-            }
+            onWindowHidden();
         }
     }
     
+    /**
+     * Called when the input method window has been shown to the user, after
+     * previously not being visible.  This is done after all of the UI setup
+     * for the window has occurred (creating its views etc).
+     */
+    public void onWindowShown() {
+    }
+    
+    /**
+     * Called when the input method window has been hidden from the user,
+     * after previously being visible.
+     */
+    public void onWindowHidden() {
+    }
+    
     /**
      * Called when a new client has bound to the input method.  This
      * may be followed by a series of {@link #onStartInput(EditorInfo, boolean)}
@@ -1341,8 +1351,7 @@ public class InputMethodService extends AbstractInputMethodService {
      * InputMethodManager.HIDE_IMPLICIT_ONLY} bit set.
      */
     public void dismissSoftInput(int flags) {
-        ((InputMethodManager)getSystemService(INPUT_METHOD_SERVICE))
-                .hideSoftInputFromInputMethod(mToken, flags);
+        mImm.hideSoftInputFromInputMethod(mToken, flags);
     }
     
     /**
@@ -1447,17 +1456,19 @@ public class InputMethodService extends AbstractInputMethodService {
                         return true;
                     }
                 } else {
-                    KeyEvent down = new KeyEvent(event, KeyEvent.ACTION_DOWN);
-                    if (movement.onKeyDown(eet,
-                            (Spannable)eet.getText(), keyCode, down)) {
-                        KeyEvent up = new KeyEvent(event, KeyEvent.ACTION_UP);
-                        movement.onKeyUp(eet,
-                                (Spannable)eet.getText(), keyCode, up);
-                        while (--count > 0) {
-                            movement.onKeyDown(eet,
-                                    (Spannable)eet.getText(), keyCode, down);
+                    if (!movement.onKeyOther(eet, (Spannable)eet.getText(), event)) {
+                        KeyEvent down = new KeyEvent(event, KeyEvent.ACTION_DOWN);
+                        if (movement.onKeyDown(eet,
+                                (Spannable)eet.getText(), keyCode, down)) {
+                            KeyEvent up = new KeyEvent(event, KeyEvent.ACTION_UP);
                             movement.onKeyUp(eet,
                                     (Spannable)eet.getText(), keyCode, up);
+                            while (--count > 0) {
+                                movement.onKeyDown(eet,
+                                        (Spannable)eet.getText(), keyCode, down);
+                                movement.onKeyUp(eet,
+                                        (Spannable)eet.getText(), keyCode, up);
+                            }
                         }
                     }
                 }
@@ -1593,5 +1604,9 @@ public class InputMethodService extends AbstractInputMethodService {
         p.println("  mExtractedToken=" + mExtractedToken);
         p.println("  mIsInputViewShown=" + mIsInputViewShown
                 + " mStatusIcon=" + mStatusIcon);
+        p.println("Last computed insets:");
+        p.println("  contentTopInsets=" + mTmpInsets.contentTopInsets
+                + " visibleTopInsets=" + mTmpInsets.visibleTopInsets
+                + " touchableInsets=" + mTmpInsets.touchableInsets);
     }
 }
diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
index b2c74f24bf00..b8bd10dc44de 100755
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ b/core/java/android/inputmethodservice/KeyboardView.java
@@ -1084,6 +1084,10 @@ public class KeyboardView extends View implements View.OnClickListener {
         if (mPreviewPopup.isShowing()) {
             mPreviewPopup.dismiss();
         }
+        mHandler.removeMessages(MSG_REPEAT);
+        mHandler.removeMessages(MSG_LONGPRESS);
+        mHandler.removeMessages(MSG_SHOW_PREVIEW);
+        
         dismissPopupKeyboard();
     }
     
diff --git a/core/java/android/net/UrlQuerySanitizer.java b/core/java/android/net/UrlQuerySanitizer.java
index 70e50b7c2635..a6efcdd3da51 100644
--- a/core/java/android/net/UrlQuerySanitizer.java
+++ b/core/java/android/net/UrlQuerySanitizer.java
@@ -23,7 +23,7 @@ import java.util.Set;
 import java.util.StringTokenizer;
 
 /**
- * 
+ *
  * Sanitizes the Query portion of a URL. Simple example:
  * <code>
  * UrlQuerySanitizer sanitizer = new UrlQuerySanitizer();
@@ -32,7 +32,7 @@ import java.util.StringTokenizer;
  * String name = sanitizer.getValue("name"));
  * // name now contains "Joe_User"
  * </code>
- * 
+ *
  * Register ValueSanitizers to customize the way individual
  * parameters are sanitized:
  * <code>
@@ -46,7 +46,7 @@ import java.util.StringTokenizer;
  * unregistered parameter sanitizer does not allow any special characters,
  * and ' ' is a special character.)
  * </code>
- * 
+ *
  * There are several ways to create ValueSanitizers. In order of increasing
  * sophistication:
  * <ol>
@@ -56,7 +56,7 @@ import java.util.StringTokenizer;
  * <li>Subclass UrlQuerySanitizer.ValueSanitizer to define your own value
  * sanitizer.
  * </ol>
- * 
+ *
  */
 public class UrlQuerySanitizer {
 
@@ -84,7 +84,7 @@ public class UrlQuerySanitizer {
          */
         public String mValue;
     }
-    
+
     final private HashMap<String, ValueSanitizer> mSanitizers =
         new HashMap<String, ValueSanitizer>();
     final private HashMap<String, String> mEntries =
@@ -95,9 +95,9 @@ public class UrlQuerySanitizer {
     private boolean mPreferFirstRepeatedParameter;
     private ValueSanitizer mUnregisteredParameterValueSanitizer =
         getAllIllegal();
-   
+
     /**
-     * A functor used to sanitize a single query value. 
+     * A functor used to sanitize a single query value.
      *
      */
     public static interface ValueSanitizer {
@@ -108,7 +108,7 @@ public class UrlQuerySanitizer {
          */
         public String sanitize(String value);
     }
-    
+
     /**
      * Sanitize values based on which characters they contain. Illegal
      * characters are replaced with either space or '_', depending upon
@@ -117,7 +117,7 @@ public class UrlQuerySanitizer {
     public static class IllegalCharacterValueSanitizer implements
         ValueSanitizer {
         private int mFlags;
-        
+
         /**
          * Allow space (' ') characters.
          */
@@ -165,21 +165,21 @@ public class UrlQuerySanitizer {
          * such as "javascript:" or "vbscript:"
          */
         public final static int SCRIPT_URL_OK =         1 << 10;
-        
+
         /**
          * Mask with all fields set to OK
          */
         public final static int ALL_OK =                0x7ff;
-        
+
         /**
          * Mask with both regular space and other whitespace OK
          */
         public final static int ALL_WHITESPACE_OK =
             SPACE_OK | OTHER_WHITESPACE_OK;
 
-        
+
         // Common flag combinations:
-        
+
         /**
          * <ul>
          * <li>Deny all special characters.
@@ -262,18 +262,18 @@ public class UrlQuerySanitizer {
          */
         public final static int ALL_BUT_NUL_AND_ANGLE_BRACKETS_LEGAL =
             ALL_OK & ~(NUL_OK | LT_OK | GT_OK);
-        
+
         /**
          *  Script URL definitions
          */
-        
+
         private final static String JAVASCRIPT_PREFIX = "javascript:";
-        
+
         private final static String VBSCRIPT_PREFIX = "vbscript:";
-        
+
         private final static int MIN_SCRIPT_PREFIX_LENGTH = Math.min(
                 JAVASCRIPT_PREFIX.length(), VBSCRIPT_PREFIX.length());
-        
+
         /**
          * Construct a sanitizer. The parameters set the behavior of the
          * sanitizer.
@@ -312,7 +312,7 @@ public class UrlQuerySanitizer {
                     }
                 }
             }
-            
+
             // If whitespace isn't OK, get rid of whitespace at beginning
             // and end of value.
             if ( (mFlags & ALL_WHITESPACE_OK) == 0) {
@@ -337,7 +337,7 @@ public class UrlQuerySanitizer {
             }
             return stringBuilder.toString();
         }
-        
+
         /**
          * Trim whitespace from the beginning and end of a string.
          * <p>
@@ -361,7 +361,7 @@ public class UrlQuerySanitizer {
             }
             return value.substring(start, end + 1);
         }
-        
+
         /**
          * Check if c is whitespace.
          * @param c character to test
@@ -380,7 +380,7 @@ public class UrlQuerySanitizer {
                 return false;
             }
         }
-        
+
         /**
          * Check whether an individual character is legal. Uses the
          * flag bit-set passed into the constructor.
@@ -400,11 +400,11 @@ public class UrlQuerySanitizer {
             case '%' : return (mFlags & PCT_OK) != 0;
             case '\0': return (mFlags & NUL_OK) != 0;
             default  : return (c >= 32 && c < 127) ||
-                (c >= 128 && c <= 255 && ((mFlags & NON_7_BIT_ASCII_OK) != 0));
-            }    
+                ((c >= 128) && ((mFlags & NON_7_BIT_ASCII_OK) != 0));
+            }
         }
     }
-    
+
     /**
      * Get the current value sanitizer used when processing
      * unregistered parameter values.
@@ -412,14 +412,14 @@ public class UrlQuerySanitizer {
      * <b>Note:</b> The default unregistered parameter value sanitizer is
      * one that doesn't allow any special characters, similar to what
      * is returned by calling createAllIllegal.
-     * 
+     *
      * @return the current ValueSanitizer used to sanitize unregistered
      * parameter values.
      */
     public ValueSanitizer getUnregisteredParameterValueSanitizer() {
         return mUnregisteredParameterValueSanitizer;
     }
-    
+
     /**
      * Set the value sanitizer used when processing unregistered
      * parameter values.
@@ -430,46 +430,46 @@ public class UrlQuerySanitizer {
             ValueSanitizer sanitizer) {
         mUnregisteredParameterValueSanitizer = sanitizer;
     }
-    
-    
+
+
     // Private fields for singleton sanitizers:
-    
+
     private static final ValueSanitizer sAllIllegal =
         new IllegalCharacterValueSanitizer(
                 IllegalCharacterValueSanitizer.ALL_ILLEGAL);
-    
+
     private static final ValueSanitizer sAllButNulLegal =
         new IllegalCharacterValueSanitizer(
                 IllegalCharacterValueSanitizer.ALL_BUT_NUL_LEGAL);
-    
+
     private static final ValueSanitizer sAllButWhitespaceLegal =
         new IllegalCharacterValueSanitizer(
                 IllegalCharacterValueSanitizer.ALL_BUT_WHITESPACE_LEGAL);
-    
+
     private static final ValueSanitizer sURLLegal =
         new IllegalCharacterValueSanitizer(
                 IllegalCharacterValueSanitizer.URL_LEGAL);
-    
+
     private static final ValueSanitizer sUrlAndSpaceLegal =
         new IllegalCharacterValueSanitizer(
                 IllegalCharacterValueSanitizer.URL_AND_SPACE_LEGAL);
-    
+
     private static final ValueSanitizer sAmpLegal =
         new IllegalCharacterValueSanitizer(
-                IllegalCharacterValueSanitizer.AMP_LEGAL);   
-    
+                IllegalCharacterValueSanitizer.AMP_LEGAL);
+
     private static final ValueSanitizer sAmpAndSpaceLegal =
         new IllegalCharacterValueSanitizer(
                 IllegalCharacterValueSanitizer.AMP_AND_SPACE_LEGAL);
-    
+
     private static final ValueSanitizer sSpaceLegal =
         new IllegalCharacterValueSanitizer(
                 IllegalCharacterValueSanitizer.SPACE_LEGAL);
-    
+
     private static final ValueSanitizer sAllButNulAndAngleBracketsLegal =
         new IllegalCharacterValueSanitizer(
                 IllegalCharacterValueSanitizer.ALL_BUT_NUL_AND_ANGLE_BRACKETS_LEGAL);
-    
+
     /**
      * Return a value sanitizer that does not allow any special characters,
      * and also does not allow script URLs.
@@ -478,7 +478,7 @@ public class UrlQuerySanitizer {
     public static final ValueSanitizer getAllIllegal() {
         return sAllIllegal;
     }
-    
+
     /**
      * Return a value sanitizer that allows everything except Nul ('\0')
      * characters. Script URLs are allowed.
@@ -547,7 +547,7 @@ public class UrlQuerySanitizer {
     public static final ValueSanitizer getAllButNulAndAngleBracketsLegal() {
         return sAllButNulAndAngleBracketsLegal;
     }
-    
+
     /**
      * Constructs a UrlQuerySanitizer.
      * <p>
@@ -560,7 +560,7 @@ public class UrlQuerySanitizer {
      */
     public UrlQuerySanitizer() {
     }
-    
+
     /**
      * Constructs a UrlQuerySanitizer and parse a URL.
      * This constructor is provided for convenience when the
@@ -585,7 +585,7 @@ public class UrlQuerySanitizer {
         setAllowUnregisteredParamaters(true);
         parseUrl(url);
     }
-    
+
     /**
      * Parse the query parameters out of an encoded URL.
      * Works by extracting the query portion from the URL and then
@@ -604,7 +604,7 @@ public class UrlQuerySanitizer {
         }
         parseQuery(query);
     }
-    
+
     /**
      * Parse a query. A query string is any number of parameter-value clauses
      * separated by any non-zero number of ampersands. A parameter-value clause
@@ -631,7 +631,7 @@ public class UrlQuerySanitizer {
             }
         }
     }
-    
+
     /**
      * Get a set of all of the parameters found in the sanitized query.
      * <p>
@@ -641,7 +641,7 @@ public class UrlQuerySanitizer {
     public Set<String> getParameterSet() {
         return mEntries.keySet();
     }
-    
+
     /**
      * An array list of all of the parameter value pairs in the sanitized
      * query, in the order they appeared in the query. May contain duplicate
@@ -691,7 +691,7 @@ public class UrlQuerySanitizer {
         }
         mSanitizers.put(parameter, valueSanitizer);
     }
-    
+
     /**
      * Register a value sanitizer for an array of parameters.
      * @param parameters An array of unencoded parameter names.
@@ -705,7 +705,7 @@ public class UrlQuerySanitizer {
             mSanitizers.put(parameters[i], valueSanitizer);
         }
     }
-    
+
     /**
      * Set whether or not unregistered parameters are allowed. If they
      * are not allowed, then they will be dropped when a query is sanitized.
@@ -718,7 +718,7 @@ public class UrlQuerySanitizer {
             boolean allowUnregisteredParamaters) {
         mAllowUnregisteredParamaters = allowUnregisteredParamaters;
     }
-    
+
     /**
      * Get whether or not unregistered parameters are allowed. If not
      * allowed, they will be dropped when a query is parsed.
@@ -728,10 +728,10 @@ public class UrlQuerySanitizer {
     public boolean getAllowUnregisteredParamaters() {
         return mAllowUnregisteredParamaters;
     }
-    
+
     /**
      * Set whether or not the first occurrence of a repeated parameter is
-     * preferred. True means the first repeated parameter is preferred. 
+     * preferred. True means the first repeated parameter is preferred.
      * False means that the last repeated parameter is preferred.
      * <p>
      * The preferred parameter is the one that is returned when getParameter
@@ -746,7 +746,7 @@ public class UrlQuerySanitizer {
             boolean preferFirstRepeatedParameter) {
         mPreferFirstRepeatedParameter = preferFirstRepeatedParameter;
     }
-    
+
     /**
      * Get whether or not the first occurrence of a repeated parameter is
      * preferred.
@@ -757,10 +757,10 @@ public class UrlQuerySanitizer {
     public boolean getPreferFirstRepeatedParameter() {
         return mPreferFirstRepeatedParameter;
     }
-    
+
     /**
      * Parse an escaped parameter-value pair. The default implementation
-     * unescapes both the parameter and the value, then looks up the 
+     * unescapes both the parameter and the value, then looks up the
      * effective value sanitizer for the parameter and uses it to sanitize
      * the value. If all goes well then addSanitizedValue is called with
      * the unescaped parameter and the sanitized unescaped value.
@@ -779,7 +779,7 @@ public class UrlQuerySanitizer {
         String sanitizedValue = valueSanitizer.sanitize(unescapedValue);
         addSanitizedEntry(unescapedParameter, sanitizedValue);
     }
-    
+
     /**
      * Record a sanitized parameter-value pair. Override if you want to
      * do additional filtering or validation.
@@ -796,7 +796,7 @@ public class UrlQuerySanitizer {
         }
         mEntries.put(parameter, value);
     }
-    
+
     /**
      * Get the value sanitizer for a parameter. Returns null if there
      * is no value sanitizer registered for the parameter.
@@ -807,7 +807,7 @@ public class UrlQuerySanitizer {
     public ValueSanitizer getValueSanitizer(String parameter) {
         return mSanitizers.get(parameter);
     }
-    
+
     /**
      * Get the effective value sanitizer for a parameter. Like getValueSanitizer,
      * except if there is no value sanitizer registered for a parameter, and
@@ -823,7 +823,7 @@ public class UrlQuerySanitizer {
         }
         return sanitizer;
     }
-    
+
     /**
      * Unescape an escaped string.
      * <ul>
@@ -867,7 +867,7 @@ public class UrlQuerySanitizer {
         }
         return stringBuilder.toString();
     }
-    
+
     /**
      * Test if a character is a hexidecimal digit. Both upper case and lower
      * case hex digits are allowed.
@@ -877,7 +877,7 @@ public class UrlQuerySanitizer {
     protected boolean isHexDigit(char c) {
         return decodeHexDigit(c) >= 0;
     }
-    
+
     /**
      * Convert a character that represents a hexidecimal digit into an integer.
      * If the character is not a hexidecimal digit, then -1 is returned.
@@ -885,7 +885,7 @@ public class UrlQuerySanitizer {
      * @param c the hexidecimal digit.
      * @return the integer value of the hexidecimal digit.
      */
-    
+
     protected int decodeHexDigit(char c) {
         if (c >= '0' && c <= '9') {
             return c - '0';
@@ -900,7 +900,7 @@ public class UrlQuerySanitizer {
             return -1;
         }
     }
-    
+
     /**
      * Clear the existing entries. Called to get ready to parse a new
      * query string.
diff --git a/core/java/android/pim/RecurrenceSet.java b/core/java/android/pim/RecurrenceSet.java
index c6615da03eef..1a287c814dca 100644
--- a/core/java/android/pim/RecurrenceSet.java
+++ b/core/java/android/pim/RecurrenceSet.java
@@ -140,7 +140,6 @@ public class RecurrenceSet {
             recurrence = recurrence.substring(tzidx + 1);
         }
         Time time = new Time(tz);
-        boolean rdateNotInUtc = !tz.equals(Time.TIMEZONE_UTC);
         String[] rawDates = recurrence.split(",");
         int n = rawDates.length;
         long[] dates = new long[n];
diff --git a/core/java/android/preference/PreferenceGroupAdapter.java b/core/java/android/preference/PreferenceGroupAdapter.java
index 05c295224374..02ab1da35fda 100644
--- a/core/java/android/preference/PreferenceGroupAdapter.java
+++ b/core/java/android/preference/PreferenceGroupAdapter.java
@@ -88,6 +88,9 @@ class PreferenceGroupAdapter extends BaseAdapter implements OnPreferenceChangeIn
 
     public PreferenceGroupAdapter(PreferenceGroup preferenceGroup) {
         mPreferenceGroup = preferenceGroup;
+        // If this group gets or loses any children, let us know
+        mPreferenceGroup.setOnPreferenceChangeInternalListener(this);
+        
         mPreferenceList = new ArrayList<Preference>();
         mPreferenceClassNames = new ArrayList<String>();
         
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 054da1de5f48..c6a7b407101c 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -878,15 +878,6 @@ public final class Settings {
          */
         public static final String AIRPLANE_MODE_RADIOS = "airplane_mode_radios";
 
-        /**
-         * The interval in milliseconds after which Wi-Fi is considered idle.
-         * When idle, it is possible for the device to be switched from Wi-Fi to
-         * the mobile data network.
-         * 
-         * @hide pending API Council approval
-         */
-        public static final String WIFI_IDLE_MS = "wifi_idle_ms";
-
         /**
          * The policy for deciding when Wi-Fi should go to sleep (which will in
          * turn switch to using the mobile data as an Internet connection).
@@ -1288,6 +1279,12 @@ public final class Settings {
          */
         public static final String SOUND_EFFECTS_ENABLED = "sound_effects_enabled";
         
+        /**
+         * Whether the haptic feedback (long presses, ...) are enabled. The value is
+         * boolean (1 or 0).
+         */
+        public static final String HAPTIC_FEEDBACK_ENABLED = "haptic_feedback_enabled";
+        
         // Settings moved to Settings.Secure
 
         /**
@@ -2731,6 +2728,13 @@ public final class Settings {
         public static final String GPRS_REGISTER_CHECK_PERIOD_MS =
                 "gprs_register_check_period_ms";
 
+        /**
+         * The interval in milliseconds after which Wi-Fi is considered idle.
+         * When idle, it is possible for the device to be switched from Wi-Fi to
+         * the mobile data network.
+         */
+        public static final String WIFI_IDLE_MS = "wifi_idle_ms";
+
         /**
          * Screen timeout in milliseconds corresponding to the
          * PowerManager's POKE_LOCK_SHORT_TIMEOUT flag (i.e. the fastest
diff --git a/core/java/android/server/BluetoothDeviceService.java b/core/java/android/server/BluetoothDeviceService.java
index d1497619a92e..7c15045dbfb4 100644
--- a/core/java/android/server/BluetoothDeviceService.java
+++ b/core/java/android/server/BluetoothDeviceService.java
@@ -25,8 +25,8 @@
 package android.server;
 
 import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHeadset;  // just for dump()
 import android.bluetooth.BluetoothError;
+import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothIntent;
 import android.bluetooth.IBluetoothDevice;
 import android.bluetooth.IBluetoothDeviceCallback;
@@ -35,23 +35,20 @@ import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.os.RemoteException;
-import android.provider.Settings;
-import android.util.Log;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.Message;
+import android.os.RemoteException;
 import android.os.SystemService;
+import android.provider.Settings;
+import android.util.Log;
 
-import java.io.IOException;
 import java.io.FileDescriptor;
-import java.io.FileNotFoundException;
-import java.io.FileWriter;
 import java.io.PrintWriter;
 import java.io.UnsupportedEncodingException;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 public class BluetoothDeviceService extends IBluetoothDevice.Stub {
@@ -119,7 +116,7 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub {
     public synchronized boolean disable() {
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                 "Need BLUETOOTH_ADMIN permission");
-        
+
         if (mEnableThread != null && mEnableThread.isAlive()) {
             return false;
         }
@@ -229,9 +226,9 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub {
         long origCallerIdentityToken = Binder.clearCallingIdentity();
         Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.BLUETOOTH_ON,
                 bluetoothOn ? 1 : 0);
-        Binder.restoreCallingIdentity(origCallerIdentityToken);        
+        Binder.restoreCallingIdentity(origCallerIdentityToken);
     }
-    
+
     private native int enableNative();
     private native int disableNative();
 
@@ -247,6 +244,7 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub {
     public class BondState {
         private final HashMap<String, Integer> mState = new HashMap<String, Integer>();
         private final HashMap<String, Integer> mPinAttempt = new HashMap<String, Integer>();
+        private final ArrayList<String> mAutoPairingFailures = new ArrayList<String>();
 
         public synchronized void loadBondState() {
             if (!mIsEnabled) {
@@ -281,8 +279,8 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub {
             intent.putExtra(BluetoothIntent.BOND_PREVIOUS_STATE, oldState);
             if (state == BluetoothDevice.BOND_NOT_BONDED) {
                 if (reason <= 0) {
-                    Log.w(TAG, "setBondState() called to unbond device with invalid reason code " +
-                          "Setting reason = BOND_RESULT_REMOVED");
+                    Log.w(TAG, "setBondState() called to unbond device, but reason code is " +
+                          "invalid. Overriding reason code with BOND_RESULT_REMOVED");
                     reason = BluetoothDevice.UNBOND_REASON_REMOVED;
                 }
                 intent.putExtra(BluetoothIntent.REASON, reason);
@@ -290,11 +288,7 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub {
             } else {
                 mState.put(address, state);
             }
-            if (state == BluetoothDevice.BOND_BONDING) {
-                mPinAttempt.put(address, Integer.valueOf(0));
-            } else {
-                mPinAttempt.remove(address);
-            }
+
             mContext.sendBroadcast(intent, BLUETOOTH_PERM);
         }
 
@@ -316,6 +310,24 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub {
             return result.toArray(new String[result.size()]);
         }
 
+        public synchronized void addAutoPairingFailure(String address) {
+            if (!mAutoPairingFailures.contains(address)) {
+                mAutoPairingFailures.add(address);
+            }
+        }
+
+        public synchronized boolean isAutoPairingAttemptsInProgress(String address) {
+            return getAttempt(address) != 0;
+        }
+
+        public synchronized void clearPinAttempts(String address) {
+            mPinAttempt.remove(address);
+        }
+
+        public synchronized boolean hasAutoPairingFailed(String address) {
+            return mAutoPairingFailures.contains(address);
+        }
+
         public synchronized int getAttempt(String address) {
             Integer attempt = mPinAttempt.get(address);
             if (attempt == null) {
@@ -326,10 +338,13 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub {
 
         public synchronized void attempt(String address) {
             Integer attempt = mPinAttempt.get(address);
+            int newAttempt;
             if (attempt == null) {
-                return;
+                newAttempt = 1;
+            } else {
+                newAttempt = attempt.intValue() + 1;
             }
-            mPinAttempt.put(address, new Integer(attempt.intValue() + 1));
+            mPinAttempt.put(address, new Integer(newAttempt));
         }
 
     }
@@ -508,7 +523,11 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub {
             return false;
         }
         address = address.toUpperCase();
-        if (mBondState.getBondState(address) != BluetoothDevice.BOND_NOT_BONDED) {
+
+        // Check for bond state only if we are not performing auto
+        // pairing exponential back-off attempts.
+        if (!mBondState.isAutoPairingAttemptsInProgress(address) &&
+            mBondState.getBondState(address) != BluetoothDevice.BOND_NOT_BONDED) {
             return false;
         }
 
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index 0f60fae34620..b5e409027ce9 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -24,6 +24,8 @@ import android.bluetooth.BluetoothIntent;
 import android.bluetooth.IBluetoothDeviceCallback;
 import android.content.Context;
 import android.content.Intent;
+import android.os.Handler;
+import android.os.Message;
 import android.os.RemoteException;
 import android.util.Log;
 
@@ -48,9 +50,33 @@ class BluetoothEventLoop {
     private BluetoothDeviceService mBluetoothService;
     private Context mContext;
 
+    private static final int EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 1;
+
+    // The time (in millisecs) to delay the pairing attempt after the first
+    // auto pairing attempt fails. We use an exponential delay with
+    // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the initial value and
+    // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY as the max value.
+    private static final long INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 3000;
+    private static final long MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 12000;
+
     private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
     private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
 
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+            case EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY:
+                String address = (String)msg.obj;
+                if (address != null) {
+                    mBluetoothService.createBond(address);
+                    return;
+                }
+                break;
+            }
+        }
+    };
+
     static { classInitNative(); }
     private static native void classInitNative();
 
@@ -149,16 +175,6 @@ class BluetoothEventLoop {
         mContext.sendBroadcast(intent, BLUETOOTH_PERM);
     }
 
-    private void onPairingRequest() {
-        Intent intent = new Intent(BluetoothIntent.PAIRING_REQUEST_ACTION);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-    }
-    
-    private void onPairingCancel() {
-        Intent intent = new Intent(BluetoothIntent.PAIRING_CANCEL_ACTION);
-        mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
-    }
-
     private void onRemoteDeviceFound(String address, int deviceClass, short rssi) {
         Intent intent = new Intent(BluetoothIntent.REMOTE_DEVICE_FOUND_ACTION);
         intent.putExtra(BluetoothIntent.ADDRESS, address);
@@ -214,12 +230,55 @@ class BluetoothEventLoop {
         address = address.toUpperCase();
         if (result == BluetoothError.SUCCESS) {
             mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_BONDED);
+            if (mBluetoothService.getBondState().isAutoPairingAttemptsInProgress(address)) {
+                mBluetoothService.getBondState().clearPinAttempts(address);
+            }
+        } else if (result == BluetoothDevice.UNBOND_REASON_AUTH_FAILED &&
+                mBluetoothService.getBondState().getAttempt(address) == 1) {
+            mBluetoothService.getBondState().addAutoPairingFailure(address);
+            pairingAttempt(address, result);
+        } else if (result == BluetoothDevice.UNBOND_REASON_REMOTE_DEVICE_DOWN &&
+                mBluetoothService.getBondState().isAutoPairingAttemptsInProgress(address)) {
+            pairingAttempt(address, result);
         } else {
             mBluetoothService.getBondState().setBondState(address,
                                                           BluetoothDevice.BOND_NOT_BONDED, result);
+            if (mBluetoothService.getBondState().isAutoPairingAttemptsInProgress(address)) {
+                mBluetoothService.getBondState().clearPinAttempts(address);
+            }
         }
     }
 
+    private void pairingAttempt(String address, int result) {
+        // This happens when our initial guess of "0000" as the pass key
+        // fails. Try to create the bond again and display the pin dialog
+        // to the user. Use back-off while posting the delayed
+        // message. The initial value is
+        // INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY and the max value is
+        // MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY. If the max value is
+        // reached, display an error to the user.
+        int attempt = mBluetoothService.getBondState().getAttempt(address);
+        if (attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY >
+                    MAX_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY) {
+            mBluetoothService.getBondState().clearPinAttempts(address);
+            mBluetoothService.getBondState().setBondState(address,
+                    BluetoothDevice.BOND_NOT_BONDED, result);
+            return;
+        }
+
+        Message message = mHandler.obtainMessage(EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY);
+        message.obj = address;
+        boolean postResult =  mHandler.sendMessageDelayed(message,
+                                        attempt * INIT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY);
+        if (!postResult) {
+            mBluetoothService.getBondState().clearPinAttempts(address);
+            mBluetoothService.getBondState().setBondState(address,
+                    BluetoothDevice.BOND_NOT_BONDED, result);
+            return;
+        }
+        mBluetoothService.getBondState().attempt(address);
+    }
+
     private void onBondingCreated(String address) {
         mBluetoothService.getBondState().setBondState(address.toUpperCase(),
                                                       BluetoothDevice.BOND_BONDED);
@@ -253,12 +312,12 @@ class BluetoothEventLoop {
             case BluetoothClass.Device.AUDIO_VIDEO_PORTABLE_AUDIO:
             case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
             case BluetoothClass.Device.AUDIO_VIDEO_HIFI_AUDIO:
-                if (mBluetoothService.getBondState().getAttempt(address) < 1) {
+                if (!mBluetoothService.getBondState().hasAutoPairingFailed(address)) {
                     mBluetoothService.getBondState().attempt(address);
                     mBluetoothService.setPin(address, BluetoothDevice.convertPinToBytes("0000"));
                     return;
                 }
-            }
+           }
         }
         Intent intent = new Intent(BluetoothIntent.PAIRING_REQUEST_ACTION);
         intent.putExtra(BluetoothIntent.ADDRESS, address);
diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java
index a559b9d6f43d..6df0b35cb497 100644
--- a/core/java/android/text/method/ArrowKeyMovementMethod.java
+++ b/core/java/android/text/method/ArrowKeyMovementMethod.java
@@ -16,6 +16,7 @@
 
 package android.text.method;
 
+import android.util.Log;
 import android.view.KeyEvent;
 import android.text.*;
 import android.widget.TextView;
@@ -185,15 +186,9 @@ implements MovementMethod
         if (code != KeyEvent.KEYCODE_UNKNOWN
                 && event.getAction() == KeyEvent.ACTION_MULTIPLE) {
             int repeat = event.getRepeatCount();
-            boolean first = true;
             boolean handled = false;
             while ((--repeat) > 0) {
-                if (first && executeDown(view, text, code)) {
-                    handled = true;
-                    MetaKeyKeyListener.adjustMetaAfterKeypress(text);
-                    MetaKeyKeyListener.resetLockedMeta(text);
-                }
-                first = false;
+                handled |= executeDown(view, text, code);
             }
             return handled;
         }
diff --git a/core/java/android/text/method/MetaKeyKeyListener.java b/core/java/android/text/method/MetaKeyKeyListener.java
index d89fbec557ae..39ad97689a5d 100644
--- a/core/java/android/text/method/MetaKeyKeyListener.java
+++ b/core/java/android/text/method/MetaKeyKeyListener.java
@@ -287,10 +287,10 @@ public abstract class MetaKeyKeyListener {
     }
 
     public static void clearMetaKeyState(Editable content, int states) {
-        if ((states&META_SHIFT_ON) != 0) resetLock(content, CAP);
-        if ((states&META_ALT_ON) != 0) resetLock(content, ALT);
-        if ((states&META_SYM_ON) != 0) resetLock(content, SYM);
-        if ((states&META_SELECTING) != 0) resetLock(content, SELECTING);
+        if ((states&META_SHIFT_ON) != 0) content.removeSpan(CAP);
+        if ((states&META_ALT_ON) != 0) content.removeSpan(ALT);
+        if ((states&META_SYM_ON) != 0) content.removeSpan(SYM);
+        if ((states&META_SELECTING) != 0) content.removeSpan(SELECTING);
     }
 
     /**
diff --git a/core/java/android/text/method/PasswordTransformationMethod.java b/core/java/android/text/method/PasswordTransformationMethod.java
index 85adabd72abb..fad4f64ffe1e 100644
--- a/core/java/android/text/method/PasswordTransformationMethod.java
+++ b/core/java/android/text/method/PasswordTransformationMethod.java
@@ -105,8 +105,10 @@ implements TransformationMethod, TextWatcher
                         sp.removeSpan(old[i]);
                     }
 
-                    sp.setSpan(new Visible(sp, this), start, start + count,
-                               Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    if (count == 1) {
+                        sp.setSpan(new Visible(sp, this), start, start + count,
+                                   Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+                    }
                 }
             }
         }
diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java
new file mode 100644
index 000000000000..cc3563c40f8d
--- /dev/null
+++ b/core/java/android/view/HapticFeedbackConstants.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+/**
+ * Constants to be used to perform haptic feedback effects via
+ * {@link View#performHapticFeedback(int)} 
+ */
+public class HapticFeedbackConstants {
+
+    private HapticFeedbackConstants() {}
+
+    public static final int LONG_PRESS = 0;
+    
+    /** @hide pending API council */
+    public static final int ZOOM_RING_TICK = 1;
+    
+    /**
+     * Flag for {@link View#performHapticFeedback(int, int)
+     * View.performHapticFeedback(int, int)}: Ignore the setting in the
+     * view for whether to perform haptic feedback, do it always.
+     */
+    public static final int FLAG_IGNORE_VIEW_SETTING = 0x0001;
+    
+    /**
+     * Flag for {@link View#performHapticFeedback(int, int)
+     * View.performHapticFeedback(int, int)}: Ignore the global setting
+     * for whether to perform haptic feedback, do it always.
+     */
+    public static final int FLAG_IGNORE_GLOBAL_SETTING = 0x0002;
+}
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 7276f173cf3f..115685669406 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -106,5 +106,6 @@ interface IWindowSession {
     
     void setInTouchMode(boolean showFocus);
     boolean getInTouchMode();
+    
+    boolean performHapticFeedback(IWindow window, int effectId, boolean always);
 }
-
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a51b5646c157..1d5e7cd49ca5 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -835,6 +835,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback {
      */
     public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
 
+    /**
+     * View flag indicating whether this view should have haptic feedback
+     * enabled for events such as long presses.
+     */
+    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
+
     /**
      * Use with {@link #focusSearch}. Move focus to the previous selectable
      * item.
@@ -1637,6 +1643,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback {
     public View(Context context) {
         mContext = context;
         mResources = context != null ? context.getResources() : null;
+        mViewFlags = SOUND_EFFECTS_ENABLED|HAPTIC_FEEDBACK_ENABLED;
         ++sInstanceCount;
     }
 
@@ -1703,9 +1710,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback {
 
         int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
 
-        viewFlagValues |= SOUND_EFFECTS_ENABLED;
-        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
-
         final int N = a.getIndexCount();
         for (int i = 0; i < N; i++) {
             int attr = a.getIndex(i);
@@ -1801,6 +1805,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback {
                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
                     }
+                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
+                    if (!a.getBoolean(attr, true)) {
+                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
+                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
+                    }
                 case R.styleable.View_scrollbars:
                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
                     if (scrollbars != SCROLLBARS_NONE) {
@@ -2182,6 +2191,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback {
         if (!handled) {
             handled = showContextMenu();
         }
+        if (handled) {
+            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+        }
         return handled;
     }
 
@@ -2742,7 +2754,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback {
      * Set whether this view should have sound effects enabled for events such as
      * clicking and touching.
      *
-     * You may wish to disable sound effects for a view if you already play sounds,
+     * <p>You may wish to disable sound effects for a view if you already play sounds,
      * for instance, a dial key that plays dtmf tones.
      *
      * @param soundEffectsEnabled whether sound effects are enabled for this view.
@@ -2767,6 +2779,35 @@ public class View implements Drawable.Callback, KeyEvent.Callback {
         return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
     }
 
+    /**
+     * Set whether this view should have haptic feedback for events such as
+     * long presses.
+     *
+     * <p>You may wish to disable haptic feedback if your view already controls
+     * its own haptic feedback.
+     *
+     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
+     * @see #isHapticFeedbackEnabled()
+     * @see #performHapticFeedback(int)
+     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
+     */
+    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
+        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
+    }
+
+    /**
+     * @return whether this view should have haptic feedback enabled for events
+     * long presses.
+     *
+     * @see #setHapticFeedbackEnabled(boolean)
+     * @see #performHapticFeedback(int)
+     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
+     */
+    @ViewDebug.ExportedProperty
+    public boolean isHapticFeedbackEnabled() {
+        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
+    }
+
     /**
      * If this view doesn't do any drawing on its own, set this flag to
      * allow further optimizations. By default, this flag is not set on
@@ -7312,20 +7353,57 @@ public class View implements Drawable.Callback, KeyEvent.Callback {
     /**
      * Play a sound effect for this view.
      *
-     * The framework will play sound effects for some built in actions, such as
+     * <p>The framework will play sound effects for some built in actions, such as
      * clicking, but you may wish to play these effects in your widget,
      * for instance, for internal navigation.
      *
-     * The sound effect will only be played if sound effects are enabled by the user, and
+     * <p>The sound effect will only be played if sound effects are enabled by the user, and
      * {@link #isSoundEffectsEnabled()} is true.
      *
      * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
      */
-    protected void playSoundEffect(int soundConstant) {
-        if (mAttachInfo == null || mAttachInfo.mSoundEffectPlayer == null || !isSoundEffectsEnabled()) {
+    public void playSoundEffect(int soundConstant) {
+        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
             return;
         }
-        mAttachInfo.mSoundEffectPlayer.playSoundEffect(soundConstant);
+        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
+    }
+
+    /**
+     * Provide haptic feedback to the user for this view.
+     *
+     * <p>The framework will provide haptic feedback for some built in actions,
+     * such as long presses, but you may wish to provide feedback for your
+     * own widget.
+     *
+     * <p>The feedback will only be performed if
+     * {@link #isHapticFeedbackEnabled()} is true.
+     *
+     * @param feedbackConstant One of the constants defined in
+     * {@link HapticFeedbackConstants}
+     */
+    public boolean performHapticFeedback(int feedbackConstant) {
+        return performHapticFeedback(feedbackConstant, 0);
+    }
+
+    /**
+     * Like {@link #performHapticFeedback(int)}, with additional options.
+     *
+     * @param feedbackConstant One of the constants defined in
+     * {@link HapticFeedbackConstants}
+     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
+     */
+    public boolean performHapticFeedback(int feedbackConstant, int flags) {
+        if (mAttachInfo == null) {
+            return false;
+        }
+        if ((flags&HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
+                && !isHapticFeedbackEnabled()) {
+            return false;
+        }
+        return mAttachInfo.mRootCallbacks.performHapticFeedback(
+                feedbackConstant,
+                (flags&HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
     }
 
     /**
@@ -7704,8 +7782,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback {
      */
     static class AttachInfo {
 
-        interface SoundEffectPlayer {
+        interface Callbacks {
             void playSoundEffect(int effectId);
+            boolean performHapticFeedback(int effectId, boolean always);
         }
 
         /**
@@ -7775,7 +7854,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback {
 
         final IBinder mWindowToken;
 
-        final SoundEffectPlayer mSoundEffectPlayer;
+        final Callbacks mRootCallbacks;
 
         /**
          * The top view of the hierarchy.
@@ -7922,12 +8001,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback {
          * @param handler the events handler the view must use
          */
         AttachInfo(IWindowSession session, IWindow window,
-                Handler handler, SoundEffectPlayer effectPlayer) {
+                Handler handler, Callbacks effectPlayer) {
             mSession = session;
             mWindow = window;
             mWindowToken = window.asBinder();
             mHandler = handler;
-            mSoundEffectPlayer = effectPlayer;
+            mRootCallbacks = effectPlayer;
         }
     }
 
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 4e46397bae38..ccfa6bf97fcf 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -61,7 +61,7 @@ import static javax.microedition.khronos.opengles.GL10.*;
  */
 @SuppressWarnings({"EmptyCatchBlock"})
 public final class ViewRoot extends Handler implements ViewParent,
-        View.AttachInfo.SoundEffectPlayer {
+        View.AttachInfo.Callbacks {
     private static final String TAG = "ViewRoot";
     private static final boolean DBG = false;
     @SuppressWarnings({"ConstantConditionalExpression"})
@@ -1637,7 +1637,7 @@ public final class ViewRoot extends Handler implements ViewParent,
             dispatchDetachedFromWindow();
             break;
         case DISPATCH_KEY_FROM_IME:
-            if (true) Log.v(
+            if (LOCAL_LOGV) Log.v(
                 "ViewRoot", "Dispatching key "
                 + msg.obj + " from IME to " + mView);
             deliverKeyEventToViewHierarchy((KeyEvent)msg.obj, false);
@@ -2235,6 +2235,17 @@ public final class ViewRoot extends Handler implements ViewParent,
         }
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    public boolean performHapticFeedback(int effectId, boolean always) {
+        try {
+            return sWindowSession.performHapticFeedback(mWindow, effectId, always);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
     /**
      * {@inheritDoc}
      */
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index d08a6fa67558..406af3e3d384 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -925,7 +925,7 @@ public interface WindowManager extends ViewManager {
                 sb.append(Integer.toHexString(windowAnimations));
             }
             if (screenOrientation != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
-                sb.append("or=");
+                sb.append(" or=");
                 sb.append(screenOrientation);
             }
             sb.append('}');
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 542b35fc6b8d..051f823fdfde 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -771,4 +771,15 @@ public interface WindowManagerPolicy {
     public boolean isCheekPressedAgainstScreen(MotionEvent ev);
     
     public void setCurrentOrientation(int newOrientation);
+    
+    /**
+     * Call from application to perform haptic feedback on its window.
+     */
+    public boolean performHapticFeedback(WindowState win, int effectId, boolean always);
+    
+    /**
+     * Called when we have stopped keeping the screen on because a window
+     * requesting this is no longer visible.
+     */
+    public void screenOnStopped();
 }
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index 56c6c924fbf3..9509b15317eb 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -371,6 +371,14 @@ public class BaseInputConnection implements InputConnection {
         if (DEBUG) Log.v(TAG, "setSelection " + start + ", " + end);
         final Editable content = getEditable();
         if (content == null) return false;
+        int len = content.length();
+        if (start > len || end > len) {
+            // If the given selection is out of bounds, just ignore it.
+            // Most likely the text was changed out from under the IME,
+            // the the IME is going to have to update all of its state
+            // anyway.
+            return true;
+        }
         Selection.setSelection(content, start, end);
         return true;
     }
@@ -396,20 +404,10 @@ public class BaseInputConnection implements InputConnection {
     }
     
     /**
-     * Provides standard implementation for hiding the status icon associated
-     * with the current input method.
+     * Updates InputMethodManager with the current fullscreen mode.
      */
-    public boolean hideStatusIcon() {
-        mIMM.updateStatusIcon(0, null);
-        return true;
-    }
-    
-    /**
-     * Provides standard implementation for showing the status icon associated
-     * with the current input method.
-     */
-    public boolean showStatusIcon(String packageName, int resId) {
-        mIMM.updateStatusIcon(resId, packageName);
+    public boolean reportFullscreenMode(boolean enabled) {
+        mIMM.setFullscreenMode(enabled);
         return true;
     }
     
@@ -420,7 +418,11 @@ public class BaseInputConnection implements InputConnection {
         
         Editable content = getEditable();
         if (content != null) {
-            if (content.length() == 1) {
+            final int N = content.length();
+            if (N == 0) {
+                return;
+            }
+            if (N == 1) {
                 // If it's 1 character, we have a chance of being
                 // able to generate normal key events...
                 if (mKeyCharacterMap == null) {
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index 8c30d3fd4128..13173f656397 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -266,6 +266,13 @@ public interface InputConnection {
      */
     public boolean clearMetaKeyStates(int states);
     
+    /**
+     * Called by the IME to tell the client when it switches between fullscreen
+     * and normal modes.  This will normally be called for you by the standard
+     * implementation of {@link android.inputmethodservice.InputMethodService}.
+     */
+    public boolean reportFullscreenMode(boolean enabled);
+    
     /**
      * API to send private commands from an input method to its connected
      * editor.  This can be used to provide domain-specific features that are
@@ -284,23 +291,4 @@ public interface InputConnection {
      * valid.
      */
     public boolean performPrivateCommand(String action, Bundle data);
-    
-    /**
-     * Show an icon in the status bar.
-     * 
-     * @param packageName The package holding the icon resource to be shown.
-     * @param resId The resource id of the icon to show.
-     *        
-     * @return Returns true on success, false if the input connection is no longer
-     * valid.
-     */
-    public boolean showStatusIcon(String packageName, int resId);
-    
-    /**
-     * Hide the icon shown in the status bar.
-     *        
-     * @return Returns true on success, false if the input connection is no longer
-     * valid.
-     */
-    public boolean hideStatusIcon();
 }
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 99d5aa511df9..fe1416680620 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -214,6 +214,11 @@ public final class InputMethodManager {
      */
     boolean mActive = false;
     
+    /**
+     * As reported by IME through InputConnection.
+     */
+    boolean mFullscreenMode;
+    
     // -----------------------------------------------------------
     
     /**
@@ -374,6 +379,7 @@ public final class InputMethodManager {
         
         public void setActive(boolean active) {
             mActive = active;
+            mFullscreenMode = false;
         }
     };    
     
@@ -443,14 +449,36 @@ public final class InputMethodManager {
         }
     }
 
-    public void updateStatusIcon(int iconId, String iconPackage) {
+    public void showStatusIcon(IBinder imeToken, String packageName, int iconId) {
+        try {
+            mService.updateStatusIcon(imeToken, packageName, iconId);
+        } catch (RemoteException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public void hideStatusIcon(IBinder imeToken) {
         try {
-            mService.updateStatusIcon(iconId, iconPackage);
+            mService.updateStatusIcon(imeToken, null, 0);
         } catch (RemoteException e) {
             throw new RuntimeException(e);
         }
     }
 
+    /** @hide */
+    public void setFullscreenMode(boolean enabled) {
+        mFullscreenMode = true;
+    }
+    
+    /**
+     * Allows you to discover whether the attached input method is running
+     * in fullscreen mode.  Return true if it is fullscreen, entirely covering
+     * your UI, else returns false.
+     */
+    public boolean isFullscreenMode() {
+        return mFullscreenMode;
+    }
+    
     /**
      * Return true if the given view is the currently active view for the
      * input method.
@@ -503,7 +531,6 @@ public final class InputMethodManager {
     void finishInputLocked() {
         if (mServedView != null) {
             if (DEBUG) Log.v(TAG, "FINISH INPUT: " + mServedView);
-            updateStatusIcon(0, null);
             
             if (mCurrentTextBoxAttribute != null) {
                 try {
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index 5a37f040d5ff..07c1a5d1c025 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -171,6 +171,10 @@ public final class CookieManager {
         boolean pathMatch(String urlPath) {
             if (urlPath.startsWith(path)) {
                 int len = path.length();
+                if (len == 0) {
+                    Log.w(LOGTAG, "Empty cookie path");
+                    return false;
+                }
                 int urlLen = urlPath.length();
                 if (path.charAt(len-1) != PATH_DELIM && urlLen > len) {
                     // make sure /wee doesn't match /we
@@ -864,7 +868,10 @@ public final class CookieManager {
                                     "illegal format for max-age: " + value);
                         }
                     } else if (name.equals(PATH)) {
-                        cookie.path = value;
+                        // only allow non-empty path value
+                        if (value.length() > 0) {
+                            cookie.path = value;
+                        }
                     } else if (name.equals(DOMAIN)) {
                         int lastPeriod = value.lastIndexOf(PERIOD);
                         if (lastPeriod == 0) {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 330670042468..bdbf38a70369 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -260,19 +260,8 @@ public class WebView extends AbsoluteLayout
     // Whether we are in the drag tap mode, which exists starting at the second
     // tap's down, through its move, and includes its up. These events should be
     // given to the method on the zoom controller.
-    private boolean mInZoomTapDragMode;
-    
-    // The event time of the previous touch up. 
-    private long mPreviousUpTime;
-    
-    private Runnable mRemoveReleaseSingleTap = new Runnable() {
-        public void run() {
-            mPrivateHandler.removeMessages(RELEASE_SINGLE_TAP);
-            mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
-            mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
-        }
-    };
-    
+    private boolean mInZoomTapDragMode = false;
+
     // Whether to prevent drag during touch. The initial value depends on
     // mForwardTouchEvents. If WebCore wants touch events, we assume it will
     // take control of touch events unless it says no for touch down event.
@@ -517,6 +506,11 @@ public class WebView extends AbsoluteLayout
     
     private ZoomRingController mZoomRingController;
 
+    // These keep track of the center point of the zoom ring.  They are used to
+    // determine the point around which we should zoom.
+    private float mZoomCenterX;
+    private float mZoomCenterY;
+
     private ZoomRingController.OnZoomListener mZoomListener =
             new ZoomRingController.OnZoomListener() {
         
@@ -554,12 +548,9 @@ public class WebView extends AbsoluteLayout
                     deltaZoomLevel == 0) {
                 return false;
             }
-            
-            int deltaX = centerX - getViewWidth() / 2;
-            int deltaY = centerY - getViewHeight() / 2;
+            mZoomCenterX = (float) centerX;
+            mZoomCenterY = (float) centerY;
 
-            pinScrollBy(deltaX, deltaY, false, 0);
-            
             while (deltaZoomLevel != 0) {
                 if (deltaZoomLevel > 0) {
                     if (!zoomIn()) return false;
@@ -569,15 +560,16 @@ public class WebView extends AbsoluteLayout
                     deltaZoomLevel++;
                 }
             }
-            
-            pinScrollBy(-deltaX, -deltaY, false, 0);
-                    
+
             return true;
         }
         
         public void onSimpleZoom(boolean zoomIn) {
-            if (zoomIn) zoomIn();
-            else zoomOut();
+            if (zoomIn) {
+                zoomIn();
+            } else {
+                zoomOut();
+            }
         }
     };
     
@@ -1586,8 +1578,8 @@ public class WebView extends AbsoluteLayout
                 int oldX = mScrollX;
                 int oldY = mScrollY;
                 float ratio = scale * mInvActualScale;   // old inverse
-                float sx = ratio * oldX + (ratio - 1) * getViewWidth() * 0.5f;
-                float sy = ratio * oldY + (ratio - 1) * getViewHeight() * 0.5f;
+                float sx = ratio * oldX + (ratio - 1) * mZoomCenterX;
+                float sy = ratio * oldY + (ratio - 1) * mZoomCenterY;
 
                 // now update our new scale and inverse
                 if (scale != mActualScale && !mPreviewZoomOnly) {
@@ -2264,8 +2256,8 @@ public class WebView extends AbsoluteLayout
                 zoomScale = mZoomScale;
             }
             float scale = (mActualScale - zoomScale) * mInvActualScale;
-            float tx = scale * ((getLeft() + getRight()) * 0.5f + mScrollX);
-            float ty = scale * ((getTop() + getBottom()) * 0.5f + mScrollY);
+            float tx = scale * (mZoomCenterX + mScrollX);
+            float ty = scale * (mZoomCenterY + mScrollY);
 
             // this block pins the translate to "legal" bounds. This makes the
             // animation a bit non-obvious, but it means we won't pop when the
@@ -3025,8 +3017,8 @@ public class WebView extends AbsoluteLayout
                             (keyCode == KeyEvent.KEYCODE_7) ? 1 : 0, 0);
                     break;
                 case KeyEvent.KEYCODE_9:
-                    debugDump();
-                    break;
+                    nativeInstrumentReport();
+                    return true;
             }
         }
 
@@ -3161,6 +3153,7 @@ public class WebView extends AbsoluteLayout
      * @hide
      */
     public void emulateShiftHeld() {
+        mExtendSelection = false;
         mShiftIsPressed = true;
     }
 
@@ -3176,6 +3169,7 @@ public class WebView extends AbsoluteLayout
                 mWebViewCore.sendMessage(EventHub.GET_SELECTION, selection);
                 copiedSomething = true;
             }
+            mExtendSelection = false;
         }
         mShiftIsPressed = false;
         if (mTouchMode == TOUCH_SELECT_MODE) {
@@ -3218,6 +3212,11 @@ public class WebView extends AbsoluteLayout
         }
     }
 
+    /**
+     * @deprecated WebView should not have implemented
+     * ViewTreeObserver.OnGlobalFocusChangeListener.  This method
+     * does nothing now.
+     */
     @Deprecated
     public void onGlobalFocusChanged(View oldFocus, View newFocus) {
     }
@@ -3281,7 +3280,11 @@ public class WebView extends AbsoluteLayout
     @Override
     protected void onSizeChanged(int w, int h, int ow, int oh) {
         super.onSizeChanged(w, h, ow, oh);
-
+        // Center zooming to the center of the screen.  This is appropriate for
+        // this case of zooming, and it also sets us up properly if we remove
+        // the new zoom ring controller
+        mZoomCenterX = getViewWidth() * .5f;
+        mZoomCenterY = getViewHeight() * .5f;
         // we always force, in case our height changed, in which case we still
         // want to send the notification over to webkit
         setNewZoomScale(mActualScale, true);
@@ -3342,25 +3345,12 @@ public class WebView extends AbsoluteLayout
                     + mTouchMode);
         }
 
-        if (mZoomRingController.isVisible()) {
-            if (mInZoomTapDragMode) {
-                mZoomRingController.handleDoubleTapEvent(ev);
-                if (ev.getAction() == MotionEvent.ACTION_UP) {
-                    // Just released the second tap, no longer in tap-drag mode
-                    mInZoomTapDragMode = false;
-                }
-                return true;
-            } else {
-                // TODO: properly do this.
-                /*
-                 * When the zoom widget is showing, the user can tap outside of
-                 * it to dismiss it. Furthermore, he can drag outside of it to
-                 * pan the browser. However, we do not want a tap on a link to
-                 * open the link.
-                 */
-                post(mRemoveReleaseSingleTap);
-                // Continue through to normal processing
+        if (mZoomRingController.isVisible() && mInZoomTapDragMode) {
+            if (ev.getAction() == MotionEvent.ACTION_UP) {
+                // Just released the second tap, no longer in tap-drag mode
+                mInZoomTapDragMode = false;
             }
+            return mZoomRingController.handleDoubleTapEvent(ev);
         }
 
         int action = ev.getAction();
@@ -3418,21 +3408,19 @@ public class WebView extends AbsoluteLayout
                             , viewToContent(mSelectY), false);
                     mTouchSelection = mExtendSelection = true;
                 } else if (!ZoomRingController.useOldZoom(mContext) &&
-                        eventTime - mPreviousUpTime < DOUBLE_TAP_TIMEOUT &&
-                        getSettings().supportZoom() &&
-                        mMinZoomScale < mMaxZoomScale) {
+                        mPrivateHandler.hasMessages(RELEASE_SINGLE_TAP)) {
                     // Found doubletap, invoke the zoom controller
-                    mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
-                    mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
                     mPrivateHandler.removeMessages(RELEASE_SINGLE_TAP);
                     mZoomRingController.setVisible(true);
                     mInZoomTapDragMode = true;
-                    mZoomRingController.handleDoubleTapEvent(ev);
+                    return mZoomRingController.handleDoubleTapEvent(ev);
                 } else {
                     mTouchMode = TOUCH_INIT_MODE;
                     mPreventDrag = mForwardTouchEvents;
                 }
-                if (mTouchMode == TOUCH_INIT_MODE) {
+                // don't trigger the link if zoom ring is visible
+                if (mTouchMode == TOUCH_INIT_MODE
+                        && !mZoomRingController.isVisible()) {
                     mPrivateHandler.sendMessageDelayed(mPrivateHandler
                             .obtainMessage(SWITCH_TO_SHORTPRESS), TAP_TIMEOUT);
                 }
@@ -3485,9 +3473,6 @@ public class WebView extends AbsoluteLayout
                         mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
                     }
 
-                    // Prevent double-tap from being invoked
-                    mPreviousUpTime = 0;
-                    
                     // if it starts nearly horizontal or vertical, enforce it
                     int ax = Math.abs(deltaX);
                     int ay = Math.abs(deltaY);
@@ -3597,6 +3582,10 @@ public class WebView extends AbsoluteLayout
             case MotionEvent.ACTION_UP: {
                 switch (mTouchMode) {
                     case TOUCH_INIT_MODE: // tap
+                        if (mZoomRingController.isVisible()) {
+                            // don't trigger the link if zoom ring is visible
+                            break;
+                        }
                         mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
                         if (getSettings().supportZoom()
                                 && (mMinZoomScale < mMaxZoomScale)) {
@@ -3611,7 +3600,7 @@ public class WebView extends AbsoluteLayout
                         break;
                     case TOUCH_SELECT_MODE:
                         commitCopy();
-                        mTouchSelection = mExtendSelection = false;
+                        mTouchSelection = false;
                         break;
                     case SCROLL_ZOOM_ANIMATION_IN:
                     case SCROLL_ZOOM_ANIMATION_OUT:
@@ -3679,7 +3668,6 @@ public class WebView extends AbsoluteLayout
                     mVelocityTracker.recycle();
                     mVelocityTracker = null;
                 }
-                mPreviousUpTime = eventTime;
                 break;
             }
             case MotionEvent.ACTION_CANCEL: {
@@ -4109,6 +4097,14 @@ public class WebView extends AbsoluteLayout
         return mZoomControls;
     }
 
+    /**
+     * @hide pending API council? Assuming we make ZoomRingController itself
+     *       public, which I think we will.
+     */
+    public ZoomRingController getZoomRingController() {
+        return mZoomRingController;    
+    }
+    
     /**
      * Perform zoom in in the webview
      * @return TRUE if zoom in succeeds. FALSE if no zoom changes.
@@ -4193,16 +4189,15 @@ public class WebView extends AbsoluteLayout
             return;
         }
         switchOutDrawHistory();
-        // FIXME: we don't know if the current (x,y) is on a focus node or
-        // not -- so playing the sound effect here is premature
-        if (nativeUpdateFocusNode()) {
-            playSoundEffect(SoundEffectConstants.CLICK);
-        }
         // mLastTouchX and mLastTouchY are the point in the current viewport
         int contentX = viewToContent((int) mLastTouchX + mScrollX);
         int contentY = viewToContent((int) mLastTouchY + mScrollY);
         int contentSize = ViewConfiguration.get(getContext()).getScaledTouchSlop();
         nativeMotionUp(contentX, contentY, contentSize, true);
+        if (nativeUpdateFocusNode() && !mFocusNode.mIsTextField
+                && !mFocusNode.mIsTextArea) {
+            playSoundEffect(SoundEffectConstants.CLICK);
+        }
     }
 
     @Override
@@ -5013,6 +5008,7 @@ public class WebView extends AbsoluteLayout
     private native boolean  nativeUpdateFocusNode();
     private native Rect     nativeGetFocusRingBounds();
     private native Rect     nativeGetNavBounds();
+    private native void     nativeInstrumentReport();
     private native void     nativeMarkNodeInvalid(int node);
     private native void     nativeMotionUp(int x, int y, int slop, boolean isClick);
     // returns false if it handled the key
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 8f788872bfe1..b979032f55de 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -330,8 +330,7 @@ final class WebViewCore {
             String currentText, int keyCode, int keyValue, boolean down,
             boolean cap, boolean fn, boolean sym);
 
-    private native void nativeSaveDocumentState(int frame, int node, int x,
-            int y);
+    private native void nativeSaveDocumentState(int frame);
 
     private native void nativeSetFinalFocus(int framePtr, int nodePtr, int x,
             int y, boolean block);
@@ -777,8 +776,7 @@ final class WebViewCore {
 
                         case SAVE_DOCUMENT_STATE: {
                             FocusData fDat = (FocusData) msg.obj;
-                            nativeSaveDocumentState(fDat.mFrame, fDat.mNode,
-                                    fDat.mX, fDat.mY);
+                            nativeSaveDocumentState(fDat.mFrame);
                             break;
                         }
 
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
index 96f36983343a..1004e30ef5e6 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -531,33 +531,34 @@ public class WebViewDatabase {
      * @param url The url
      * @return CacheResult The CacheManager.CacheResult
      */
-    @SuppressWarnings("deprecation")
     CacheResult getCache(String url) {
         if (url == null || mCacheDatabase == null) {
             return null;
         }
 
-        CacheResult ret = null;
-        final String s = "SELECT filepath, lastmodify, etag, expires, mimetype, encoding, httpstatus, location, contentlength FROM cache WHERE url = ";
-        StringBuilder sb = new StringBuilder(256);
-        sb.append(s);
-        DatabaseUtils.appendEscapedSQLString(sb, url);
-        Cursor cursor = mCacheDatabase.rawQuery(sb.toString(), null);
+        Cursor cursor = mCacheDatabase.rawQuery("SELECT filepath, lastmodify, etag, expires, "
+                    + "mimetype, encoding, httpstatus, location, contentlength "
+                    + "FROM cache WHERE url = ?",
+                new String[] { url });
 
-        if (cursor.moveToFirst()) {
-            ret = new CacheResult();
-            ret.localPath = cursor.getString(0);
-            ret.lastModified = cursor.getString(1);
-            ret.etag = cursor.getString(2);
-            ret.expires = cursor.getLong(3);
-            ret.mimeType = cursor.getString(4);
-            ret.encoding = cursor.getString(5);
-            ret.httpStatusCode = cursor.getInt(6);
-            ret.location = cursor.getString(7);
-            ret.contentLength = cursor.getLong(8);
+        try {
+            if (cursor.moveToFirst()) {
+                CacheResult ret = new CacheResult();
+                ret.localPath = cursor.getString(0);
+                ret.lastModified = cursor.getString(1);
+                ret.etag = cursor.getString(2);
+                ret.expires = cursor.getLong(3);
+                ret.mimeType = cursor.getString(4);
+                ret.encoding = cursor.getString(5);
+                ret.httpStatusCode = cursor.getInt(6);
+                ret.location = cursor.getString(7);
+                ret.contentLength = cursor.getLong(8);
+                return ret;
+            }
+        } finally {
+            if (cursor != null) cursor.close();
         }
-        cursor.close();
-        return ret;
+        return null;
     }
 
     /**
@@ -565,16 +566,12 @@ public class WebViewDatabase {
      * 
      * @param url The url
      */
-    @SuppressWarnings("deprecation")
     void removeCache(String url) {
         if (url == null || mCacheDatabase == null) {
             return;
         }
 
-        StringBuilder sb = new StringBuilder(256);
-        sb.append("DELETE FROM cache WHERE url = ");
-        DatabaseUtils.appendEscapedSQLString(sb, url);
-        mCacheDatabase.execSQL(sb.toString());
+        mCacheDatabase.execSQL("DELETE FROM cache WHERE url = ?", new String[] { url });
     }
 
     /**
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 378d2183a7db..c012e25cf0c5 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -31,6 +31,7 @@ import android.text.Editable;
 import android.text.TextWatcher;
 import android.util.AttributeSet;
 import android.view.Gravity;
+import android.view.HapticFeedbackConstants;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -1622,6 +1623,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
             mContextMenuInfo = createContextMenuInfo(child, longPressPosition, longPressId);
             handled = super.showContextMenuForChild(AbsListView.this);
         }
+        if (handled) {
+            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+        }
         return handled;
     }
 
diff --git a/core/java/android/widget/CursorFilter.java b/core/java/android/widget/CursorFilter.java
index afd5b10e0dd3..dbded69364f3 100644
--- a/core/java/android/widget/CursorFilter.java
+++ b/core/java/android/widget/CursorFilter.java
@@ -60,11 +60,10 @@ class CursorFilter extends Filter {
     }
 
     @Override
-    protected void publishResults(CharSequence constraint,
-            FilterResults results) {
+    protected void publishResults(CharSequence constraint, FilterResults results) {
         Cursor oldCursor = mClient.getCursor();
         
-        if (results.values != oldCursor) {
+        if (results.values != null && results.values != oldCursor) {
             mClient.changeCursor((Cursor) results.values);
         }
     }
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 67010b2dcece..54f27072b4f9 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -47,11 +47,8 @@ public class DatePicker extends FrameLayout {
     /* UI Components */
     private final NumberPicker mDayPicker;
     private final NumberPicker mMonthPicker;
-    private final NumberPicker mYearPicker;    
-    
-    private final int mStartYear;
-    private final int mEndYear;
-    
+    private final NumberPicker mYearPicker;
+
     /**
      * How we notify users the date has changed.
      */
@@ -87,12 +84,9 @@ public class DatePicker extends FrameLayout {
     public DatePicker(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
 
-        LayoutInflater inflater =
-                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        inflater.inflate(R.layout.date_picker,
-            this, // we are the parent
-            true);
-        
+        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        inflater.inflate(R.layout.date_picker, this, true);
+
         mDayPicker = (NumberPicker) findViewById(R.id.day);
         mDayPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
         mDayPicker.setSpeed(100);
@@ -134,20 +128,17 @@ public class DatePicker extends FrameLayout {
         });
         
         // attributes
-        TypedArray a = context
-                .obtainStyledAttributes(attrs, R.styleable.DatePicker);
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DatePicker);
 
-        mStartYear = a.getInt(R.styleable.DatePicker_startYear, DEFAULT_START_YEAR);
-        mEndYear = a.getInt(R.styleable.DatePicker_endYear, DEFAULT_END_YEAR);
+        int mStartYear = a.getInt(R.styleable.DatePicker_startYear, DEFAULT_START_YEAR);
+        int mEndYear = a.getInt(R.styleable.DatePicker_endYear, DEFAULT_END_YEAR);
         mYearPicker.setRange(mStartYear, mEndYear);
         
         a.recycle();
         
         // initialize to current date
         Calendar cal = Calendar.getInstance();
-        init(cal.get(Calendar.YEAR), 
-                cal.get(Calendar.MONTH), 
-                cal.get(Calendar.DAY_OF_MONTH), null);
+        init(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH), null);
         
         // re-order the number pickers to match the current date format
         reorderPickers();
diff --git a/core/java/android/widget/Filter.java b/core/java/android/widget/Filter.java
index 7f1601e581c8..a2316cf6c7bf 100644
--- a/core/java/android/widget/Filter.java
+++ b/core/java/android/widget/Filter.java
@@ -20,6 +20,7 @@ import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
+import android.util.Log;
 
 /**
  * <p>A filter constrains data with a filtering pattern.</p>
@@ -36,6 +37,8 @@ import android.os.Message;
  * @see android.widget.Filterable
  */
 public abstract class Filter {
+    private static final String LOG_TAG = "Filter";
+    
     private static final String THREAD_NAME = "Filter";
     private static final int FILTER_TOKEN = 0xD0D0F00D;
     private static final int FINISH_TOKEN = 0xDEADBEEF;
@@ -221,6 +224,9 @@ public abstract class Filter {
                     RequestArguments args = (RequestArguments) msg.obj;
                     try {
                         args.results = performFiltering(args.constraint);
+                    } catch (Exception e) {
+                        args.results = new FilterResults();
+                        Log.w(LOG_TAG, "An exception occured during performFiltering()!", e);
                     } finally {
                         message = mResultHandler.obtainMessage(what);
                         message.obj = args;
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index ffabb0227060..e7b303ada4d0 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -27,6 +27,7 @@ import android.util.Config;
 import android.util.Log;
 import android.view.GestureDetector;
 import android.view.Gravity;
+import android.view.HapticFeedbackConstants;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
@@ -994,6 +995,7 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList
             return;
         }
         
+        performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
         long id = getItemIdAtPosition(mDownTouchPosition);
         dispatchLongPress(mDownTouchView, mDownTouchPosition, id);
     }
@@ -1086,6 +1088,10 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList
             handled = super.showContextMenuForChild(this);
         }
 
+        if (handled) {
+            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+        }
+        
         return handled;
     }
     
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index b5d4e2d5a6d4..4ae322e1fb01 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -48,6 +48,7 @@ import android.widget.RemoteViews.RemoteView;
  * @attr ref android.R.styleable#ImageView_maxHeight
  * @attr ref android.R.styleable#ImageView_tint
  * @attr ref android.R.styleable#ImageView_scaleType
+ * @attr ref android.R.styleable#ImageView_cropToPadding
  */
 @RemoteView
 public class ImageView extends View {
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index a1023bdc5d7d..25afee83a548 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -35,6 +35,8 @@ import android.view.View;
 import android.view.ViewGroup;
 import android.view.LayoutInflater.Filter;
 import android.view.View.OnClickListener;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
@@ -547,6 +549,54 @@ public class RemoteViews implements Parcelable, Filter {
         public final static int TAG = 9;
     }
     
+    /**
+     * Equivalent to calling {@link android.widget.ViewFlipper#startFlipping()}
+     * or {@link android.widget.ViewFlipper#stopFlipping()} along with
+     * {@link android.widget.ViewFlipper#setFlipInterval(int)}.
+     */
+    private class SetFlipping extends Action {
+        public SetFlipping(int id, boolean flipping, int milliseconds) {
+            this.viewId = id;
+            this.flipping = flipping;
+            this.milliseconds = milliseconds;
+        }
+        
+        public SetFlipping(Parcel parcel) {
+            viewId = parcel.readInt();
+            flipping = parcel.readInt() != 0;
+            milliseconds = parcel.readInt();
+        }
+        
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeInt(TAG);
+            dest.writeInt(viewId);
+            dest.writeInt(flipping ? 1 : 0);
+            dest.writeInt(milliseconds);
+        }
+        
+        @Override
+        public void apply(View root) {
+            final View target = root.findViewById(viewId);
+            if (target instanceof ViewFlipper) {
+                final ViewFlipper flipper = (ViewFlipper) target;
+                if (milliseconds != -1) {
+                    flipper.setFlipInterval(milliseconds);
+                }
+                if (flipping) {
+                    flipper.startFlipping();
+                } else {
+                    flipper.stopFlipping();
+                }
+            }
+        }
+        
+        int viewId;
+        boolean flipping;
+        int milliseconds;
+
+        public final static int TAG = 10;
+    }
+
     /**
      * Create a new RemoteViews object that will display the views contained
      * in the specified layout file.
@@ -603,6 +653,9 @@ public class RemoteViews implements Parcelable, Filter {
                 case SetTextColor.TAG:
                     mActions.add(new SetTextColor(parcel));
                     break;
+                case SetFlipping.TAG:
+                    mActions.add(new SetFlipping(parcel));
+                    break;
                 default:
                     throw new ActionException("Tag " + tag + "not found");
                 }
@@ -768,6 +821,22 @@ public class RemoteViews implements Parcelable, Filter {
         addAction(new SetTextColor(viewId, color));
     }
 
+    /**
+     * Equivalent to calling {@link android.widget.ViewFlipper#startFlipping()}
+     * or {@link android.widget.ViewFlipper#stopFlipping()} along with
+     * {@link android.widget.ViewFlipper#setFlipInterval(int)}.
+     * 
+     * @param viewId The id of the view to apply changes to
+     * @param flipping True means we should
+     *            {@link android.widget.ViewFlipper#startFlipping()}, otherwise
+     *            {@link android.widget.ViewFlipper#stopFlipping()}.
+     * @param milliseconds How long to wait before flipping to the next view, or
+     *            -1 to leave unchanged.
+     */
+    public void setFlipping(int viewId, boolean flipping, int milliseconds) {
+        addAction(new SetFlipping(viewId, flipping, milliseconds));
+    }
+
     /**
      * Inflates the view hierarchy represented by this object and applies
      * all of the actions.
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index d21c01722d96..2ae5d4ee5364 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3844,7 +3844,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
             boolean doDown = true;
             if (otherEvent != null) {
                 try {
-                    boolean handled = mMovement.onKeyOther(this, (Editable) mText,
+                    boolean handled = mMovement.onKeyOther(this, (Spannable) mText,
                             otherEvent);
                     doDown = false;
                     if (handled) {
diff --git a/core/java/android/widget/ViewAnimator.java b/core/java/android/widget/ViewAnimator.java
index 8c652e5ead34..fa8935e3bc55 100644
--- a/core/java/android/widget/ViewAnimator.java
+++ b/core/java/android/widget/ViewAnimator.java
@@ -28,6 +28,9 @@ import android.view.animation.AnimationUtils;
 /**
  * Base class for a {@link FrameLayout} container that will perform animations
  * when switching between its views.
+ *
+ * @attr ref android.R.styleable#ViewAnimator_inAnimation
+ * @attr ref android.R.styleable#ViewAnimator_outAnimation
  */
 public class ViewAnimator extends FrameLayout {
 
diff --git a/core/java/android/widget/ViewFlipper.java b/core/java/android/widget/ViewFlipper.java
index a3c15d945b3b..e20bfdf0f52f 100644
--- a/core/java/android/widget/ViewFlipper.java
+++ b/core/java/android/widget/ViewFlipper.java
@@ -22,12 +22,16 @@ import android.content.res.TypedArray;
 import android.os.Handler;
 import android.os.Message;
 import android.util.AttributeSet;
+import android.widget.RemoteViews.RemoteView;
 
 /**
  * Simple {@link ViewAnimator} that will animate between two or more views
  * that have been added to it.  Only one child is shown at a time.  If
  * requested, can automatically flip between each child at a regular interval.
+ *
+ * @attr ref android.R.styleable#ViewFlipper_flipInterval
  */
+@RemoteView
 public class ViewFlipper extends ViewAnimator {
     private int mFlipInterval = 3000;
     private boolean mKeepFlipping = false;
diff --git a/core/java/android/widget/ZoomButton.java b/core/java/android/widget/ZoomButton.java
index df3f307a3cbc..0df919d02a5f 100644
--- a/core/java/android/widget/ZoomButton.java
+++ b/core/java/android/widget/ZoomButton.java
@@ -20,6 +20,7 @@ import android.content.Context;
 import android.os.Handler;
 import android.util.AttributeSet;
 import android.view.GestureDetector;
+import android.view.HapticFeedbackConstants;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
@@ -57,6 +58,7 @@ public class ZoomButton extends ImageButton implements OnLongClickListener {
         mGestureDetector = new GestureDetector(context, new SimpleOnGestureListener() {
             @Override
             public void onLongPress(MotionEvent e) {
+                performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
                 onLongClick(ZoomButton.this);
             }
         });
diff --git a/core/java/android/widget/ZoomRing.java b/core/java/android/widget/ZoomRing.java
index 20d605617075..be3b1fbd527f 100644
--- a/core/java/android/widget/ZoomRing.java
+++ b/core/java/android/widget/ZoomRing.java
@@ -6,10 +6,9 @@ import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
-import android.os.Handler;
+import android.graphics.drawable.RotateDrawable;
 import android.util.AttributeSet;
-import android.util.Log;
-import android.view.KeyEvent;
+import android.view.HapticFeedbackConstants;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewConfiguration;
@@ -18,17 +17,20 @@ import android.view.ViewConfiguration;
  * @hide
  */
 public class ZoomRing extends View {
-    
+
     // TODO: move to ViewConfiguration?
-    private static final int DOUBLE_TAP_DISMISS_TIMEOUT = ViewConfiguration.getJumpTapTimeout();
+    static final int DOUBLE_TAP_DISMISS_TIMEOUT = ViewConfiguration.getJumpTapTimeout();
     // TODO: get from theme
     private static final int DISABLED_ALPHA = 160;
-    
+
     private static final String TAG = "ZoomRing";
 
+    // TODO: Temporary until the trail is done
+    private static final boolean DRAW_TRAIL = false;
+
     // TODO: xml
-    private static final int THUMB_DISTANCE = 63; 
-    
+    private static final int THUMB_DISTANCE = 63;
+
     /** To avoid floating point calculations, we multiply radians by this value. */
     public static final int RADIAN_INT_MULTIPLIER = 100000000;
     /** PI using our multiplier. */
@@ -36,68 +38,81 @@ public class ZoomRing extends View {
     /** PI/2 using our multiplier. */
     private static final int HALF_PI_INT_MULTIPLIED = PI_INT_MULTIPLIED / 2;
 
+    private int mZeroAngle = HALF_PI_INT_MULTIPLIED * 3;
+
     private static final int THUMB_GRAB_SLOP = PI_INT_MULTIPLIED / 4;
-    
+
     /** The cached X of our center. */
     private int mCenterX;
-    /** The cached Y of our center. */ 
+    /** The cached Y of our center. */
     private int mCenterY;
 
     /** The angle of the thumb (in int radians) */
     private int mThumbAngle;
     private boolean mIsThumbAngleValid;
-    private int mThumbCenterX;
-    private int mThumbCenterY;
     private int mThumbHalfWidth;
     private int mThumbHalfHeight;
-    
-    private int mCallbackThreshold = Integer.MAX_VALUE;
-    
-    /** The accumulated amount of drag for the thumb (in int radians). */
-    private int mAcculumalatedThumbDrag = 0;
-   
+
     /** The inner radius of the track. */
     private int mBoundInnerRadiusSquared = 0;
     /** The outer radius of the track. */
     private int mBoundOuterRadiusSquared = Integer.MAX_VALUE;
-    
+
     private int mPreviousWidgetDragX;
     private int mPreviousWidgetDragY;
-    
+
     private boolean mDrawThumb = true;
     private Drawable mThumbDrawable;
-    
+
     private static final int MODE_IDLE = 0;
     private static final int MODE_DRAG_THUMB = 1;
+    /**
+     * User has his finger down, but we are waiting for him to pass the touch
+     * slop before going into the #MODE_MOVE_ZOOM_RING. This is a good time to
+     * show the movable hint.
+     */
+    private static final int MODE_WAITING_FOR_MOVE_ZOOM_RING = 4;
     private static final int MODE_MOVE_ZOOM_RING = 2;
     private static final int MODE_TAP_DRAG = 3;
     private int mMode;
 
-    private long mPreviousTapTime;
-    
-    private Handler mHandler = new Handler();
-    
+    private long mPreviousDownTime;
+    private int mPreviousDownX;
+    private int mPreviousDownY;
+
     private Disabler mDisabler = new Disabler();
-    
+
     private OnZoomRingCallback mCallback;
-    
+    private int mPreviousCallbackAngle;
+    private int mCallbackThreshold = Integer.MAX_VALUE;
+
     private boolean mResetThumbAutomatically = true;
     private int mThumbDragStartAngle;
-    
+    private final int mTouchSlop;
+    private Drawable mTrail;
+    private double mAcculumalatedTrailAngle;
+
     public ZoomRing(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
-        // TODO get drawable from style instead
+
+        ViewConfiguration viewConfiguration = ViewConfiguration.get(context);
+        mTouchSlop = viewConfiguration.getScaledTouchSlop();
+
+        // TODO get drawables from style instead
         Resources res = context.getResources();
         mThumbDrawable = res.getDrawable(R.drawable.zoom_ring_thumb);
-        
+        if (DRAW_TRAIL) {
+            mTrail = res.getDrawable(R.drawable.zoom_ring_trail).mutate();
+        }
+
         // TODO: add padding to drawable
         setBackgroundResource(R.drawable.zoom_ring_track);
         // TODO get from style
         setBounds(30, Integer.MAX_VALUE);
-        
+
         mThumbHalfHeight = mThumbDrawable.getIntrinsicHeight() / 2;
         mThumbHalfWidth = mThumbDrawable.getIntrinsicWidth() / 2;
-        
+
         mCallbackThreshold = PI_INT_MULTIPLIED / 6;
     }
 
@@ -108,7 +123,7 @@ public class ZoomRing extends View {
     public ZoomRing(Context context) {
         this(context, null);
     }
-    
+
     public void setCallback(OnZoomRingCallback callback) {
         mCallback = callback;
     }
@@ -132,26 +147,49 @@ public class ZoomRing extends View {
             mBoundOuterRadiusSquared = Integer.MAX_VALUE;
         }
     }
-    
+
     public void setThumbAngle(int angle) {
         mThumbAngle = angle;
-        mThumbCenterX = (int) (Math.cos(1f * angle / RADIAN_INT_MULTIPLIER) * THUMB_DISTANCE)
-                + mCenterX;
-        mThumbCenterY = (int) (Math.sin(1f * angle / RADIAN_INT_MULTIPLIER) * THUMB_DISTANCE)
-                * -1 + mCenterY;
+        int unoffsetAngle = angle + mZeroAngle;
+        int thumbCenterX = (int) (Math.cos(1f * unoffsetAngle / RADIAN_INT_MULTIPLIER) *
+                THUMB_DISTANCE) + mCenterX;
+        int thumbCenterY = (int) (Math.sin(1f * unoffsetAngle / RADIAN_INT_MULTIPLIER) *
+                THUMB_DISTANCE) * -1 + mCenterY;
+
+        mThumbDrawable.setBounds(thumbCenterX - mThumbHalfWidth,
+                thumbCenterY - mThumbHalfHeight,
+                thumbCenterX + mThumbHalfWidth,
+                thumbCenterY + mThumbHalfHeight);
+
+        if (DRAW_TRAIL) {
+            double degrees;
+            degrees = Math.min(359.0, Math.abs(mAcculumalatedTrailAngle));
+            int level = (int) (10000.0 * degrees / 360.0);
+
+            mTrail.setLevel((int) (10000.0 *
+                    (-Math.toDegrees(angle / (double) RADIAN_INT_MULTIPLIER) -
+                            degrees + 90) / 360.0));
+            ((RotateDrawable) mTrail).getDrawable().setLevel(level);
+        }
+
         invalidate();
     }
-    
+
+    public void resetThumbAngle(int angle) {
+        mPreviousCallbackAngle = angle;
+        setThumbAngle(angle);
+    }
+
     public void resetThumbAngle() {
         if (mResetThumbAutomatically) {
-            setThumbAngle(HALF_PI_INT_MULTIPLIED);
+            resetThumbAngle(0);
         }
     }
-    
+
     public void setResetThumbAutomatically(boolean resetThumbAutomatically) {
         mResetThumbAutomatically = resetThumbAutomatically;
     }
-    
+
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         setMeasuredDimension(resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec),
@@ -162,7 +200,7 @@ public class ZoomRing extends View {
     protected void onLayout(boolean changed, int left, int top, int right,
             int bottom) {
         super.onLayout(changed, left, top, right, bottom);
-        
+
         // Cache the center point
         mCenterX = (right - left) / 2;
         mCenterY = (bottom - top) / 2;
@@ -172,8 +210,12 @@ public class ZoomRing extends View {
         if (mThumbAngle == Integer.MIN_VALUE) {
             resetThumbAngle();
         }
+
+        if (DRAW_TRAIL) {
+            mTrail.setBounds(0, 0, right - left, bottom - top);
+        }
     }
-    
+
     @Override
     public boolean onTouchEvent(MotionEvent event) {
         return handleTouch(event.getAction(), event.getEventTime(),
@@ -184,61 +226,66 @@ public class ZoomRing extends View {
     private void resetState() {
         mMode = MODE_IDLE;
         mPreviousWidgetDragX = mPreviousWidgetDragY = Integer.MIN_VALUE;
-        mAcculumalatedThumbDrag = 0;
+        mAcculumalatedTrailAngle = 0.0;
         mIsThumbAngleValid = false;
     }
-    
+
     public void setTapDragMode(boolean tapDragMode, int x, int y) {
         resetState();
         mMode = tapDragMode ? MODE_TAP_DRAG : MODE_IDLE;
         mIsThumbAngleValid = false;
-        
+
         if (tapDragMode && mCallback != null) {
             onThumbDragStarted(getAngle(x - mCenterX, y - mCenterY));
         }
     }
-    
+
     public boolean handleTouch(int action, long time, int x, int y, int rawX, int rawY) {
         switch (action) {
-        
+
             case MotionEvent.ACTION_DOWN:
-                if (mPreviousTapTime + DOUBLE_TAP_DISMISS_TIMEOUT >= time) {
+                if (mPreviousDownTime + DOUBLE_TAP_DISMISS_TIMEOUT >= time) {
                     if (mCallback != null) {
                         mCallback.onZoomRingDismissed();
                     }
                 } else {
-                    mPreviousTapTime = time;
+                    mPreviousDownTime = time;
+                    mPreviousDownX = x;
+                    mPreviousDownY = y;
                 }
                 resetState();
                 return true;
-                
+
             case MotionEvent.ACTION_MOVE:
                 // Fall through to code below switch
                 break;
-                
+
             case MotionEvent.ACTION_CANCEL:
             case MotionEvent.ACTION_UP:
                 if (mCallback != null) {
-                    if (mMode == MODE_MOVE_ZOOM_RING) {
-                        mCallback.onZoomRingMovingStopped();
+                    if (mMode == MODE_MOVE_ZOOM_RING || mMode == MODE_WAITING_FOR_MOVE_ZOOM_RING) {
+                        mCallback.onZoomRingSetMovableHintVisible(false);
+                        if (mMode == MODE_MOVE_ZOOM_RING) {
+                            mCallback.onZoomRingMovingStopped();
+                        }
                     } else if (mMode == MODE_DRAG_THUMB || mMode == MODE_TAP_DRAG) {
                         onThumbDragStopped(getAngle(x - mCenterX, y - mCenterY));
                     }
                 }
                 mDisabler.setEnabling(true);
                 return true;
-                
+
             default:
                 return false;
         }
-        
+
         // local{X,Y} will be where the center of the widget is (0,0)
         int localX = x - mCenterX;
         int localY = y - mCenterY;
         boolean isTouchingThumb = true;
         boolean isInBounds = true;
         int touchAngle = getAngle(localX, localY);
-        
+
         int radiusSquared = localX * localX + localY * localY;
         if (radiusSquared < mBoundInnerRadiusSquared ||
                 radiusSquared > mBoundOuterRadiusSquared) {
@@ -246,7 +293,7 @@ public class ZoomRing extends View {
             isTouchingThumb = false;
             isInBounds = false;
         }
-        
+
         int deltaThumbAndTouch = getDelta(touchAngle, mThumbAngle);
         int absoluteDeltaThumbAndTouch = deltaThumbAndTouch >= 0 ?
                 deltaThumbAndTouch : -deltaThumbAndTouch;
@@ -255,19 +302,35 @@ public class ZoomRing extends View {
             // Didn't grab close enough to the thumb
             isTouchingThumb = false;
         }
-        
+
         if (mMode == MODE_IDLE) {
-            mMode = isTouchingThumb ? MODE_DRAG_THUMB : MODE_MOVE_ZOOM_RING;
-            
+            if (isTouchingThumb) {
+                mMode = MODE_DRAG_THUMB;
+            } else {
+                mMode = MODE_WAITING_FOR_MOVE_ZOOM_RING;
+            }
+
             if (mCallback != null) {
                 if (mMode == MODE_DRAG_THUMB) {
                     onThumbDragStarted(touchAngle);
-                } else if (mMode == MODE_MOVE_ZOOM_RING) {
+                } else if (mMode == MODE_WAITING_FOR_MOVE_ZOOM_RING) {
+                    mCallback.onZoomRingSetMovableHintVisible(true);
+                }
+            }
+
+        } else if (mMode == MODE_WAITING_FOR_MOVE_ZOOM_RING) {
+            if (Math.abs(x - mPreviousDownX) > mTouchSlop ||
+                    Math.abs(y - mPreviousDownY) > mTouchSlop) {
+                /* Make sure the user has moved the slop amount before going into that mode. */
+                mMode = MODE_MOVE_ZOOM_RING;
+
+                if (mCallback != null) {
                     mCallback.onZoomRingMovingStarted();
                 }
             }
         }
-        
+
+        // Purposefully not an "else if"
         if (mMode == MODE_DRAG_THUMB || mMode == MODE_TAP_DRAG) {
             if (isInBounds) {
                 onThumbDragged(touchAngle, mIsThumbAngleValid ? deltaThumbAndTouch : 0);
@@ -277,13 +340,13 @@ public class ZoomRing extends View {
         } else if (mMode == MODE_MOVE_ZOOM_RING) {
             onZoomRingMoved(rawX, rawY);
         }
-        
+
         return true;
     }
-    
+
     private int getDelta(int angle1, int angle2) {
         int delta = angle1 - angle2;
-                
+
         // Assume this is a result of crossing over the discontinuous 0 -> 2pi
         if (delta > PI_INT_MULTIPLIED || delta < -PI_INT_MULTIPLIED) {
             // Bring both the radians and previous angle onto a continuous range
@@ -295,7 +358,7 @@ public class ZoomRing extends View {
                 delta -= PI_INT_MULTIPLIED * 2;
             }
         }
-       
+
         return delta;
     }
 
@@ -303,46 +366,69 @@ public class ZoomRing extends View {
         mThumbDragStartAngle = startAngle;
         mCallback.onZoomRingThumbDraggingStarted(startAngle);
     }
-    
+
     private void onThumbDragged(int touchAngle, int deltaAngle) {
-        mAcculumalatedThumbDrag += deltaAngle;
-        if (mAcculumalatedThumbDrag > mCallbackThreshold
-                || mAcculumalatedThumbDrag < -mCallbackThreshold) {
+        mAcculumalatedTrailAngle += Math.toDegrees(deltaAngle / (double) RADIAN_INT_MULTIPLIER);
+        int totalDeltaAngle = getDelta(touchAngle, mPreviousCallbackAngle);
+        if (totalDeltaAngle > mCallbackThreshold
+                || totalDeltaAngle < -mCallbackThreshold) {
             if (mCallback != null) {
                 boolean canStillZoom = mCallback.onZoomRingThumbDragged(
-                        mAcculumalatedThumbDrag / mCallbackThreshold,
-                        mAcculumalatedThumbDrag, mThumbDragStartAngle, touchAngle);
+                        totalDeltaAngle / mCallbackThreshold,
+                        mThumbDragStartAngle, touchAngle);
                 mDisabler.setEnabling(canStillZoom);
+
+                if (canStillZoom) {
+                    // TODO: we're trying the haptics to see how it goes with
+                    // users, so we're ignoring the settings (for now)
+                    performHapticFeedback(HapticFeedbackConstants.ZOOM_RING_TICK,
+                            HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING |
+                            HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
+                }
             }
-            mAcculumalatedThumbDrag = 0;
+
+            // Get the closest tick and lock on there
+            mPreviousCallbackAngle = getClosestTickAngle(touchAngle);
         }
-    
+
         setThumbAngle(touchAngle);
         mIsThumbAngleValid = true;
     }
-    
+
+    private int getClosestTickAngle(int angle) {
+        int smallerAngleDistance = angle % mCallbackThreshold;
+        int smallerAngle = angle - smallerAngleDistance;
+        if (smallerAngleDistance < mCallbackThreshold / 2) {
+            // Closer to the smaller angle
+            return smallerAngle;
+        } else {
+            // Closer to the bigger angle (premodding)
+            return (smallerAngle + mCallbackThreshold) % (PI_INT_MULTIPLIED * 2);
+        }
+    }
+
     private void onThumbDragStopped(int stopAngle) {
         mCallback.onZoomRingThumbDraggingStopped(stopAngle);
     }
-    
+
     private void onZoomRingMoved(int x, int y) {
         if (mPreviousWidgetDragX != Integer.MIN_VALUE) {
             int deltaX = x - mPreviousWidgetDragX;
             int deltaY = y - mPreviousWidgetDragY;
-            
+
             if (mCallback != null) {
                 mCallback.onZoomRingMoved(deltaX, deltaY);
             }
         }
-        
+
         mPreviousWidgetDragX = x;
         mPreviousWidgetDragY = y;
     }
-    
+
     @Override
     public void onWindowFocusChanged(boolean hasWindowFocus) {
         super.onWindowFocusChanged(hasWindowFocus);
-        
+
         if (!hasWindowFocus && mCallback != null) {
             mCallback.onZoomRingDismissed();
         }
@@ -353,22 +439,25 @@ public class ZoomRing extends View {
 
         // Convert from [-pi,pi] to {0,2pi]
         if (radians < 0) {
-            return -radians;
+            radians = -radians;
         } else if (radians > 0) {
-            return 2 * PI_INT_MULTIPLIED - radians;
+            radians = 2 * PI_INT_MULTIPLIED - radians;
         } else {
-            return 0;
+            radians = 0;
         }
+
+        radians = radians - mZeroAngle;
+        return radians >= 0 ? radians : radians + 2 * PI_INT_MULTIPLIED;
     }
 
     @Override
     protected void onDraw(Canvas canvas) {
         super.onDraw(canvas);
-        
+
         if (mDrawThumb) {
-            mThumbDrawable.setBounds(mThumbCenterX - mThumbHalfWidth, mThumbCenterY
-                    - mThumbHalfHeight, mThumbCenterX + mThumbHalfWidth, mThumbCenterY
-                    + mThumbHalfHeight);
+            if (DRAW_TRAIL) {
+                mTrail.draw(canvas);
+            }
             mThumbDrawable.draw(canvas);
         }
     }
@@ -409,12 +498,14 @@ public class ZoomRing extends View {
     }
     
     public interface OnZoomRingCallback {
+        void onZoomRingSetMovableHintVisible(boolean visible);
+        
         void onZoomRingMovingStarted();
         boolean onZoomRingMoved(int deltaX, int deltaY);
         void onZoomRingMovingStopped();
         
         void onZoomRingThumbDraggingStarted(int startAngle);
-        boolean onZoomRingThumbDragged(int numLevels, int dragAmount, int startAngle, int curAngle);
+        boolean onZoomRingThumbDragged(int numLevels, int startAngle, int curAngle);
         void onZoomRingThumbDraggingStopped(int endAngle);
         
         void onZoomRingDismissed();
diff --git a/core/java/android/widget/ZoomRingController.java b/core/java/android/widget/ZoomRingController.java
index 2ca03741b7b5..eb287670c7a1 100644
--- a/core/java/android/widget/ZoomRingController.java
+++ b/core/java/android/widget/ZoomRingController.java
@@ -17,14 +17,17 @@
 package android.widget;
 
 import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.SharedPreferences;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.Message;
 import android.os.SystemClock;
+import android.os.Vibrator;
 import android.provider.Settings;
 import android.util.Log;
 import android.view.Gravity;
@@ -42,6 +45,7 @@ import android.view.animation.DecelerateInterpolator;
 
 /**
  * TODO: Docs
+ * 
  * @hide
  */
 public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
@@ -222,7 +226,7 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
     public ZoomRingController(Context context, View ownerView) {
         mContext = context;
         mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
-        
+
         mOwnerView = ownerView;
         
         mZoomRing = new ZoomRing(context);
@@ -437,7 +441,15 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
                     
                         case MotionEvent.ACTION_UP:
                             mTouchMode = TOUCH_MODE_IDLE;
+                            
+                            /*
+                             * This is a power-user feature that only shows the
+                             * zoom while the user is performing the tap-drag.
+                             * That means once it is released, the zoom ring
+                             * should disappear.
+                             */  
                             mZoomRing.setTapDragMode(false, (int) event.getX(), (int) event.getY());
+                            dismissZoomRingDelayed(0);
                             break;
                     }
                     break;
@@ -560,10 +572,13 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
         mZoomRing.handleTouch(event.getAction(), event.getEventTime(), x, y, rawX, rawY);
     }
     
+    public void onZoomRingSetMovableHintVisible(boolean visible) {
+        setPanningArrowsVisible(visible); 
+    }
+
     public void onZoomRingMovingStarted() {
         mHandler.removeMessages(MSG_DISMISS_ZOOM_RING);
         mScroller.abortAnimation();
-        setPanningArrowsVisible(true); 
     }
     
     private void setPanningArrowsVisible(boolean visible) {
@@ -641,8 +656,7 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
         }
     }
     
-    public boolean onZoomRingThumbDragged(int numLevels, int dragAmount, int startAngle,
-            int curAngle) {
+    public boolean onZoomRingThumbDragged(int numLevels, int startAngle, int curAngle) {
         if (mCallback != null) {
             int deltaZoomLevel = -numLevels;
             int globalZoomCenterX = mContainerLayoutParams.x + mZoomRing.getLeft() +
@@ -650,7 +664,8 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
             int globalZoomCenterY = mContainerLayoutParams.y + mZoomRing.getTop() +
                     mZoomRingHeight / 2;
             
-            return mCallback.onDragZoom(deltaZoomLevel, globalZoomCenterX - mOwnerViewBounds.left,
+            return mCallback.onDragZoom(deltaZoomLevel,
+                    globalZoomCenterX - mOwnerViewBounds.left,
                     globalZoomCenterY - mOwnerViewBounds.top,
                     (float) startAngle / ZoomRing.RADIAN_INT_MULTIPLIER,
                     (float) curAngle / ZoomRing.RADIAN_INT_MULTIPLIER);
@@ -719,6 +734,45 @@ public class ZoomRingController implements ZoomRing.OnZoomRingCallback,
         ensureZoomRingIsCentered();
     }
 
+    /**
+     * Shows a "tutorial" (some text) to the user teaching her the new zoom
+     * invocation method.
+     * <p>
+     * It checks the global system setting to ensure this has not been seen
+     * before. Furthermore, if the application does not have privilege to write
+     * to the system settings, it will store this bit locally in a shared
+     * preference.
+     * 
+     * @hide This should only be used by our main apps--browser, maps, and
+     *       gallery
+     */
+    public static void showZoomTutorialOnce(Context context) {
+        ContentResolver cr = context.getContentResolver();
+        if (Settings.System.getInt(cr, SETTING_NAME_SHOWN_TOAST, 0) == 1) {
+            return;
+        }
+        
+        SharedPreferences sp = context.getSharedPreferences("_zoom", Context.MODE_PRIVATE);
+        if (sp.getInt(SETTING_NAME_SHOWN_TOAST, 0) == 1) {
+            return;
+        }
+        
+        try {
+            Settings.System.putInt(cr, SETTING_NAME_SHOWN_TOAST, 1);
+        } catch (SecurityException e) {
+            /*
+             * The app does not have permission to clear this global flag, make
+             * sure the user does not see the message when he comes back to this
+             * same app at least.
+             */
+            sp.edit().putInt(SETTING_NAME_SHOWN_TOAST, 1).commit();
+        }
+
+        Toast.makeText(context,
+                com.android.internal.R.string.tutorial_double_tap_to_zoom_message_short,
+                Toast.LENGTH_LONG).show();
+    }
+    
     private class Panner implements Runnable {
         private static final int RUN_DELAY = 15;
         private static final float STOP_SLOWDOWN = 0.8f;
diff --git a/core/java/com/android/internal/gadget/IGadgetHost.aidl b/core/java/com/android/internal/gadget/IGadgetHost.aidl
index a5b865496db7..e7b5a1e22e60 100644
--- a/core/java/com/android/internal/gadget/IGadgetHost.aidl
+++ b/core/java/com/android/internal/gadget/IGadgetHost.aidl
@@ -17,11 +17,12 @@
 package com.android.internal.gadget;
 
 import android.content.ComponentName;
-import android.gadget.GadgetInfo;
+import android.gadget.GadgetProviderInfo;
 import android.widget.RemoteViews;
 
 /** {@hide} */
 oneway interface IGadgetHost {
     void updateGadget(int gadgetId, in RemoteViews views);
+    void providerChanged(int gadgetId, in GadgetProviderInfo info);
 }
 
diff --git a/core/java/com/android/internal/gadget/IGadgetService.aidl b/core/java/com/android/internal/gadget/IGadgetService.aidl
index 1b3946fce3a8..a22f3f399ec4 100644
--- a/core/java/com/android/internal/gadget/IGadgetService.aidl
+++ b/core/java/com/android/internal/gadget/IGadgetService.aidl
@@ -17,7 +17,7 @@
 package com.android.internal.gadget;
 
 import android.content.ComponentName;
-import android.gadget.GadgetInfo;
+import android.gadget.GadgetProviderInfo;
 import com.android.internal.gadget.IGadgetHost;
 import android.widget.RemoteViews;
 
@@ -41,8 +41,8 @@ interface IGadgetService {
     //
     void updateGadgetIds(in int[] gadgetIds, in RemoteViews views);
     void updateGadgetProvider(in ComponentName provider, in RemoteViews views);
-    List<GadgetInfo> getInstalledProviders();
-    GadgetInfo getGadgetInfo(int gadgetId);
+    List<GadgetProviderInfo> getInstalledProviders();
+    GadgetProviderInfo getGadgetInfo(int gadgetId);
     void bindGadgetId(int gadgetId, in ComponentName provider);
 
 }
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index b0b00b2d4c52..ac72a20e6483 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -32,8 +32,7 @@ public class IInputConnectionWrapper extends IInputContext.Stub {
     private static final int DO_DELETE_SURROUNDING_TEXT = 80;
     private static final int DO_BEGIN_BATCH_EDIT = 90;
     private static final int DO_END_BATCH_EDIT = 95;
-    private static final int DO_HIDE_STATUS_ICON = 100;
-    private static final int DO_SHOW_STATUS_ICON = 110;
+    private static final int DO_REPORT_FULLSCREEN_MODE = 100;
     private static final int DO_PERFORM_PRIVATE_COMMAND = 120;
     private static final int DO_CLEAR_META_KEY_STATES = 130;
         
@@ -133,12 +132,8 @@ public class IInputConnectionWrapper extends IInputContext.Stub {
         dispatchMessage(obtainMessage(DO_END_BATCH_EDIT));
     }
 
-    public void hideStatusIcon() {
-        dispatchMessage(obtainMessage(DO_HIDE_STATUS_ICON));
-    }
-
-    public void showStatusIcon(String packageName, int resId) {
-        dispatchMessage(obtainMessageIO(DO_SHOW_STATUS_ICON, resId, packageName));
+    public void reportFullscreenMode(boolean enabled) {
+        dispatchMessage(obtainMessageII(DO_REPORT_FULLSCREEN_MODE, enabled ? 1 : 0, 0));
     }
 
     public void performPrivateCommand(String action, Bundle data) {
@@ -323,22 +318,13 @@ public class IInputConnectionWrapper extends IInputContext.Stub {
                 ic.endBatchEdit();
                 return;
             }
-            case DO_HIDE_STATUS_ICON: {
-                InputConnection ic = mInputConnection.get();
-                if (ic == null || !isActive()) {
-                    Log.w(TAG, "hideStatusIcon on inactive InputConnection");
-                    return;
-                }
-                ic.hideStatusIcon();
-                return;
-            }
-            case DO_SHOW_STATUS_ICON: {
+            case DO_REPORT_FULLSCREEN_MODE: {
                 InputConnection ic = mInputConnection.get();
                 if (ic == null || !isActive()) {
                     Log.w(TAG, "showStatusIcon on inactive InputConnection");
                     return;
                 }
-                ic.showStatusIcon((String)msg.obj, msg.arg1);
+                ic.reportFullscreenMode(msg.arg1 != 1);
                 return;
             }
             case DO_PERFORM_PRIVATE_COMMAND: {
diff --git a/core/java/com/android/internal/view/IInputContext.aidl b/core/java/com/android/internal/view/IInputContext.aidl
index 7cc8ada6044e..02b604438a35 100644
--- a/core/java/com/android/internal/view/IInputContext.aidl
+++ b/core/java/com/android/internal/view/IInputContext.aidl
@@ -56,13 +56,11 @@ import com.android.internal.view.IInputContextCallback;
     
     void endBatchEdit();
     
+    void reportFullscreenMode(boolean enabled);
+    
     void sendKeyEvent(in KeyEvent event);
     
     void clearMetaKeyStates(int states);
     
     void performPrivateCommand(String action, in Bundle data);
-    
-    void showStatusIcon(String packageName, int resId);
-
-    void hideStatusIcon();
 }
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 2f5cd14ea7ac..1b1c7f78a7af 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -47,7 +47,7 @@ interface IInputMethodManager {
     void showInputMethodPickerFromClient(in IInputMethodClient client);
     void setInputMethod(in IBinder token, String id);
     void hideMySoftInput(in IBinder token, int flags);
-    void updateStatusIcon(int iconId, String iconPackage);
+    void updateStatusIcon(in IBinder token, String packageName, int iconId);
     
     boolean setInputMethodEnabled(String id, boolean enabled);
 }
diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java
index af4ad25fc6f2..32d9f3dd2287 100644
--- a/core/java/com/android/internal/view/InputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/InputConnectionWrapper.java
@@ -322,18 +322,9 @@ public class InputConnectionWrapper implements InputConnection {
         }
     }
 
-    public boolean hideStatusIcon() {
+    public boolean reportFullscreenMode(boolean enabled) {
         try {
-            mIInputContext.showStatusIcon(null, 0);
-            return true;
-        } catch (RemoteException e) {
-            return false;
-        }
-    }
-
-    public boolean showStatusIcon(String packageName, int resId) {
-        try {
-            mIInputContext.showStatusIcon(packageName, resId);
+            mIInputContext.reportFullscreenMode(enabled);
             return true;
         } catch (RemoteException e) {
             return false;
diff --git a/core/java/com/android/internal/widget/NumberPicker.java b/core/java/com/android/internal/widget/NumberPicker.java
index 20ea6a6d2879..1647c207ff00 100644
--- a/core/java/com/android/internal/widget/NumberPicker.java
+++ b/core/java/com/android/internal/widget/NumberPicker.java
@@ -28,12 +28,8 @@ import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.View.OnFocusChangeListener;
 import android.view.View.OnLongClickListener;
-import android.view.animation.Animation;
-import android.view.animation.TranslateAnimation;
-import android.widget.EditText;
-import android.widget.LinearLayout;
 import android.widget.TextView;
-import android.widget.ViewSwitcher;
+import android.widget.LinearLayout;
 
 import com.android.internal.R;
 
@@ -71,25 +67,18 @@ public class NumberPicker extends LinearLayout implements OnClickListener,
     private final Runnable mRunnable = new Runnable() {
         public void run() {
             if (mIncrement) {
-                changeCurrent(mCurrent + 1, mSlideUpInAnimation, mSlideUpOutAnimation);
+                changeCurrent(mCurrent + 1);
                 mHandler.postDelayed(this, mSpeed);
             } else if (mDecrement) {
-                changeCurrent(mCurrent - 1, mSlideDownInAnimation, mSlideDownOutAnimation);
+                changeCurrent(mCurrent - 1);
                 mHandler.postDelayed(this, mSpeed);
             }
         }
     };
-    
-    private final LayoutInflater mInflater;
+
     private final TextView mText;
-    private final InputFilter mInputFilter;
     private final InputFilter mNumberInputFilter;
-    
-    private final Animation mSlideUpOutAnimation;
-    private final Animation mSlideUpInAnimation;
-    private final Animation mSlideDownOutAnimation;
-    private final Animation mSlideDownInAnimation;
-    
+
     private String[] mDisplayedValues;
     private int mStart;
     private int mEnd;
@@ -110,14 +99,14 @@ public class NumberPicker extends LinearLayout implements OnClickListener,
         this(context, attrs, 0);
     }
 
-    public NumberPicker(Context context, AttributeSet attrs,
-            int defStyle) {
+    @SuppressWarnings({"UnusedDeclaration"})
+    public NumberPicker(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs);
         setOrientation(VERTICAL);
-        mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);        
-        mInflater.inflate(R.layout.number_picker, this, true);
+        LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        inflater.inflate(R.layout.number_picker, this, true);
         mHandler = new Handler();
-        mInputFilter = new NumberPickerInputFilter();
+        InputFilter inputFilter = new NumberPickerInputFilter();
         mNumberInputFilter = new NumberRangeKeyListener();
         mIncrementButton = (NumberPickerButton) findViewById(R.id.increment);
         mIncrementButton.setOnClickListener(this);
@@ -130,30 +119,9 @@ public class NumberPicker extends LinearLayout implements OnClickListener,
         
         mText = (TextView) findViewById(R.id.timepicker_input);
         mText.setOnFocusChangeListener(this);
-        mText.setFilters(new InputFilter[] { mInputFilter });
+        mText.setFilters(new InputFilter[] {inputFilter});
         mText.setRawInputType(InputType.TYPE_CLASS_NUMBER);
-        
-        mSlideUpOutAnimation = new TranslateAnimation(
-                Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF,
-                0, Animation.RELATIVE_TO_SELF, 0,
-                Animation.RELATIVE_TO_SELF, -100);
-        mSlideUpOutAnimation.setDuration(200);
-        mSlideUpInAnimation = new TranslateAnimation(
-                Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF,
-                0, Animation.RELATIVE_TO_SELF, 100,
-                Animation.RELATIVE_TO_SELF, 0);
-        mSlideUpInAnimation.setDuration(200);
-        mSlideDownOutAnimation = new TranslateAnimation(
-                Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF,
-                0, Animation.RELATIVE_TO_SELF, 0,
-                Animation.RELATIVE_TO_SELF, 100);
-        mSlideDownOutAnimation.setDuration(200);
-        mSlideDownInAnimation = new TranslateAnimation(
-                Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF,
-                0, Animation.RELATIVE_TO_SELF, -100,
-                Animation.RELATIVE_TO_SELF, 0);
-        mSlideDownInAnimation.setDuration(200);
-        
+
         if (!isEnabled()) {
             setEnabled(false);
         }
@@ -228,9 +196,9 @@ public class NumberPicker extends LinearLayout implements OnClickListener,
 
         // now perform the increment/decrement
         if (R.id.increment == v.getId()) {
-            changeCurrent(mCurrent + 1, mSlideUpInAnimation, mSlideUpOutAnimation);
+            changeCurrent(mCurrent + 1);
         } else if (R.id.decrement == v.getId()) {
-            changeCurrent(mCurrent - 1, mSlideDownInAnimation, mSlideDownOutAnimation);
+            changeCurrent(mCurrent - 1);
         }
     }
     
@@ -240,7 +208,7 @@ public class NumberPicker extends LinearLayout implements OnClickListener,
                 : String.valueOf(value);
     }
  
-    private void changeCurrent(int current, Animation in, Animation out) {
+    private void changeCurrent(int current) {
         
         // Wrap around the values if we go past the start or end
         if (current > mEnd) {
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 307c6fdd89c9..288433af6a0d 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -267,7 +267,7 @@ static void android_media_AudioRecord_finalize(JNIEnv *env,  jobject thiz) {
             (AudioRecord *)env->GetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj);
 
     if (lpRecorder) {
-        //LOGV("About to delete lpRecorder: %x\n", (int)lpRecorder);
+        LOGV("About to delete lpRecorder: %x\n", (int)lpRecorder);
         lpRecorder->stop();
         delete lpRecorder;
     }
@@ -448,6 +448,39 @@ static jint android_media_AudioRecord_get_pos_update_period(JNIEnv *env,  jobjec
 }
 
 
+// ----------------------------------------------------------------------------
+// returns the minimum required size for the successful creation of an AudioRecord instance.
+// returns 0 if the parameter combination is not supported.
+// return -1 if there was an error querying the buffer size.
+static jint android_media_AudioRecord_get_min_buff_size(JNIEnv *env,  jobject thiz,
+    jint sampleRateInHertz, jint nbChannels, jint audioFormat) {
+    
+    size_t inputBuffSize = 0;
+    LOGV(">> android_media_AudioRecord_get_min_buff_size(%d, %d, %d)", sampleRateInHertz, nbChannels, audioFormat);
+    
+    status_t result = AudioSystem::getInputBufferSize(
+                        sampleRateInHertz, 
+                        (audioFormat == javaAudioRecordFields.PCM16 ? 
+                            AudioSystem::PCM_16_BIT : AudioSystem::PCM_8_BIT), 
+                        nbChannels, &inputBuffSize);
+    switch(result) {
+    case(NO_ERROR):
+        if(inputBuffSize == 0) {
+            LOGV("Recording parameters are not supported: %dHz, %d channel(s), (java) format %d",
+                sampleRateInHertz, nbChannels, audioFormat);
+            return 0;
+        } else {
+            // the minimum buffer size is twice the hardware input buffer size
+            return 2*inputBuffSize;
+        }
+        break;
+    case(PERMISSION_DENIED):
+    default:
+        return -1; 
+    }
+}
+
+
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 static JNINativeMethod gMethods[] = {
@@ -470,6 +503,8 @@ static JNINativeMethod gMethods[] = {
                              "(I)I",   (void *)android_media_AudioRecord_set_pos_update_period},
     {"native_get_pos_update_period",
                              "()I",    (void *)android_media_AudioRecord_get_pos_update_period},
+    {"native_get_min_buff_size",
+                             "(III)I",   (void *)android_media_AudioRecord_get_min_buff_size},
 };
 
 // field names found in android/media/AudioRecord.java
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 6bd365519567..692610ea42cc 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -53,13 +53,8 @@ static int
 android_media_AudioSystem_setVolume(JNIEnv *env, jobject clazz, jint type, jint volume)
 {
     LOGV("setVolume(%d)", int(volume));
-    if (int(type) == AudioTrack::VOICE_CALL) {
-        return check_AudioSystem_Command(AudioSystem::setStreamVolume(type, float(volume) / 100.0));
-    } else if (int(type) == AudioTrack::BLUETOOTH_SCO) {
-        return check_AudioSystem_Command(AudioSystem::setStreamVolume(type, float(1.0)));
-    } else {
-        return check_AudioSystem_Command(AudioSystem::setStreamVolume(type, AudioSystem::linearToLog(volume)));
-    }
+    
+    return check_AudioSystem_Command(AudioSystem::setStreamVolume(type, AudioSystem::linearToLog(volume)));
 }
 
 static int
@@ -68,12 +63,7 @@ android_media_AudioSystem_getVolume(JNIEnv *env, jobject clazz, jint type)
     float v;
     int v_int = -1;
     if (AudioSystem::getStreamVolume(int(type), &v) == NO_ERROR) {
-        // voice call volume is converted to log scale in the hardware
-        if (int(type) == AudioTrack::VOICE_CALL) {
-            v_int = lrint(v * 100.0);
-        } else {
-            v_int = AudioSystem::logToLinear(v);
-        }
+        v_int = AudioSystem::logToLinear(v);
     }
     return v_int;
 }
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index bbecc1b6a0cf..6ca821d2fca5 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -72,6 +72,7 @@ class AudioTrackJniStorage {
         sp<MemoryHeapBase>         mMemHeap;
         sp<MemoryBase>             mMemBase;
         audiotrack_callback_cookie mCallbackData;
+        int                        mStreamType;
 
     AudioTrackJniStorage() {
     }
@@ -168,11 +169,11 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
     int afSampleRate;
     int afFrameCount;
 
-    if (AudioSystem::getOutputFrameCount(&afFrameCount) != NO_ERROR) {
+    if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
         LOGE("Error creating AudioTrack: Could not get AudioSystem frame count.");
         return AUDIOTRACK_ERROR_SETUP_AUDIOSYSTEM;
     }
-    if (AudioSystem::getOutputSamplingRate(&afSampleRate) != NO_ERROR) {
+    if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
         LOGE("Error creating AudioTrack: Could not get AudioSystem sampling rate.");
         return AUDIOTRACK_ERROR_SETUP_AUDIOSYSTEM;
     }
@@ -183,21 +184,21 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
     }
     
     // check the stream type
-    AudioTrack::stream_type atStreamType;
+    AudioSystem::stream_type atStreamType;
     if (streamType == javaAudioTrackFields.STREAM_VOICE_CALL) {
-        atStreamType = AudioTrack::VOICE_CALL;
+        atStreamType = AudioSystem::VOICE_CALL;
     } else if (streamType == javaAudioTrackFields.STREAM_SYSTEM) {
-        atStreamType = AudioTrack::SYSTEM;
+        atStreamType = AudioSystem::SYSTEM;
     } else if (streamType == javaAudioTrackFields.STREAM_RING) {
-        atStreamType = AudioTrack::RING;
+        atStreamType = AudioSystem::RING;
     } else if (streamType == javaAudioTrackFields.STREAM_MUSIC) {
-        atStreamType = AudioTrack::MUSIC;
+        atStreamType = AudioSystem::MUSIC;
     } else if (streamType == javaAudioTrackFields.STREAM_ALARM) {
-        atStreamType = AudioTrack::ALARM;
+        atStreamType = AudioSystem::ALARM;
     } else if (streamType == javaAudioTrackFields.STREAM_NOTIFICATION) {
-        atStreamType = AudioTrack::NOTIFICATION;
+        atStreamType = AudioSystem::NOTIFICATION;
     } else if (streamType == javaAudioTrackFields.STREAM_BLUETOOTH_SCO) {
-        atStreamType = AudioTrack::BLUETOOTH_SCO;
+        atStreamType = AudioSystem::BLUETOOTH_SCO;
     } else {
         LOGE("Error creating AudioTrack: unknown stream type.");
         return AUDIOTRACK_ERROR_SETUP_INVALIDSTREAMTYPE;
@@ -238,6 +239,8 @@ android_media_AudioTrack_native_setup(JNIEnv *env, jobject thiz, jobject weak_th
     // we use a weak reference so the AudioTrack object can be garbage collected.
     lpJniStorage->mCallbackData.audioTrack_ref = env->NewGlobalRef(weak_this);
     
+    lpJniStorage->mStreamType = atStreamType;
+    
     // create the native AudioTrack object
     AudioTrack* lpTrack = new AudioTrack();
     if (lpTrack == NULL) {
@@ -656,8 +659,14 @@ static jint android_media_AudioTrack_reload(JNIEnv *env,  jobject thiz) {
 
 // ----------------------------------------------------------------------------
 static jint android_media_AudioTrack_get_output_sample_rate(JNIEnv *env,  jobject thiz) {
-    int afSamplingRate;
-    if (AudioSystem::getOutputSamplingRate(&afSamplingRate) != NO_ERROR) {
+    int afSamplingRate;    
+    AudioTrackJniStorage* lpJniStorage = (AudioTrackJniStorage *)env->GetIntField(
+        thiz, javaAudioTrackFields.jniData);
+    if (lpJniStorage == NULL) {
+        return DEFAULT_OUTPUT_SAMPLE_RATE;
+    }
+
+    if (AudioSystem::getOutputSamplingRate(&afSamplingRate, lpJniStorage->mStreamType) != NO_ERROR) {
         return DEFAULT_OUTPUT_SAMPLE_RATE;
     } else {
         return afSamplingRate;
diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
index 75a0fbee23eb..e5ae2ea19bea 100644
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ b/core/jni/android_server_BluetoothEventLoop.cpp
@@ -751,6 +751,10 @@ void onCreateBondingResult(DBusMessage *msg, void *user) {
             // Other device is not responding at all
             LOGV("... error = %s (%s)\n", err.name, err.message);
             result = BOND_RESULT_REMOTE_DEVICE_DOWN;
+        } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AlreadyExists")) {
+            // already bonded
+            LOGV("... error = %s (%s)\n", err.name, err.message);
+            result = BOND_RESULT_SUCCESS;
         } else {
             LOGE("%s: D-Bus error: %s (%s)\n", __FUNCTION__, err.name, err.message);
             result = BOND_RESULT_ERROR;
diff --git a/core/jni/android_util_EventLog.cpp b/core/jni/android_util_EventLog.cpp
index d0cac183ab67..5e5103a2fabe 100644
--- a/core/jni/android_util_EventLog.cpp
+++ b/core/jni/android_util_EventLog.cpp
@@ -19,7 +19,7 @@
 #include "JNIHelp.h"
 #include "android_runtime/AndroidRuntime.h"
 #include "jni.h"
-#include "utils/logger.h"
+#include "cutils/logger.h"
 
 #define END_DELIMITER '\n'
 #define INT_BUFFER_SIZE (sizeof(jbyte)+sizeof(jint)+sizeof(END_DELIMITER))
diff --git a/core/res/res/drawable/presence_away.png b/core/res/res/drawable/presence_away.png
index a539ec7787190c1e5aa5627bf388478de8c7fbfe..f8120df43bfe56831686901c2aeed0d15f693f4e 100644
GIT binary patch
delta 787
zcmV+u1MK{)8>$A7B!3xnMObuGZ)S9NVRB^vL1b@YWgtmyVP|DhWnpA_ami&o0008a
zNkl<Zc-pK~KTH#06#v~_uf1zaX)&e6n5F@u(t$}MHgSc`6;0S2Ab^uBLUeJ(4G1QV
zIIz0WMH3TZ!hm)tBm`2r=*gdyqkrytZO`}a@Bk$)`X#UT<$wMD^n35#cY<x(_#ex6
zRdRB2a#&T>kw74j_4#}QoNG3lTc&BQ*X#AQrKP3Z?;7Fai6$l{($Q#iI*~|>$K&yE
zBoYA`Iv5#1*L55m98@$-ds8l#7nYZoi+>nRO--fA;8kB=-&iV@Ld5t4d|ySQyzSur
z=xrc53SD`CQh%w0-QC?4GJLVPxLCYYS~8iO&SWxUy{ROW!Zg%I0jAkN=Fw*d-&-9*
zz}SZ0pFudY07X&81VPXUnqgezpV`^j;r{;qaSEuLPtj5Nf{0Io(gq~B!F$dz#vJCd
zhP9qiPfyQCI-L#&wGU7ZHxZ<2)wT_#MYXpr2ypkDV}H!y5SKNq^^Cf^yR%(gU9j`-
zAR2&i1nA!kRDY0>RU<PS66NKF1-}IZ$dtLPVXfDrSS&UW3<goxc0gR*nEOfwrx1j*
z21+3aCYd%`5DAwkpznY+to4jSp%7?hP-_5f3L$izUZ-_FB%%z7O0v)Jw(0I!!&=XX
zy1ylg;(w4Gy$Shf1EuG2NYr5tK9wv}e-ywXv1PhX=90$IdOhNaZM9lZ?>})$ll?$A
z40J@?P-rIG4vz+tdR48#;j)Icp3%w4$r>dpvFu|suHAutN-d}Y6^d%z4c>E(G3GFr
zHLSff+4+2ao+kR4&@`|&{}9kNs0VI&yy(xJ6MrFb7ris@Vfz%G@YjQbgXaUuYkz-#
zf$q<W7zp9k%a4eTzD2e39uBLWPVk;{j4_9~tnpq5pXgWQa=CP|Se&QJd0MO0?5lz?
z<}ml7R=DbWR45dNY1l^SK4oQDcIL#gtS!SZ){l>m*XU0E{WJ0}>!$z%0B1FJsZO4P
R{R{vA002ovPDHLkV1jNxeck{7

delta 3498
zcmV;b4OQ~02CN&9B!3BTNLh0L01FcU01FcV0GgZ_000V4X+uL$P-t&-Z*ypGa3D!T
zLm+T+Z)Rz1WdHzp+MQEpR8#2|J@?-9LQ9B%luK_?6$l_wLW_VDktQl32@pz%A)(n7
zQNa;KMFbnjpojyGj)066Q7jCK3fKqaA)=0hqlk*i`{8?|Yk$_f_vX$1wbwr9tn;0-
z&j-K=43<bUQ8j=JsX`tR;Dg7+#^K~HK!FM*Z~zbpvt%K2{UZSY_<lS*D<Z%Lz5oGu
z(+dayz)hRLFdT>f59&ghTmgWD0l;*TI7<kC6aYYajzXpYKt=(8otP$50H6c_V9R4-
z;{Z@C0AMG7=6}-wfSvf6djSAjlpz%XppgI|6J>}*0BAb^tj|`8MF3bZ02F3R#5n-i
zEdVe{S7t~6u(trf&JYW-00;~KFj0twDF6g}0AR=?BX|IWnE(_<@>e|ZE3OddDgXd@
znX){&BsoQaTL>+22Uk}v9w^R97b_GtVFF>AKrX_0nSU8Ffiw@`^UMGMppg|3;Dhu1
zc+L*4&dxTDwhmt{>c0m6B4T3W{^ifBa6kY6;dFk{{wy!E8h|?nfNlPwCGG@hUJIag
z_lst-4?wj5py}FI^KkfnJUm6Akh$5}<>chpO2k52Vaiv1{%68pz*qfj`F=e7_x0eu
z;v|7GU4MZ`1o+^>%=Ap99M6&ogks$0k4OBs3;+Bb(;~!4V!2o<6ys46agIcqjPo+3
zB8fthDa9qy|77CdEc*jK-!%ZRYCZvbku9iQV*~a}ClFY4z~c7+0P?$U!PF=S1Au6Q
z;m>#f??3%Vpd|o+W=WE9003S@Bra6Svp>fO0Dk~Ppn)o|K^yeJ7%adB9Ki+L!3+Fg
zHiSYX#KJ-lLJDMn9CBbOtb#%)hRv`YDqt_vKpix|QD}yfa1JiQRk#j4a1Z)n2%f<x
zynzV>LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxWizFb)h!jyGOOZ85F;a?DAXP{m@;!0_
zIe&*-M!JzZ$N(~e{D!<oF_eL_Q9aZQwL`h6HyVUSq6^SubTOKb7NDEZa<m#fj5eX?
z(5q+<+K)a%$1uR?7zZ=NY%ngy!$Pq*ED4ii%dsM?46DW(uvV-CyNUH<&#`v|5`jg)
z2{r_GLLgxtK}c9kSWehTs3069G!fbfH-8BOgi*pLB9o{~v?jU{`NSAvGBJl(NGv1P
z5|0xv5POJ2#5W`oi9<3cxsU=$v7}Ve64FM}Zc-!ZEUB9`NE#!P$=YOVvIjYoEFde$
zh2)*&!{jsM8{{GKTMC_GKyjq_Q{pI6%4$j(<q+jG<pyP#GC@_Nno`}Up;QqykAGT1
zt)aG3uTh7n6Et<2In9F>NlT@zqLtGcXcuVrX|L#Xx)I%#9!{6gSJKPrN9dR61N3(c
z4Tcqi$B1Vr8Jidf7-t!G7_XR2rWw<V8OKyGH!<s&=a~<gZ&g?-wkmuTk;)2{N|h#+
z8!9hUsj8-`-l_{#^Hs}KkEvc$eSfY-RWnoLsR`7Ut5vF<Q0r40Q)j6=sE4X&sBct1
zq<&fbi3VB2Ov6t@q*0);U*o*SAPZv|vv@2aYYnT0b%8a+Cb7-ge0D0knEf5Qi#@8T
zp*ce{N;6lpQuCB%KL_KOarm5cP6_8Ir<e17iry6ODdH&`rZh~sF=bq9s(+T3mRPGu
zt5K^*>%BIv?Wdily+ylO`+*KY$4Vz$Cr4+G&IO(4Q`uA9rwXSQO+7mGt}d!;r5mBU
zM0dY#r|y`ZzFvTyOmC;&dA;ZQ9DOhSRQ+xGr}ak+SO&8UBnI0I&KNw!HF0k|9WTe*
z@liuv!$3o&VU=N*;e?U7(SJOn)kcj*4~%KXT;n9;ZN_cJqb3F>Atp;r>P_yNQcbz0
zDW*G2J50yT%*~?B)|oY%Ju%lZ=bPu7*PGwBU|M)uEVih&xMfMQ<XWa#?zX&cg<3gT
zrC3#3U9(25ovkI-yREyY5vRFMlTNFi)@Q@8@wUmfska%h<=6(>u79>|wtZn|Vi#w(
z#jeBdlf9FDx_yoPJqHbk*$%56S{;6Kv~m<WRyy9A&YbQ)eZ};a=`Uwk&k)bpGvl@s
z%PGWZol~3BM`ssjxpRZ_h>M9!g3B(KJ}#RZ#@)!h<Vtk)ab4kh()FF2vzx;0sN1jZ
zHtuQehuojcG@mJ+S${Kg(8I_>;8Eq#KMS9gFl*neeosSBfoHYnBQIkwkyowPu(zdm
zs`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMeBmZRodjHV?r+_5^X9J0W
zL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0?0=B0A@}E)&XLY(4uw#D
z=+@8&Vdi0r!+s1Wg@=V#hChyQh*%oYF_$%W(cD9G-$eREmPFp0XE9GXuPsV7Dn6<%
zYCPIEx-_~!#x7=A%+*+(SV?S4962s3t~PFLzTf=q^M~S{;tS(@7nm=|U2u7!&cgJC
zrxvL$5-d8FKz~e#PB@hCK@cja7K|nG6L%$!3VFgE!e=5c(KgYD*h5?@9!~N|DouKl
z?2)`Rc_hU%r7Y#SgeR$xyi5&D-J3d|7MgY-Z8AMNy)lE5k&tmhsv%92wrA>R=4N)w
ztYw9={>5&Kw=W)*2gz%*kgNq+Eef_mrsz~!DAy_nvVUh~S7yJ>iOM;atDY;(?aZ^v
z+mJV$@1Ote62cPUlD4IWOIIx&SmwQ~YB{nzae3Pc;}r!fhE@iwJh+OsDs9zItL;~p
zu715HdQEGAUct(O!L<Qv>kCy1<%NCg+}G`0PgpNm-?d@-hMgNe6^V+j6x$b<6@S<$
z+<4_1hktL%znR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX4c}I@?e+FW+b@^R
zDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i&_B8C(+grT%{XWUQ
z+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?SIDu(gXbmBM!FLxzyDi(mhmCkJc;e
zM-ImyzW$x>cP$Mz4ONYt#^NJzM0w=t_X*$k9t}F$c8q(h;Rn+nb{%IOFKR-X@|s4Q
zQ=0o*Vq3aT%s$c9>fU<%N829{oHRUHc}nwC$!Xf@g42^{^3RN&m7RTlF8SPG+oHC6
z=YM0)-)awU@466l;nGF_i|0GMJI-A4xODQe+vO8ixL2C5I$v$-bm~0*lhaSfyPUh4
zuDM)mx$b(swR>jw=^LIm&fWCAdGQwi*43UlJ>9+YdT;l|_x0Zv-F|W>{m#p~*>@-I
zt-MdXU-UrjLD@syht)q@{@mE_+<$7ocYmPs(cDM(28Dyq{*m>M4?_iynUBkc4TkHU
zI6gT!;y-fz>HMcd&t%Ugo)`Y2{>!cx7B7DI)$7;J(U{Spm-3gBzioV_{p!H$8L!*M
z!p0uH$#^p{Ui4P`?ZJ24cOCDe-w#jZd?0@)|7iKK^;6KN`;!@ylm7$*nDhK&Gk-1H
z0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F}0008lNkl<Z
zc-oAVF=!lD5QaZpws<Sn@D?O;59=TcS7cQLEE0iT#GF8dgG!koLy919lOv=!+(hM7
zK?D<&A_5aI7!^_zP*TL$*SSz}mw)P1<X{C#cm^HW1#h$i+GJDQN?9om$q&QNFmLAl
zGrTubMNv>i`+j>G#fnm@r5v^BI&L!~gPf7%av&l-g#E4Ut<!4WRJBn1)Aq8~`o1w{
z)z?1S(<o0t4w4H=k`Rw$?1|k=l4N`9tF5R1DAak-Su@6Lgl~oO#wY^k2Y(b1Dz^X#
z25|x+J|H?yh>oJ6J+|G=FE@8C3UwZImcvH)FnBwd4`vgBv<qhfIpA;wn#k`EooEh6
zhr=j}KHL0a^XVJuZ|SsYm~Qw^czgcMgvPI*!08|GXFjp_z60|i9DM`%6yzy>`Xlc3
z_hGs*oBy7>k9Qt_@A$L+N`Kf4SA$s>{d2oik%3GaqHK&5AiMDE(FSqw1ZkR88z;L?
zy<Tq_WAIPDMx_y;$^s?l=efz{m_!68kC4VX<`>(l`7{2a)*3zTPtJ&xoLp8VQi+v3
zeu4HhrfwD;?dhiLxiCJ2T&@hZs;JuP1Zo`NDi`hPrsH07!I``ja(`g0&ueiWcPfm4
zQn=S#Y6?aG;)Q?TUR6}Gl(8y{7osNa$cZx!0%U=i1?1%bzFpwoAXk`~1q8^l?4TxT
z+!F!0`8lXM!vBP-PjW<%RC=`}N%rG3-ox>cJC9I#Df_?d&J%Ea;xyi~W4m9w_tCvm
zYwfm(4AtBca`zdiI)9w;dQ)}O-Dfa&3lSMwYq!@wUO&C~w1b}pYi7=DXr<@L6QtKg
zUcP{FRL&zn&D}!X+(0}HX)=tCZ1={yH+BFhisHihgZ{F$b~k&K6<L-QSymL;S;^=A
ztE{lr?)C@$<!bKK)y4L__k21Cf)&?uTgp+3N~tC}2r?3pgCi`7d(pAoUurE~T5Nv}
Y0K%=D^~TEWAOHXW07*qoM6N<$g4pAjU;qFB

diff --git a/core/res/res/drawable/presence_busy.png b/core/res/res/drawable/presence_busy.png
index 1e3f547b8cd31c98c022f9d05392db678e54a2f0..9d7620b1d0c8d50f4e86df6743d11fd6b8558ab8 100644
GIT binary patch
delta 788
zcmV+v1MB?B8><G8B!3xnMObuGZ)S9NVRB^vL1b@YWgtmyVP|DhWnpA_ami&o0008b
zNkl<Zc-pK~Jxo(k6#m{%ef^_ALraU1Jfy*Z2}&YjNE}QIjf*1*37Z3i5*M9Fm`I#(
zF+d=3#6>5aq%qNng+ze?f&^2#U_-5Ksr0q4kLNj8C?M#f_kZRzx95D{_wKpxyHB!h
z8~<ad=Osr*M*3VXS5(uqUR71wIajGv)=Q<*VzF3Un3<W0|IU$4?r3;;Sg)(A8*OZC
z90~*iUZ2kg5)?HOKt7+x?(S|Ol}gQJv)QTH+1bPyp;#=YlfXo4YwKWhb2Gf3K0|rG
z1ZgKN>UOvR)_<LD6uR1wOeV3lwKY$I<I~gAiBqkGLZQ))j*h|0p(d!~bI=lBp<U3R
zD2k|C*&UQtUP0AE@J<ZD>2wZCl9Zy-W3J2mGd4EX7l}lMD4;%k2G4R5K2t?aS%J4K
zi{LfqxW*X9GKaa<9fiZ;sIKc?C%5u(6K)rsjcmhV9)CcRf3<EO*ib68Ht669V-r^I
zx#~@)(@`qNg-|dU?DhNosJwU$4P_X`?=XvbC^RLSLWrhyIAw|wVg2`R3vP8s_4W1b
zZnqox%`YVL11&4>Anh4dk)y$4c8wDo*X{y@We#(zLLQF?<QaO7N&iepO%0Gt>x{pI
ztV2QN5P!!U=2nI1^w(uszID)c3ChwYHUeFutv|IUQQjgfaRj&e*4VL@Wx@MkfX=c)
zNexcazy%-Ns1?C$&T)+~jAagUt3tV4Zh;bo;6OjhHzLTOfGnL=4&>&;;5FyC#u&yj
zhq<Smy}G(ONsfL5!@%<WeppKz^lVMECk)ANihrikeFfLwyaYLt9sablv-8-HJhr#D
zr|AC7D|C1_KfJ}o=TBhtwBTE<DT3FW;~HZa%bep^N;^7=cs#Br5{XH=oO}EG`}TRk
zHO4UZBv(4`d$hK;)<*`7(tYZ6I2^(!rfIGlhOwB*WESX7{{1uZFXN{G0{|WcZ$>>6
SI}P~&0000<MNUMnLSTaA*nHmr

delta 3527
zcmV;&4LI_v2FV+cB!3BTNLh0L01FcU01FcV0GgZ_000V4X+uL$P-t&-Z*ypGa3D!T
zLm+T+Z)Rz1WdHzp+MQEpR8#2|J@?-9LQ9B%luK_?6$l_wLW_VDktQl32@pz%A)(n7
zQNa;KMFbnjpojyGj)066Q7jCK3fKqaA)=0hqlk*i`{8?|Yk$_f_vX$1wbwr9tn;0-
z&j-K=43<bUQ8j=JsX`tR;Dg7+#^K~HK!FM*Z~zbpvt%K2{UZSY_<lS*D<Z%Lz5oGu
z(+dayz)hRLFdT>f59&ghTmgWD0l;*TI7<kC6aYYajzXpYKt=(8otP$50H6c_V9R4-
z;{Z@C0AMG7=6}-wfSvf6djSAjlpz%XppgI|6J>}*0BAb^tj|`8MF3bZ02F3R#5n-i
zEdVe{S7t~6u(trf&JYW-00;~KFj0twDF6g}0AR=?BX|IWnE(_<@>e|ZE3OddDgXd@
znX){&BsoQaTL>+22Uk}v9w^R97b_GtVFF>AKrX_0nSU8Ffiw@`^UMGMppg|3;Dhu1
zc+L*4&dxTDwhmt{>c0m6B4T3W{^ifBa6kY6;dFk{{wy!E8h|?nfNlPwCGG@hUJIag
z_lst-4?wj5py}FI^KkfnJUm6Akh$5}<>chpO2k52Vaiv1{%68pz*qfj`F=e7_x0eu
z;v|7GU4MZ`1o+^>%=Ap99M6&ogks$0k4OBs3;+Bb(;~!4V!2o<6ys46agIcqjPo+3
zB8fthDa9qy|77CdEc*jK-!%ZRYCZvbku9iQV*~a}ClFY4z~c7+0P?$U!PF=S1Au6Q
z;m>#f??3%Vpd|o+W=WE9003S@Bra6Svp>fO0Dk~Ppn)o|K^yeJ7%adB9Ki+L!3+Fg
zHiSYX#KJ-lLJDMn9CBbOtb#%)hRv`YDqt_vKpix|QD}yfa1JiQRk#j4a1Z)n2%f<x
zynzV>LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxWizFb)h!jyGOOZ85F;a?DAXP{m@;!0_
zIe&*-M!JzZ$N(~e{D!<oF_eL_Q9aZQwL`h6HyVUSq6^SubTOKb7NDEZa<m#fj5eX?
z(5q+<+K)a%$1uR?7zZ=NY%ngy!$Pq*ED4ii%dsM?46DW(uvV-CyNUH<&#`v|5`jg)
z2{r_GLLgxtK}c9kSWehTs3069G!fbfH-8BOgi*pLB9o{~v?jU{`NSAvGBJl(NGv1P
z5|0xv5POJ2#5W`oi9<3cxsU=$v7}Ve64FM}Zc-!ZEUB9`NE#!P$=YOVvIjYoEFde$
zh2)*&!{jsM8{{GKTMC_GKyjq_Q{pI6%4$j(<q+jG<pyP#GC@_Nno`}Up;QqykAGT1
zt)aG3uTh7n6Et<2In9F>NlT@zqLtGcXcuVrX|L#Xx)I%#9!{6gSJKPrN9dR61N3(c
z4Tcqi$B1Vr8Jidf7-t!G7_XR2rWw<V8OKyGH!<s&=a~<gZ&g?-wkmuTk;)2{N|h#+
z8!9hUsj8-`-l_{#^Hs}KkEvc$eSfY-RWnoLsR`7Ut5vF<Q0r40Q)j6=sE4X&sBct1
zq<&fbi3VB2Ov6t@q*0);U*o*SAPZv|vv@2aYYnT0b%8a+Cb7-ge0D0knEf5Qi#@8T
zp*ce{N;6lpQuCB%KL_KOarm5cP6_8Ir<e17iry6ODdH&`rZh~sF=bq9s(+T3mRPGu
zt5K^*>%BIv?Wdily+ylO`+*KY$4Vz$Cr4+G&IO(4Q`uA9rwXSQO+7mGt}d!;r5mBU
zM0dY#r|y`ZzFvTyOmC;&dA;ZQ9DOhSRQ+xGr}ak+SO&8UBnI0I&KNw!HF0k|9WTe*
z@liuv!$3o&VU=N*;e?U7(SJOn)kcj*4~%KXT;n9;ZN_cJqb3F>Atp;r>P_yNQcbz0
zDW*G2J50yT%*~?B)|oY%Ju%lZ=bPu7*PGwBU|M)uEVih&xMfMQ<XWa#?zX&cg<3gT
zrC3#3U9(25ovkI-yREyY5vRFMlTNFi)@Q@8@wUmfska%h<=6(>u79>|wtZn|Vi#w(
z#jeBdlf9FDx_yoPJqHbk*$%56S{;6Kv~m<WRyy9A&YbQ)eZ};a=`Uwk&k)bpGvl@s
z%PGWZol~3BM`ssjxpRZ_h>M9!g3B(KJ}#RZ#@)!h<Vtk)ab4kh()FF2vzx;0sN1jZ
zHtuQehuojcG@mJ+S${Kg(8I_>;8Eq#KMS9gFl*neeosSBfoHYnBQIkwkyowPu(zdm
zs`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMeBmZRodjHV?r+_5^X9J0W
zL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0?0=B0A@}E)&XLY(4uw#D
z=+@8&Vdi0r!+s1Wg@=V#hChyQh*%oYF_$%W(cD9G-$eREmPFp0XE9GXuPsV7Dn6<%
zYCPIEx-_~!#x7=A%+*+(SV?S4962s3t~PFLzTf=q^M~S{;tS(@7nm=|U2u7!&cgJC
zrxvL$5-d8FKz~e#PB@hCK@cja7K|nG6L%$!3VFgE!e=5c(KgYD*h5?@9!~N|DouKl
z?2)`Rc_hU%r7Y#SgeR$xyi5&D-J3d|7MgY-Z8AMNy)lE5k&tmhsv%92wrA>R=4N)w
ztYw9={>5&Kw=W)*2gz%*kgNq+Eef_mrsz~!DAy_nvVUh~S7yJ>iOM;atDY;(?aZ^v
z+mJV$@1Ote62cPUlD4IWOIIx&SmwQ~YB{nzae3Pc;}r!fhE@iwJh+OsDs9zItL;~p
zu715HdQEGAUct(O!L<Qv>kCy1<%NCg+}G`0PgpNm-?d@-hMgNe6^V+j6x$b<6@S<$
z+<4_1hktL%znR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX4c}I@?e+FW+b@^R
zDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i&_B8C(+grT%{XWUQ
z+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?SIDu(gXbmBM!FLxzyDi(mhmCkJc;e
zM-ImyzW$x>cP$Mz4ONYt#^NJzM0w=t_X*$k9t}F$c8q(h;Rn+nb{%IOFKR-X@|s4Q
zQ=0o*Vq3aT%s$c9>fU<%N829{oHRUHc}nwC$!Xf@g42^{^3RN&m7RTlF8SPG+oHC6
z=YM0)-)awU@466l;nGF_i|0GMJI-A4xODQe+vO8ixL2C5I$v$-bm~0*lhaSfyPUh4
zuDM)mx$b(swR>jw=^LIm&fWCAdGQwi*43UlJ>9+YdT;l|_x0Zv-F|W>{m#p~*>@-I
zt-MdXU-UrjLD@syht)q@{@mE_+<$7ocYmPs(cDM(28Dyq{*m>M4?_iynUBkc4TkHU
zI6gT!;y-fz>HMcd&t%Ugo)`Y2{>!cx7B7DI)$7;J(U{Spm-3gBzioV_{p!H$8L!*M
z!p0uH$#^p{Ui4P`?ZJ24cOCDe-w#jZd?0@)|7iKK^;6KN`;!@ylm7$*nDhK&Gk-1H
z0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F}0008?Nkl<Z
zc-n-NPiS0K6vlr^9&%ooz<YEC=7|9ZM{ourCfb2)lnG>Gvryxv6gLW84aG&sq67p<
zHxi0SR>iuAU>1!5A-V}<mW2c}!GFjk(t%fK;R+V#f{%Fzdds-TIDN7Hxp4SC4)^=c
zx#x24NWb4FyBb#;;|L2PQWsBZzUP-yQgC$C>AtEqQFhjEt@pCJk*rbUT4O#4f~!#!
zy&nc4K`uaY0uIzE)>^ucx|rY0mbLcQ`WNfF&loK&FI|qJXr=OEr5Xi7>3=AO*do>d
z0(l>uEE2y~CANn6e%v+>%<9_BwauZ?((=-LWwP>l>6KEoq!4}m16V~oPzQK`8<Y+N
z^TFH1IXF2zX~*~CkJoOl?T#hCC*#p%v|4$!@>aD6g->sTeFDzm5{G25=a5A4o5xJd
zPQmkqLXtXvdvoLau}ce=-hZ8{PJQz7g#v};ufRG)9j=!k3ffCR!DUbsydO{T-gy&!
z&Q+5?^e3-aEY_naBHY-6huw2Gs3-t3V1J>aV3lxVkJ5*8n1|iE7v{rS5Cq8Gle4+N
zK+ceBhG+9~5EEPrh>Bs&3vxl(&-rj_KoweFA{nVXm7U8o-GHBC{C}KJkPFJA{)7)+
zww|I+!0FkI{UZvHo^AKQpYZVnIs!9VF2YfaPJfh{(bHqubF&-tRgMN7(;4li>?;Zv
zXPz<mH$Kc=te_}qn(mKk(rw~^>+hlY@IMX6Vljm4S3p4%ZH`)NcDlB^MGzt1tdOFl
z@V_V<E07nuNq5UUGJiW`-)?{R__%d!!wVCydoM)=zg|Ok56~pR;o;$-C=S6xp%@Wv
z-+<X^G)da=z4*rB;^HsEN837TT`s*)T0x{L)?z-p4R_nv&aVh5luO9$4AJrxG#@}>
z+b8$U>g*fSn*j9t{b3xo4(E+AchWTN594uv!283TG3L(U!9d}BRy*?dk8Q8HH(r`7
zE%<?77f)&;QU*}f4o>%tO`GOHyfasyJNL2uIRHAEyq1No74iT8002ovPDHLkV1oa<
Bt1JKj

diff --git a/core/res/res/drawable/presence_invisible.png b/core/res/res/drawable/presence_invisible.png
index fb86cf128342148d45bb0c74b8b015cddedd1152..21399a4f3618f0e6549016cd7b53e75767029de6 100644
GIT binary patch
delta 632
zcmV-;0*C#)2(<-}NPhxXNkl<Zc-pK~$%<N05H07a5eJ+$`anV2g}4lUfcg<Gg%)jB
z$*Li%Y&*MF47lu{&=2SjaG@ZI!%7inaUN3V5?|~@LI}A~zH8Mv=T_CN_Y~*znf}L8
z+!D%UGBJa}5ZCE+QMFoq58vT%sBgF1xAl5mE))utKMJMOX@ALLu{^q5t_O$1ac4H0
zi3LTB1!z8>({MOk4hDm7)9Li3SS)sa6Ut_@5(|9s`~69;*Gs$Ij>hA$cw%X_TC&+}
z;@Ru<sMTt{vf$@@J}<=77e%+*{TK>`l0Ki0n$0F1k4NIt$Y?Z*IR5wheNw4Z6buGQ
zuh%CP3dMj!pMMZn;^*n<DHaF>9@wbSXb2JnP!<z}VGkc-zyJ#lxU!JP<B3a>bcY_G
z7f4^D(GWLUWB|h+KEy8l0tZ}K$mw)OQGdJL79>ttlyf?r-kE4B$AAGA9B}0xS*_N4
zq&=I>$Ye4J5=y{DTtu<I7F{eBqEv8YA&}A7{eCZ-Qh%uw_N&k}1{`o@AqLl(^Z_TJ
ze)I$Dx=aWm%gtsZFu?ves4n*i6AKVuzestxT+(W_5`=4m4>4eX1qWPNh<j6J$1)O$
zh?6Fh3Gw8Lo`D3z9zMi?0Tvu^-%WP4T7Bk;{)kgbr4o%sBhdqtcNs_~lHG2nR4OI>
zJmFu%;c@WKfyC-|yDxm=E9NAZ%TXec5JQN0fng6HV!!|kj{Kq`ql;B46{*wdJTq~@
z{W#w;#DD?zntSszQmfTsJZy1(HKIJtVovzF>wIHx{34gR(UrgY9{tPuF2Dd~Po<+F
S1x;%J0000<MNUMnLSTZOye2&W

delta 1026
zcmV+d1pWK91-uB5NPh#~Nkl<Zc-mByO>7%Q6vyAp&VJeJkKH)2-6pY<Kpj*-1&P9q
zfK;FomFR&3REP`e0U^X!MSG&q3sm9;2L#uu5=ejw8~`B#IRXmMKxs>WRs|d4HctGt
zyE8k(n>C5bu0}hS=l$OQ{omUqN-4Phdg}0#xzHs0i>`IAV}E7uaG5(dq(h=&wb~B*
zKhsX<Bia)mzxmc11MrL6!DI_0k_4W4?%92Qwfe-YpMSv4`<bGbr-ow#=_5*tupfnH
z=h{YRbFF!%xxRk-#LKUIo-g=F`46N~M~@ykRIctg)|jq0yz!D@N+8r?ASwRKC8(G~
zg6C9X$gAD<;D7f^m(RD>I<LR_{L`mN5R5=Cym;ik-IMbtr*}>5c7q~gTtOnGPJ@ep
zqMD$$Bn=SE<k8wc(Q0RX<>L8s$4?$V@tM(WZ)T_KQ!nkhxv@~rdMp+R#4-el36fN;
z)WJXr(r{@Ol>?IZ@|MHQaVeDX{;7ArX8wf#;El75hkt{jZ(JJ=A>kZ2`bDrLL#qJ{
zHjK1<N=C{gn6!s*uRKBOVSM0f>&lm`TrS^J@e3e{1c?BJiU7;fB}=V9$Kq2fOZ}u2
z1Ro_LA$LlpF}icQaTg25N_*W>Nwr!{;4vynbQACp8l%0Dx}$hggQjZI1YCg9Dh&pH
z;M2f&_kS|KP@MA!7`hxGFr!wJmND8(R6vnP#Asd=o|6gshPR2MK?$K=&Yop%)&+x^
z*ka6^2#{h6q>V*~&=?}L!*m4FigX8=0TdINDxsbe5M~p5)%3jEh--rwZX!q@hS8Ae
zg&+;32-5qsJbV~fvyGWdGczDo|5v)c`S*96_kWeo9F@cpIFC^rb}o(~76M{a8tdOe
zq|+~vZeSLicd$$w7#cF{_r9USp7?@*BPMo?fsxAsXDscCPzc3Rc`|~;I2J-^f6#a=
zi@7dT{Cr5QY}n^=iEi||XF7w8553}8w=p>rF-F0%3=mj9mkB~J7(ofD;c=Au!%Pz@
zlYcw8H6BF0Vdv9!zw-$_^!THL=AVDP9Y@inT5X!#*|-U8+XALbKwl&(A_#I2>^fP<
zWil`~RhOmlN{@tMrTNF&smC5V*x7#jm%m+pq*|*UW7MwkB=#=+be499F$}t0u+ii~
zp`e^%KxXD<M8<OCe$>6#yxe+i{`Nf|xO)I0x&C{!{QVF6s+IELf>+$HsIrHOQ(F=k
z#8HxkgyH~VWk$O%qNV1Q);sfiZe4P5zW?_<+PW6MTJ-9*+JS5?bAOH%Zo&54pq&pP
w`Yr5*KjQ1M_{+JK_wHU;7~oKB$Nek70DvL_;T%_u*Z=?k07*qoM6N<$f&$$B9smFU

diff --git a/core/res/res/drawable/presence_offline.png b/core/res/res/drawable/presence_offline.png
index da54fe7fccf409e86b29ec072f8710d7aeac85c7..3941b8205251753b2a12c04a64c71407ad5d6b56 100644
GIT binary patch
delta 743
zcmV<D0vP@I8~+86B!3xnMObuGZ)S9NVRB^vL1b@YWgtmyVP|DhWnpA_ami&o0007^
zNkl<Zc-pK~K}%v$6h4}osYPmLVaS78RD=XUi3=Bjy+7eT(RLFA!mMW7>@sQ}xOJ=G
z#zo{#A`B|aa%HJhmRc6h`Oe^DVqzGExo~{<-Sd6lz305|s(<VCdh|br?lYliG`co4
zG^7p=4h9Sc!yMM$-ri1MUS1B{?RI*1cQ^A#p-3d6jE;_OxZUn`m&;`v85toKlpG7t
z<KrXU-Q7J^tJVGc`}>`}y}j~pLa|s(VS#Vc)6-$E*GsRjuheKX<cVQ2naJUA$n)mr
zhDxQ<0SkUjB!3bjX6P$UOiXOd&(DXarlzP^EK;}IC7j4&u}GfF0-20PBQcK5W^-7l
z(^WaOiM$>^@pyb~W@cucgHBFP$m8+Q($W$=KR*-qNCI=LAqNbw;DD<MO-@d#ilW%i
zgI24B)6v4h0xd5u)9vl81m;*n4j5p;0aq(+e0)5B`hWBJyfinL%Sj2?_5J-_O2ho}
z@=|iZTwPt!%F2pxH6gp*K8IdBJUo!qYQ;NcvsnrTgT&1jq4V=|5kU_90u~%_H6f7M
zGtywhz`%e!aT?4qFvlAENyC8yt|r9YKh^8?e(ca}HmO#tk*caRJ3C7k7Z(D=9AfEo
zS_Eu18-FoJxLUK}Sb*?Z>-9RVuC7XB&(6*$l}brqjy2?f0Tvu^H6gAy%?nS9i;Hs9
zN~J=DLV=RWq`V_A#~N~Y2NoP~KREmN_;{Ng{RK{Dx5}==!^2WW-;gNV>2%^2^d0`)
z=kslTaQ5}}^$t7P&A{;1))pNd9Z8^H7-M5&6krO4$nW<{NxabkI4ty204M54CX-Rh
z<?=S0t;weAeHO?81MIKdPya^vuC1{_RlZLFHm3N5Klf>;(>dgeoaRPn{_6keU&aps
Z1^_KHl~Z@X8HWG>002ovPDHLkV1jC2Y!(0j

delta 3575
zcmV<T4G8l81^FA0B!3BTNLh0L01FcU01FcV0GgZ_000V4X+uL$P-t&-Z*ypGa3D!T
zLm+T+Z)Rz1WdHzp+MQEpR8#2|J@?-9LQ9B%luK_?6$l_wLW_VDktQl32@pz%A)(n7
zQNa;KMFbnjpojyGj)066Q7jCK3fKqaA)=0hqlk*i`{8?|Yk$_f_vX$1wbwr9tn;0-
z&j-K=43<bUQ8j=JsX`tR;Dg7+#^K~HK!FM*Z~zbpvt%K2{UZSY_<lS*D<Z%Lz5oGu
z(+dayz)hRLFdT>f59&ghTmgWD0l;*TI7<kC6aYYajzXpYKt=(8otP$50H6c_V9R4-
z;{Z@C0AMG7=6}-wfSvf6djSAjlpz%XppgI|6J>}*0BAb^tj|`8MF3bZ02F3R#5n-i
zEdVe{S7t~6u(trf&JYW-00;~KFj0twDF6g}0AR=?BX|IWnE(_<@>e|ZE3OddDgXd@
znX){&BsoQaTL>+22Uk}v9w^R97b_GtVFF>AKrX_0nSU8Ffiw@`^UMGMppg|3;Dhu1
zc+L*4&dxTDwhmt{>c0m6B4T3W{^ifBa6kY6;dFk{{wy!E8h|?nfNlPwCGG@hUJIag
z_lst-4?wj5py}FI^KkfnJUm6Akh$5}<>chpO2k52Vaiv1{%68pz*qfj`F=e7_x0eu
z;v|7GU4MZ`1o+^>%=Ap99M6&ogks$0k4OBs3;+Bb(;~!4V!2o<6ys46agIcqjPo+3
zB8fthDa9qy|77CdEc*jK-!%ZRYCZvbku9iQV*~a}ClFY4z~c7+0P?$U!PF=S1Au6Q
z;m>#f??3%Vpd|o+W=WE9003S@Bra6Svp>fO0Dk~Ppn)o|K^yeJ7%adB9Ki+L!3+Fg
zHiSYX#KJ-lLJDMn9CBbOtb#%)hRv`YDqt_vKpix|QD}yfa1JiQRk#j4a1Z)n2%f<x
zynzV>LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxWizFb)h!jyGOOZ85F;a?DAXP{m@;!0_
zIe&*-M!JzZ$N(~e{D!<oF_eL_Q9aZQwL`h6HyVUSq6^SubTOKb7NDEZa<m#fj5eX?
z(5q+<+K)a%$1uR?7zZ=NY%ngy!$Pq*ED4ii%dsM?46DW(uvV-CyNUH<&#`v|5`jg)
z2{r_GLLgxtK}c9kSWehTs3069G!fbfH-8BOgi*pLB9o{~v?jU{`NSAvGBJl(NGv1P
z5|0xv5POJ2#5W`oi9<3cxsU=$v7}Ve64FM}Zc-!ZEUB9`NE#!P$=YOVvIjYoEFde$
zh2)*&!{jsM8{{GKTMC_GKyjq_Q{pI6%4$j(<q+jG<pyP#GC@_Nno`}Up;QqykAGT1
zt)aG3uTh7n6Et<2In9F>NlT@zqLtGcXcuVrX|L#Xx)I%#9!{6gSJKPrN9dR61N3(c
z4Tcqi$B1Vr8Jidf7-t!G7_XR2rWw<V8OKyGH!<s&=a~<gZ&g?-wkmuTk;)2{N|h#+
z8!9hUsj8-`-l_{#^Hs}KkEvc$eSfY-RWnoLsR`7Ut5vF<Q0r40Q)j6=sE4X&sBct1
zq<&fbi3VB2Ov6t@q*0);U*o*SAPZv|vv@2aYYnT0b%8a+Cb7-ge0D0knEf5Qi#@8T
zp*ce{N;6lpQuCB%KL_KOarm5cP6_8Ir<e17iry6ODdH&`rZh~sF=bq9s(+T3mRPGu
zt5K^*>%BIv?Wdily+ylO`+*KY$4Vz$Cr4+G&IO(4Q`uA9rwXSQO+7mGt}d!;r5mBU
zM0dY#r|y`ZzFvTyOmC;&dA;ZQ9DOhSRQ+xGr}ak+SO&8UBnI0I&KNw!HF0k|9WTe*
z@liuv!$3o&VU=N*;e?U7(SJOn)kcj*4~%KXT;n9;ZN_cJqb3F>Atp;r>P_yNQcbz0
zDW*G2J50yT%*~?B)|oY%Ju%lZ=bPu7*PGwBU|M)uEVih&xMfMQ<XWa#?zX&cg<3gT
zrC3#3U9(25ovkI-yREyY5vRFMlTNFi)@Q@8@wUmfska%h<=6(>u79>|wtZn|Vi#w(
z#jeBdlf9FDx_yoPJqHbk*$%56S{;6Kv~m<WRyy9A&YbQ)eZ};a=`Uwk&k)bpGvl@s
z%PGWZol~3BM`ssjxpRZ_h>M9!g3B(KJ}#RZ#@)!h<Vtk)ab4kh()FF2vzx;0sN1jZ
zHtuQehuojcG@mJ+S${Kg(8I_>;8Eq#KMS9gFl*neeosSBfoHYnBQIkwkyowPu(zdm
zs`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMeBmZRodjHV?r+_5^X9J0W
zL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0?0=B0A@}E)&XLY(4uw#D
z=+@8&Vdi0r!+s1Wg@=V#hChyQh*%oYF_$%W(cD9G-$eREmPFp0XE9GXuPsV7Dn6<%
zYCPIEx-_~!#x7=A%+*+(SV?S4962s3t~PFLzTf=q^M~S{;tS(@7nm=|U2u7!&cgJC
zrxvL$5-d8FKz~e#PB@hCK@cja7K|nG6L%$!3VFgE!e=5c(KgYD*h5?@9!~N|DouKl
z?2)`Rc_hU%r7Y#SgeR$xyi5&D-J3d|7MgY-Z8AMNy)lE5k&tmhsv%92wrA>R=4N)w
ztYw9={>5&Kw=W)*2gz%*kgNq+Eef_mrsz~!DAy_nvVUh~S7yJ>iOM;atDY;(?aZ^v
z+mJV$@1Ote62cPUlD4IWOIIx&SmwQ~YB{nzae3Pc;}r!fhE@iwJh+OsDs9zItL;~p
zu715HdQEGAUct(O!L<Qv>kCy1<%NCg+}G`0PgpNm-?d@-hMgNe6^V+j6x$b<6@S<$
z+<4_1hktL%znR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX4c}I@?e+FW+b@^R
zDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i&_B8C(+grT%{XWUQ
z+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?SIDu(gXbmBM!FLxzyDi(mhmCkJc;e
zM-ImyzW$x>cP$Mz4ONYt#^NJzM0w=t_X*$k9t}F$c8q(h;Rn+nb{%IOFKR-X@|s4Q
zQ=0o*Vq3aT%s$c9>fU<%N829{oHRUHc}nwC$!Xf@g42^{^3RN&m7RTlF8SPG+oHC6
z=YM0)-)awU@466l;nGF_i|0GMJI-A4xODQe+vO8ixL2C5I$v$-bm~0*lhaSfyPUh4
zuDM)mx$b(swR>jw=^LIm&fWCAdGQwi*43UlJ>9+YdT;l|_x0Zv-F|W>{m#p~*>@-I
zt-MdXU-UrjLD@syht)q@{@mE_+<$7ocYmPs(cDM(28Dyq{*m>M4?_iynUBkc4TkHU
zI6gT!;y-fz>HMcd&t%Ugo)`Y2{>!cx7B7DI)$7;J(U{Spm-3gBzioV_{p!H$8L!*M
z!p0uH$#^p{Ui4P`?ZJ24cOCDe-w#jZd?0@)|7iKK^;6KN`;!@ylm7$*nDhK&Gk-1H
z0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F}0009dNkl<Z
zc-m}~K}%#u5XXPIPv|GJ<TcEYX;84i!#*K_HHk2%;DVcrH@)l^*pq}DWKVlEmmnbo
zPx}Qt=z21zh4tn^gL4ox!GT_)(0>a``hhR$0v}EeZ=5xo6f{LwSN*%{U)4R*@AtVc
zE6-QPQ7kH@=2fER(j=XZM5yRVB?lt1hp@ZxYUA(waU=JER=!<X$g=FYF=kn3nyitb
z8VV|qN+^nga24>Ee!D1&R~tWXy!j8%>WkH9#+aA+R6e7PMyUY+0u`u4L4N`WIPY-p
z+=)N;YwJI*Zw`T0U#u?Vllf2fk)6>-Ls@4qlmw^-8ps+M-g{1arzg(2@78}<fAgUH
zvm7^*W-b3b|Jr<ND2tNo+iS)cBNA(Udr#kv5hP$*1~sl)<zHpGv$^w2qFZ_~pU#(!
zG59MFH`GoIg>#Nb1RxTzlYbTwAzns&;W5S_r7VXKwnp3S_Pj9$5rH@;L4j!+thM#N
z0&6X1!hjn1M37Q2lLl+-e4?9rF3U39xf}B0&KxRHn5G$WqnjFk;c;hfNL`SCZCi9(
z&m~zSn@$^Pol*6H-|lf2a?ov!LgC+gx~E+fYUm@^LOPYA8frR8AAhE`wfd-2)U8)2
z1gX#N#$g}|1qyVk8C9s>-HZ&KD<RKwY}4W{9R9*%CoFlM4>^-cAQ^xq^pX(6fx*n`
zhnnK5KoIiJa!lLcE*$&aeNs}Wz)aLlIXylFKu>C<5@L)8qf*Kq0``%G1Y#8lA>ewB
z{lk5zYTN$dKCb5oA%7672npoVb%s*P-e^%2yP*u*N+~*>4pIs3w>p!%GVV&b0}~NC
zoen4nW!Uyte)qxao!2+V$H#^KM1RrBS}oHuxIY|~R8&<(S(P6EZy`w%o__Nb(=?Q2
zdE(C8_e)DlzYia6_t)+-Gi6?8jci7wzP)%~5Q<Rqk!jlPHgL0F&7u-TA;pP*=hq&8
z`FIn6e!o9lN8O_Z@BLQ1j{O*8Ki>S0zK(r=>9>v!j~4F7j(q&Fz1@2|ZmnHR8|i$O
xWOFE{2lLaDQVwDn_uRSLeKP;#Umx2)0|1tH+-*Z};lcm_002ovPDHLkV1f^=wch{$

diff --git a/core/res/res/drawable/presence_online.png b/core/res/res/drawable/presence_online.png
index 879a762955d18520d1abb221e5f03ec44398515e..22d5683e2f5970a3f53b9d8970713863b6b83d2d 100644
GIT binary patch
delta 789
zcmV+w1M2+98>|M9B!3xnMObuGZ)S9NVRB^vL1b@YWgtmyVP|DhWnpA_ami&o0008c
zNkl<Zc-pK~PiWI%6#u17n{+L8f9%>Sl#Ib-gAD~`Fgz&Ydh_B**hM^8wq3-X1|lNt
zAQLa!sNiuPy?9$a=t1VdgR;SPkYQW#PhB_Ht!<JfX?!nPgMYFiB7X45m-qX_`(EA`
z!M1Juk0l&sG(J8)8VZHdk|d3YqS((l(=<19U0+sJb!lN?A@@h4OeUkWx3^Em<MErZ
zSS%8aMnQ%SMh4j1+r!q@R<%?rJ>K2joy%sk`9nq%6B7y<-0$t}9ZRKB(83?F?SBtl
z*miKq?n0M!8h>)F2gPC$o12@9WO!$Oe%>(?TaJlDVsc<$U@X;>#5+8K7W@o48vK60
zgKJh1-}M#9IEgd;w;;>%m>>uxf~LHRrl+Sz2L}hAkx}G@o`EXo5e|nD2nOKyxkgsg
zg3&NgtJM(F6kL|FSYKbSuC1+Iotc@*ITa<7$+V&<k$-~kB|c#V(Vz%Xtike$5PUwz
z$VL;UXrd8RQP#eJxr#CzDVNJ>f^!b5ySsa&v$GR#Do<euKm#T;dmn1^2UKg@4cc>#
zG3GFrHLUe|)X~w=-`3WKulfhb5*>s3Z#KCKKKwxwZ9blh(Zk`ghP9p%_k$a2nLICU
zaF1=@VSl3*&Ro{8mX~uh>i&k0dU0IrLqi8OmB@x0)<Lx18DkD}S;Jb-h$q&vEL@1+
zfLfzZU8kH%q61SWbT`KsbC}B-)_O*jN@a->)r+ZXNC;<9tpK%spk8%F9K7coW6WVL
zYgqf+WUsES&eBBRHf#;|USGi%{Vnyt?Uge}7JpX`oRH4p?)m2k2r^Ij!=a&}DX$`4
zg+gJD?$4quhVkIiD_lSI1TlLUdgYiCyyqNa%waBTyo<^ewIY|xDfxVUmM-Uhy<WGE
z3dWej++Vdv{zho@M`_s7be~27fq*k7hGA@Inzp>Nv$I53Dfd_ZqkmaH1sDLhN2LT+
T(hi3B00000NkvXXu0mjf6)<=j

delta 3526
zcmV;%4LS0x2FM$bB!3BTNLh0L01FcU01FcV0GgZ_000V4X+uL$P-t&-Z*ypGa3D!T
zLm+T+Z)Rz1WdHzp+MQEpR8#2|J@?-9LQ9B%luK_?6$l_wLW_VDktQl32@pz%A)(n7
zQNa;KMFbnjpojyGj)066Q7jCK3fKqaA)=0hqlk*i`{8?|Yk$_f_vX$1wbwr9tn;0-
z&j-K=43<bUQ8j=JsX`tR;Dg7+#^K~HK!FM*Z~zbpvt%K2{UZSY_<lS*D<Z%Lz5oGu
z(+dayz)hRLFdT>f59&ghTmgWD0l;*TI7<kC6aYYajzXpYKt=(8otP$50H6c_V9R4-
z;{Z@C0AMG7=6}-wfSvf6djSAjlpz%XppgI|6J>}*0BAb^tj|`8MF3bZ02F3R#5n-i
zEdVe{S7t~6u(trf&JYW-00;~KFj0twDF6g}0AR=?BX|IWnE(_<@>e|ZE3OddDgXd@
znX){&BsoQaTL>+22Uk}v9w^R97b_GtVFF>AKrX_0nSU8Ffiw@`^UMGMppg|3;Dhu1
zc+L*4&dxTDwhmt{>c0m6B4T3W{^ifBa6kY6;dFk{{wy!E8h|?nfNlPwCGG@hUJIag
z_lst-4?wj5py}FI^KkfnJUm6Akh$5}<>chpO2k52Vaiv1{%68pz*qfj`F=e7_x0eu
z;v|7GU4MZ`1o+^>%=Ap99M6&ogks$0k4OBs3;+Bb(;~!4V!2o<6ys46agIcqjPo+3
zB8fthDa9qy|77CdEc*jK-!%ZRYCZvbku9iQV*~a}ClFY4z~c7+0P?$U!PF=S1Au6Q
z;m>#f??3%Vpd|o+W=WE9003S@Bra6Svp>fO0Dk~Ppn)o|K^yeJ7%adB9Ki+L!3+Fg
zHiSYX#KJ-lLJDMn9CBbOtb#%)hRv`YDqt_vKpix|QD}yfa1JiQRk#j4a1Z)n2%f<x
zynzV>LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxWizFb)h!jyGOOZ85F;a?DAXP{m@;!0_
zIe&*-M!JzZ$N(~e{D!<oF_eL_Q9aZQwL`h6HyVUSq6^SubTOKb7NDEZa<m#fj5eX?
z(5q+<+K)a%$1uR?7zZ=NY%ngy!$Pq*ED4ii%dsM?46DW(uvV-CyNUH<&#`v|5`jg)
z2{r_GLLgxtK}c9kSWehTs3069G!fbfH-8BOgi*pLB9o{~v?jU{`NSAvGBJl(NGv1P
z5|0xv5POJ2#5W`oi9<3cxsU=$v7}Ve64FM}Zc-!ZEUB9`NE#!P$=YOVvIjYoEFde$
zh2)*&!{jsM8{{GKTMC_GKyjq_Q{pI6%4$j(<q+jG<pyP#GC@_Nno`}Up;QqykAGT1
zt)aG3uTh7n6Et<2In9F>NlT@zqLtGcXcuVrX|L#Xx)I%#9!{6gSJKPrN9dR61N3(c
z4Tcqi$B1Vr8Jidf7-t!G7_XR2rWw<V8OKyGH!<s&=a~<gZ&g?-wkmuTk;)2{N|h#+
z8!9hUsj8-`-l_{#^Hs}KkEvc$eSfY-RWnoLsR`7Ut5vF<Q0r40Q)j6=sE4X&sBct1
zq<&fbi3VB2Ov6t@q*0);U*o*SAPZv|vv@2aYYnT0b%8a+Cb7-ge0D0knEf5Qi#@8T
zp*ce{N;6lpQuCB%KL_KOarm5cP6_8Ir<e17iry6ODdH&`rZh~sF=bq9s(+T3mRPGu
zt5K^*>%BIv?Wdily+ylO`+*KY$4Vz$Cr4+G&IO(4Q`uA9rwXSQO+7mGt}d!;r5mBU
zM0dY#r|y`ZzFvTyOmC;&dA;ZQ9DOhSRQ+xGr}ak+SO&8UBnI0I&KNw!HF0k|9WTe*
z@liuv!$3o&VU=N*;e?U7(SJOn)kcj*4~%KXT;n9;ZN_cJqb3F>Atp;r>P_yNQcbz0
zDW*G2J50yT%*~?B)|oY%Ju%lZ=bPu7*PGwBU|M)uEVih&xMfMQ<XWa#?zX&cg<3gT
zrC3#3U9(25ovkI-yREyY5vRFMlTNFi)@Q@8@wUmfska%h<=6(>u79>|wtZn|Vi#w(
z#jeBdlf9FDx_yoPJqHbk*$%56S{;6Kv~m<WRyy9A&YbQ)eZ};a=`Uwk&k)bpGvl@s
z%PGWZol~3BM`ssjxpRZ_h>M9!g3B(KJ}#RZ#@)!h<Vtk)ab4kh()FF2vzx;0sN1jZ
zHtuQehuojcG@mJ+S${Kg(8I_>;8Eq#KMS9gFl*neeosSBfoHYnBQIkwkyowPu(zdm
zs`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMeBmZRodjHV?r+_5^X9J0W
zL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0?0=B0A@}E)&XLY(4uw#D
z=+@8&Vdi0r!+s1Wg@=V#hChyQh*%oYF_$%W(cD9G-$eREmPFp0XE9GXuPsV7Dn6<%
zYCPIEx-_~!#x7=A%+*+(SV?S4962s3t~PFLzTf=q^M~S{;tS(@7nm=|U2u7!&cgJC
zrxvL$5-d8FKz~e#PB@hCK@cja7K|nG6L%$!3VFgE!e=5c(KgYD*h5?@9!~N|DouKl
z?2)`Rc_hU%r7Y#SgeR$xyi5&D-J3d|7MgY-Z8AMNy)lE5k&tmhsv%92wrA>R=4N)w
ztYw9={>5&Kw=W)*2gz%*kgNq+Eef_mrsz~!DAy_nvVUh~S7yJ>iOM;atDY;(?aZ^v
z+mJV$@1Ote62cPUlD4IWOIIx&SmwQ~YB{nzae3Pc;}r!fhE@iwJh+OsDs9zItL;~p
zu715HdQEGAUct(O!L<Qv>kCy1<%NCg+}G`0PgpNm-?d@-hMgNe6^V+j6x$b<6@S<$
z+<4_1hktL%znR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX4c}I@?e+FW+b@^R
zDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i&_B8C(+grT%{XWUQ
z+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?SIDu(gXbmBM!FLxzyDi(mhmCkJc;e
zM-ImyzW$x>cP$Mz4ONYt#^NJzM0w=t_X*$k9t}F$c8q(h;Rn+nb{%IOFKR-X@|s4Q
zQ=0o*Vq3aT%s$c9>fU<%N829{oHRUHc}nwC$!Xf@g42^{^3RN&m7RTlF8SPG+oHC6
z=YM0)-)awU@466l;nGF_i|0GMJI-A4xODQe+vO8ixL2C5I$v$-bm~0*lhaSfyPUh4
zuDM)mx$b(swR>jw=^LIm&fWCAdGQwi*43UlJ>9+YdT;l|_x0Zv-F|W>{m#p~*>@-I
zt-MdXU-UrjLD@syht)q@{@mE_+<$7ocYmPs(cDM(28Dyq{*m>M4?_iynUBkc4TkHU
zI6gT!;y-fz>HMcd&t%Ugo)`Y2{>!cx7B7DI)$7;J(U{Spm-3gBzioV_{p!H$8L!*M
z!p0uH$#^p{Ui4P`?ZJ24cOCDe-w#jZd?0@)|7iKK^;6KN`;!@ylm7$*nDhK&Gk-1H
z0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F}0008>Nkl<Z
zc-nlFF=!k|6ox;YmoR&*@h(Vk13A!=GvrhRl!Pm;31?6f)WlX}QltpD5+PvWCMqvY
zP)rDNV@P8#DkK{WiW`Hj2&hnkRDTF`1RtzG#TasAhj`<CkinZ`Pp6aRWZ=zv?;qad
zz5mV3R8bU6uH{?HRTPU#sgCkg%lG_7P7aQNIN1}C9>Vte{q<LqaZ{6tmcLqF2*dD}
z)_N%lBf=m=1qvL96RfqQ!xZy}*|OH&U;lCa*@Z+acUEp{tyi0~&AF%^p?_u*P$}XG
zASf4tXgJm+Cx+xWIWi}vyLNYNW1MK^&dNfw-uxkcKc0)O3hDGy1OY&mX<+OtqTzMY
z=g=SYkCG($dhNTlXP2@+v#PG^Zu5iYC((OCfBJheH-w6ixglA_!dP2uWytWIU#MSc
z5mfYy``h^sHXi)!MKjT2vwzWC(siHRU=_rc)i_nw;YtpagA~A(Rqm@U?fN~e)k`+B
zn_jI}>u9a%2lue<VAKqNoNMW#ozM?{B96bryf7UvnvPmw7-HN$DT0rX13r)=Bh6cJ
z!!Gl|ZFEhyyf6qGe&A!J52K*TbryUPhd#dY34^dv@h|(}sq$dN2Y-%pe*PagC{POj
zvQI_9Kmn0!jxOFvq+~>70(%2jE<R;+P)T$41R?f5EUA<c-42wTP3&!W?6nam<axeV
zku2>Y&<?*rxmr0DIh|X%$>|&?@W|C@hqucvGU-*UwcBZyZYeL~^V-9+{)PXwuh$-;
zh)A<^%UH90>Cxjy|9>1F9@^+i^pUP!or$Y$`hV@<UT5%{QebQ=uf`YeK0&KC@+vz@
zo+sbl`0U2-<41e&+rdpet5-u6&Iy*MFS?j)7b6MEgUE}~L7Pu&t0+Q5>``)Ty7M2;
zZvapf#aQ+a_7{vXoB7MU$n(6&^P(t5`qa-~=7lk4bNAQ%g+IyIsW(5io!(A0uE&dh
z=y#N-T1u%#Nwf^a$zE>LUUFi#uXV1S``G>+00>8`SaS~DF#rGn07*qoM6N<$f~$V7
AQ~&?~

diff --git a/core/res/res/drawable/zoom_ring_trail.xml b/core/res/res/drawable/zoom_ring_trail.xml
new file mode 100644
index 000000000000..08931ac5aafc
--- /dev/null
+++ b/core/res/res/drawable/zoom_ring_trail.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<rotate xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pivotX="50%"
+    android:pivotY="50%"
+    android:fromDegrees="0"
+    android:toDegrees="360">
+
+    <shape
+        android:shape="ring"
+        android:innerRadius="60dip"
+        android:thickness="14dip"
+        android:useLevel="true">
+
+        <gradient
+            android:type="sweep"
+            android:useLevel="true"
+            android:startColor="#1000ceff"
+            android:endColor="#ffadd252" />
+
+    </shape>
+
+ </rotate>
diff --git a/core/res/res/layout/date_picker.xml b/core/res/res/layout/date_picker.xml
index a398bd006bcc..0760cc0b7123 100644
--- a/core/res/res/layout/date_picker.xml
+++ b/core/res/res/layout/date_picker.xml
@@ -24,6 +24,7 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/parent"
     android:orientation="horizontal"
+    android:layout_gravity="center_horizontal"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content">
 
diff --git a/core/res/res/layout/date_picker_dialog.xml b/core/res/res/layout/date_picker_dialog.xml
index 879f3398f1bf..949c8a3082c7 100644
--- a/core/res/res/layout/date_picker_dialog.xml
+++ b/core/res/res/layout/date_picker_dialog.xml
@@ -17,11 +17,9 @@
 */
 -->
 
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:padding="5dip">
-    <DatePicker android:id="@+id/datePicker"
-            android:layout_width="fill_parent"
-            android:layout_height="fill_parent"/>
-</FrameLayout>
+<DatePicker xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/datePicker"
+    android:padding="5dip"
+    android:layout_gravity="center_horizontal"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"/>
diff --git a/core/res/res/layout/number_picker.xml b/core/res/res/layout/number_picker.xml
index 422733a002c5..bbdb31cb44e6 100644
--- a/core/res/res/layout/number_picker.xml
+++ b/core/res/res/layout/number_picker.xml
@@ -22,23 +22,21 @@
     <com.android.internal.widget.NumberPickerButton android:id="@+id/increment"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
-        android:background="@drawable/timepicker_up_btn"
-        />
-        
-		<EditText android:id="@+id/timepicker_input"
-		    android:layout_width="fill_parent"
-		    android:layout_height="wrap_content"
-		    android:gravity="center"
-		    android:singleLine="true"
-		    style="?android:attr/textAppearanceLargeInverse"
-		    android:textSize="30sp"
-		    android:background="@drawable/timepicker_input"
-		    />
-        
+        android:background="@drawable/timepicker_up_btn" />
+
+    <EditText android:id="@+id/timepicker_input"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center"
+        android:singleLine="true"
+        style="?android:attr/textAppearanceLargeInverse"
+        android:textColor="@android:color/primary_text_light"
+        android:textSize="30sp"
+        android:background="@drawable/timepicker_input" />
+
     <com.android.internal.widget.NumberPickerButton android:id="@+id/decrement"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
-        android:background="@drawable/timepicker_down_btn"
-        />
-        
+        android:background="@drawable/timepicker_down_btn" />
+
 </merge>
diff --git a/core/res/res/layout/number_picker_edit.xml b/core/res/res/layout/number_picker_edit.xml
index 46f4845ad3e7..f3af6e9b211e 100644
--- a/core/res/res/layout/number_picker_edit.xml
+++ b/core/res/res/layout/number_picker_edit.xml
@@ -23,6 +23,7 @@
     android:gravity="center_horizontal"
     android:singleLine="true"
     style="?android:attr/textAppearanceLargeInverse"
+    android:textColor="@android:color/primary_text_light"
     android:textSize="30sp"
     android:background="@drawable/timepicker_input"
     />
diff --git a/core/res/res/layout/time_picker.xml b/core/res/res/layout/time_picker.xml
index bdfe4900e663..c601e0e83077 100644
--- a/core/res/res/layout/time_picker.xml
+++ b/core/res/res/layout/time_picker.xml
@@ -21,6 +21,7 @@
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="horizontal"
+    android:layout_gravity="center_horizontal"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content">
 
@@ -55,5 +56,6 @@
         android:paddingLeft="20dip"
         android:paddingRight="20dip"
         style="?android:attr/textAppearanceLargeInverse"
+        android:textColor="@android:color/primary_text_light_nodisable"
         />
 </LinearLayout>
diff --git a/core/res/res/layout/time_picker_dialog.xml b/core/res/res/layout/time_picker_dialog.xml
index 6dc1bf62d150..d5a6b5eb9bc1 100644
--- a/core/res/res/layout/time_picker_dialog.xml
+++ b/core/res/res/layout/time_picker_dialog.xml
@@ -17,11 +17,9 @@
 */
 -->
 
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:padding="5dip">
-    <TimePicker android:id="@+id/timePicker"
-            android:layout_width="fill_parent"
-            android:layout_height="fill_parent"/>
-</FrameLayout>
+<TimePicker xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/timePicker"
+    android:layout_gravity="center_horizontal"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:padding="5dip" />
diff --git a/core/res/res/layout/time_picker_text.xml b/core/res/res/layout/time_picker_text.xml
deleted file mode 100644
index bad980b64324..000000000000
--- a/core/res/res/layout/time_picker_text.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- TextView of time picker-->
-
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent"
-    android:textAppearance="?attr/textAppearanceLargeInverse"
-    android:gravity="center"
-    />
diff --git a/core/res/res/values-cs-rCZ/strings.xml b/core/res/res/values-cs-rCZ/strings.xml
deleted file mode 100644
index e1eb3f475b6c..000000000000
--- a/core/res/res/values-cs-rCZ/strings.xml
+++ /dev/null
@@ -1,1112 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- no translation found for byteShort (2850097084724465606) -->
-    <skip />
-    <!-- no translation found for kilobyteShort (5865542430193761682) -->
-    <skip />
-    <!-- no translation found for megabyteShort (112984851085937882) -->
-    <skip />
-    <!-- no translation found for gigabyteShort (8586075069559273847) -->
-    <skip />
-    <!-- no translation found for terabyteShort (5828502357595687794) -->
-    <skip />
-    <!-- no translation found for petabyteShort (7523248732657962413) -->
-    <skip />
-    <string name="untitled">"&lt;bez názvu&gt;"</string>
-    <string name="ellipsis">"…"</string>
-    <string name="emptyPhoneNumber">"(žádné telefonní číslo)"</string>
-    <string name="unknownName">"(neznámý)"</string>
-    <string name="defaultVoiceMailAlphaTag">"Hlasová schránka"</string>
-    <string name="defaultMsisdnAlphaTag">"Msisdn1"</string>
-    <string name="mmiError">"Chyba sítě nebo neplatný kód MMI."</string>
-    <string name="serviceEnabled">"Služba povolena"</string>
-    <string name="serviceEnabledFor">"Služba povolena pro:"</string>
-    <string name="serviceDisabled">"Služba zakázána"</string>
-    <string name="serviceRegistered">"Registrace úspěšná"</string>
-    <string name="serviceErased">"Odstranění úspěšné"</string>
-    <string name="passwordIncorrect">"Nesprávné heslo."</string>
-    <string name="mmiComplete">"MMI dokončeno"</string>
-    <!-- no translation found for badPin (5103184589972647739) -->
-    <skip />
-    <!-- no translation found for badPuk (2200634943393540609) -->
-    <skip />
-    <!-- no translation found for mismatchPin (5055729703806180857) -->
-    <skip />
-    <!-- no translation found for invalidPin (6201854814319326475) -->
-    <skip />
-    <!-- no translation found for needPuk (4788728144863892764) -->
-    <skip />
-    <!-- no translation found for needPuk2 (7056908944942451033) -->
-    <skip />
-    <!-- no translation found for ClipMmi (5649729434121615509) -->
-    <skip />
-    <!-- no translation found for ClirMmi (5220979296096544477) -->
-    <skip />
-    <!-- no translation found for CfMmi (4998483717856803914) -->
-    <skip />
-    <!-- no translation found for CwMmi (5678103638951836350) -->
-    <skip />
-    <!-- no translation found for BaMmi (6030555200442855833) -->
-    <skip />
-    <!-- no translation found for PwdMmi (2549941247959366670) -->
-    <skip />
-    <!-- no translation found for PinMmi (2463353963837922189) -->
-    <skip />
-    <string name="CLIRDefaultOnNextCallOn">"Výchozí nastavení omezení ID - omezení. Další hovor: omezení"</string>
-    <string name="CLIRDefaultOnNextCallOff">"Výchozí nastavení omezení ID - omezení. Další hovor: bez omezení"</string>
-    <string name="CLIRDefaultOffNextCallOn">"Výchozí nastavení omezení ID - bez omezení. Další hovor: omezení"</string>
-    <string name="CLIRDefaultOffNextCallOff">"Výchozí nastavení omezení ID - bez omezení. Další hovor: bez omezení"</string>
-    <string name="serviceNotProvisioned">"Služba není poskytována."</string>
-    <string name="CLIRPermanent">"Omezení ID v trvalém režimu."</string>
-    <string name="serviceClassVoice">"Hlasový záznam"</string>
-    <string name="serviceClassData">"Data"</string>
-    <string name="serviceClassFAX">"FAX"</string>
-    <string name="serviceClassSMS">"SMS"</string>
-    <string name="serviceClassDataAsync">"Asynchronní"</string>
-    <string name="serviceClassDataSync">"Synchronizace"</string>
-    <string name="serviceClassPacket">"Pakety"</string>
-    <string name="serviceClassPAD">"PAD"</string>
-    <string name="cfTemplateNotForwarded">"{0}: Nepřesměrováno"</string>
-    <string name="cfTemplateForwarded">"{0}: {1}"</string>
-    <string name="cfTemplateForwardedTime">"{0}: {1} po {2} sekundách"</string>
-    <string name="cfTemplateRegistered">"{0}: Nepřesměrováno ({1})"</string>
-    <string name="cfTemplateRegisteredTime">"{0}: Nepřesměrováno ({1} po {2} sekundách)"</string>
-    <string name="httpErrorOk">"OK"</string>
-    <string name="httpError">"Neznámá chyba"</string>
-    <string name="httpErrorLookup">"Neznámý hostitel"</string>
-    <string name="httpErrorUnsupportedAuthScheme">"Nepodporované schéma ověření. Ověření se nezdařilo."</string>
-    <string name="httpErrorAuth">"Ověřování se nezdařilo"</string>
-    <string name="httpErrorProxyAuth">"Ověření serverem proxy se nezdařilo"</string>
-    <string name="httpErrorConnect">"Připojení k serveru se nezdařilo"</string>
-    <string name="httpErrorIO">"Čtení nebo zápis na server se nezdařil"</string>
-    <string name="httpErrorTimeout">"Časový limit připojení k serveru vypršel"</string>
-    <string name="httpErrorRedirectLoop">"Příliš mnoho přesměrování serverů"</string>
-    <string name="httpErrorUnsupportedScheme">"Nepodporovaný protokol"</string>
-    <string name="httpErrorFailedSslHandshake">"Navázání spojení typu SSL handshake se nezdařilo"</string>
-    <string name="httpErrorBadUrl">"Nepodařilo se analyzovat URL"</string>
-    <string name="httpErrorFile">"File error"</string>
-    <string name="httpErrorFileNotFound">"File not found"</string>
-    <!-- no translation found for httpErrorTooManyRequests (3764334538393544875) -->
-    <skip />
-    <string name="contentServiceSync">"Synchronizace"</string>
-    <string name="contentServiceSyncNotificationTitle">"Synchronizace"</string>
-    <!-- no translation found for contentServiceTooManyDeletesNotificationDesc (8477597194404210723) -->
-    <skip />
-    <!-- no translation found for low_memory (4191592786596642367) -->
-    <skip />
-    <!-- no translation found for me (4616693653158602117) -->
-    <skip />
-    <string name="power_dialog">"Možnosti napájení"</string>
-    <string name="silent_mode">"Tichý režim"</string>
-    <string name="turn_on_radio">"Zapnout rádio"</string>
-    <string name="turn_off_radio">"Vypnout rádio"</string>
-    <!-- no translation found for screen_lock (1560333453597081877) -->
-    <skip />
-    <string name="power_off">"Vypnuto"</string>
-    <!-- no translation found for shutdown_progress (3735034517335251808) -->
-    <skip />
-    <!-- no translation found for shutdown_confirm (699224922526414097) -->
-    <skip />
-    <!-- no translation found for no_recent_tasks (1367712919998349373) -->
-    <skip />
-    <!-- no translation found for global_actions (8299888906525675157) -->
-    <skip />
-    <!-- no translation found for global_action_lock (5943677976245541105) -->
-    <skip />
-    <!-- no translation found for global_action_power_off (3143027278596694254) -->
-    <skip />
-    <!-- no translation found for global_action_toggle_silent_mode (5849335789367070450) -->
-    <skip />
-    <!-- no translation found for global_action_silent_mode_on_status (6053429980569202260) -->
-    <skip />
-    <!-- no translation found for global_action_silent_mode_off_status (1994514127029249081) -->
-    <skip />
-    <!-- no translation found for safeMode (3375134507868534320) -->
-    <skip />
-    <!-- no translation found for permgrouplab_costMoney (904087853776533085) -->
-    <skip />
-    <!-- no translation found for permgroupdesc_costMoney (4662370555643969515) -->
-    <skip />
-    <!-- no translation found for permgrouplab_messages (2984053976424233925) -->
-    <skip />
-    <!-- no translation found for permgroupdesc_messages (2129093134354989379) -->
-    <skip />
-    <!-- no translation found for permgrouplab_personalInfo (4548406335021507392) -->
-    <skip />
-    <!-- no translation found for permgroupdesc_personalInfo (8499310823817958034) -->
-    <skip />
-    <!-- no translation found for permgrouplab_location (8535677827151907069) -->
-    <skip />
-    <!-- no translation found for permgroupdesc_location (2341662219604651887) -->
-    <skip />
-    <!-- no translation found for permgrouplab_network (3597781730625751831) -->
-    <skip />
-    <!-- no translation found for permgroupdesc_network (8332572695347918340) -->
-    <skip />
-    <!-- no translation found for permgrouplab_accounts (8631201594657951893) -->
-    <skip />
-    <!-- no translation found for permgroupdesc_accounts (443982868906396781) -->
-    <skip />
-    <!-- no translation found for permgrouplab_hardwareControls (5074512938567152139) -->
-    <skip />
-    <!-- no translation found for permgroupdesc_hardwareControls (8772503144945278440) -->
-    <skip />
-    <!-- no translation found for permgrouplab_phoneCalls (7096448531266882376) -->
-    <skip />
-    <!-- no translation found for permgroupdesc_phoneCalls (6703873478653366233) -->
-    <skip />
-    <!-- no translation found for permgrouplab_systemTools (1840847965111633430) -->
-    <skip />
-    <!-- no translation found for permgroupdesc_systemTools (2810337951496685271) -->
-    <skip />
-    <!-- no translation found for permgrouplab_developmentTools (692844635256963358) -->
-    <skip />
-    <!-- no translation found for permgroupdesc_developmentTools (5253915519857796400) -->
-    <skip />
-    <!-- no translation found for permlab_statusBar (8789506912215455922) -->
-    <skip />
-    <!-- no translation found for permdesc_statusBar (5034247171231682403) -->
-    <skip />
-    <!-- no translation found for permlab_expandStatusBar (6382500803293284173) -->
-    <skip />
-    <!-- no translation found for permdesc_expandStatusBar (90953162060681436) -->
-    <skip />
-    <!-- no translation found for permlab_processOutgoingCalls (786316295241100144) -->
-    <skip />
-    <!-- no translation found for permdesc_processOutgoingCalls (1655242138991854396) -->
-    <skip />
-    <string name="permlab_receiveSms">"Příjem zpráv SMS"</string>
-    <string name="permdesc_receiveSms">"Umožňuje aplikacím přijímat a zpracovávat zprávy SMS. Škodlivé aplikace mohou sledovat vaše zprávy nebo je odstraňovat, aniž by se zobrazily."</string>
-    <string name="permlab_receiveMms">"Příjem zpráv MMS"</string>
-    <string name="permdesc_receiveMms">"Umožňuje aplikacím přijímat a zpracovávat zprávy MMS. Škodlivé aplikace mohou sledovat vaše zprávy nebo je odstraňovat, aniž by se zobrazily."</string>
-    <!-- no translation found for permlab_sendSms (4713837923748234081) -->
-    <skip />
-    <!-- no translation found for permdesc_sendSms (7126594387176704010) -->
-    <skip />
-    <!-- no translation found for permlab_readSms (4256004535185449429) -->
-    <skip />
-    <!-- no translation found for permdesc_readSms (4586480500886941902) -->
-    <skip />
-    <!-- no translation found for permlab_writeSms (8453452414726246828) -->
-    <skip />
-    <!-- no translation found for permdesc_writeSms (1036408118901361812) -->
-    <skip />
-    <string name="permlab_receiveWapPush">"Příjem zpráv WAP"</string>
-    <string name="permdesc_receiveWapPush">"Umožňuje aplikacím přijímat a zpracovávat zprávy WAP. Škodlivé aplikace mohou sledovat vaše zprávy nebo je odstraňovat, aniž by se zobrazily."</string>
-    <string name="permlab_getTasks">"Získat informace o úkolech"</string>
-    <string name="permdesc_getTasks">"Umožňuje aplikacím načítat informace o aktuálně a naposledy spuštěných úkolech. Umožňuje škodlivým aplikacím zjišťovat soukromé informace o jiných aplikacích."</string>
-    <!-- no translation found for permlab_reorderTasks (4758862288285224517) -->
-    <skip />
-    <!-- no translation found for permdesc_reorderTasks (7507060843941912021) -->
-    <skip />
-    <!-- no translation found for permlab_setDebugApp (2973363275929449444) -->
-    <skip />
-    <!-- no translation found for permdesc_setDebugApp (5720449860498265972) -->
-    <skip />
-    <!-- no translation found for permlab_changeConfiguration (8581093564179818627) -->
-    <skip />
-    <!-- no translation found for permdesc_changeConfiguration (4055366453803187171) -->
-    <skip />
-    <!-- no translation found for permlab_restartPackages (5836367540766044606) -->
-    <skip />
-    <!-- no translation found for permdesc_restartPackages (1764965996765573321) -->
-    <skip />
-    <!-- no translation found for permlab_setProcessForeground (4860990420780868638) -->
-    <skip />
-    <!-- no translation found for permdesc_setProcessForeground (3795477299954784360) -->
-    <skip />
-    <!-- no translation found for permlab_forceBack (4737517869935566733) -->
-    <skip />
-    <!-- no translation found for permdesc_forceBack (5579316297001154697) -->
-    <skip />
-    <string name="permlab_dump">"Výpis stavu systému"</string>
-    <string name="permdesc_dump">"Umožňuje aplikacím načítat vnitřní stav systému. Škodlivé aplikace mohou načítat široký rozsah soukromých a důvěrných informací, jež by obvykle neměly nikdy vyžadovat."</string>
-    <string name="permlab_addSystemService">"Přidat systémovou službu"</string>
-    <string name="permdesc_addSystemService">"Umožňuje aplikacím vydávat vlastní systémové služby nižší úrovně. Škodlivé aplikace mohou napadnout systém a vykrást nebo poškodit jeho data."</string>
-    <string name="permlab_runSetActivityWatcher">"Nastavení sledování činností"</string>
-    <string name="permdesc_runSetActivityWatcher">"Umožňuje aplikacím sledovat a řídit spouštění činností systému. Škodlivé aplikace mohou zcela zničit systém. Toto oprávnění je nutné pouze pro vývoj, nikdy pro normální používání zařízení."</string>
-    <string name="permlab_broadcastPackageRemoved">"Sada vysílání odebrána"</string>
-    <string name="permdesc_broadcastPackageRemoved">"Umožňuje aplikacím vysílat oznámení o odebrání sady aplikací. Škodlivé aplikace toho mohou využít k likvidaci jiné spuštěné aplikace."</string>
-    <!-- no translation found for permlab_broadcastSmsReceived (1994692154847312518) -->
-    <skip />
-    <!-- no translation found for permdesc_broadcastSmsReceived (6072362543164841432) -->
-    <skip />
-    <!-- no translation found for permlab_broadcastWapPush (3070023012636951639) -->
-    <skip />
-    <!-- no translation found for permdesc_broadcastWapPush (726912255218924336) -->
-    <skip />
-    <!-- no translation found for permlab_setProcessLimit (5190694306017260601) -->
-    <skip />
-    <!-- no translation found for permdesc_setProcessLimit (593938303319848578) -->
-    <skip />
-    <!-- no translation found for permlab_setAlwaysFinish (8745533365504920540) -->
-    <skip />
-    <!-- no translation found for permdesc_setAlwaysFinish (2437195869854312148) -->
-    <skip />
-    <string name="permlab_fotaUpdate">"Instalace aktualizace systému"</string>
-    <string name="permdesc_fotaUpdate">"Umožňuje aplikacím přijímat oznámení o aktualizacích systému čekajících na dokončení a spouštět jejich instalaci. Škodlivé aplikace toho mohou využít k poškození systému neautorizovanými aktualizacemi nebo obecně k zásahům do aktualizačního procesu."</string>
-    <!-- no translation found for permlab_batteryStats (1598947993704535568) -->
-    <skip />
-    <!-- no translation found for permdesc_batteryStats (6247598531831307989) -->
-    <skip />
-    <string name="permlab_internalSystemWindow">"Okno vnitřního systému"</string>
-    <string name="permdesc_internalSystemWindow">"Umožňuje vytváření oken určených k použití uživatelským rozhraním vnitřního systému . Není určeno k použití normálními aplikacemi."</string>
-    <string name="permlab_systemAlertWindow">"Okno systémových výstrah"</string>
-    <string name="permdesc_systemAlertWindow">"Umožňuje aplikacím zobrazovat okna systémových výstrah. Škodlivé aplikace mohou ovládnout celou obrazovku zařízení."</string>
-    <!-- no translation found for permlab_setAnimationScale (2419250686027992384) -->
-    <skip />
-    <!-- no translation found for permdesc_setAnimationScale (8518027785481727264) -->
-    <skip />
-    <!-- no translation found for permlab_manageAppTokens (1033424552444304594) -->
-    <skip />
-    <!-- no translation found for permdesc_manageAppTokens (7285840918912623550) -->
-    <skip />
-    <!-- no translation found for permlab_injectEvents (1383601196263145482) -->
-    <skip />
-    <!-- no translation found for permdesc_injectEvents (840097509341464737) -->
-    <skip />
-    <!-- no translation found for permlab_readInputState (2723668746963882102) -->
-    <skip />
-    <!-- no translation found for permdesc_readInputState (4651137638757852001) -->
-    <skip />
-    <!-- no translation found for permlab_setOrientation (1112555600323148680) -->
-    <skip />
-    <!-- no translation found for permdesc_setOrientation (1960269530378827858) -->
-    <skip />
-    <string name="permlab_signalPersistentProcesses">"Signálové trvalé procesy"</string>
-    <string name="permdesc_signalPersistentProcesses">"Umožňuje aplikacím vyžadovat, aby se přiváděný signál odesílal do všech trvalých procesů."</string>
-    <!-- no translation found for permlab_persistentActivity (8163108526929094627) -->
-    <skip />
-    <!-- no translation found for permdesc_persistentActivity (5258975883823299624) -->
-    <skip />
-    <string name="permlab_deletePackages">"Odstranit sady"</string>
-    <string name="permdesc_deletePackages">"Umožňuje aplikacím odstranit sady systému Android. Škodlivé aplikace toho mohou využít k odstranění důležitých aplikací."</string>
-    <!-- no translation found for permlab_clearAppUserData (3858185484601410171) -->
-    <skip />
-    <!-- no translation found for permdesc_clearAppUserData (7233537744753081136) -->
-    <skip />
-    <!-- no translation found for permlab_deleteCacheFiles (7362746182961997888) -->
-    <skip />
-    <!-- no translation found for permdesc_deleteCacheFiles (8293849509208181266) -->
-    <skip />
-    <!-- no translation found for permlab_getPackageSize (6743556676630447973) -->
-    <skip />
-    <!-- no translation found for permdesc_getPackageSize (2893996655828539776) -->
-    <skip />
-    <string name="permlab_installPackages">"Instalovat sady"</string>
-    <string name="permdesc_installPackages">"Umožňuje aplikacím instalovat nové nebo aktualizované sady systému Android. Škodlivé aplikace toho mohou využít k přidání nových aplikací s libovolně silnými oprávněními."</string>
-    <!-- no translation found for permlab_clearAppCache (7860214328511700776) -->
-    <skip />
-    <!-- no translation found for permdesc_clearAppCache (5203820862573167878) -->
-    <skip />
-    <!-- no translation found for permlab_readLogs (6653488552442991707) -->
-    <skip />
-    <!-- no translation found for permdesc_readLogs (356352685800884319) -->
-    <skip />
-    <!-- no translation found for permlab_diagnostic (2955142476313469329) -->
-    <skip />
-    <!-- no translation found for permdesc_diagnostic (1282409892215520166) -->
-    <skip />
-    <string name="permlab_changeComponentState">"Povolit nebo zakázat součásti aplikací"</string>
-    <string name="permdesc_changeComponentState">"Umožňuje změnu aplikace bez ohledu na to, zda je součást další aplikace povolená nebo zakázaná. Škodlivá aplikace toho může využít k zakázání důležitých funkcí zařízení. Je třeba nakládat s oprávněními opatrně, protože se mohou součásti aplikace dostat do stavu nepoužitelnosti, nekonzistence nebo nestability."</string>
-    <string name="permlab_setPreferredApplications">"Nastavení upřednostňovaných aplikací"</string>
-    <string name="permdesc_setPreferredApplications">"Umožňuje aplikacím upravovat oblíbené aplikace. Škodlivé aplikace tak mohou bez upozornění měnit spouštěné aplikace a klamně využívat stávající aplikace ke shromažďování vašich soukromých dat."</string>
-    <string name="permlab_writeSettings">"Nastavení systému pro zápis"</string>
-    <string name="permdesc_writeSettings">"Umožňuje aplikacím upravovat data nastavení systému. Škodlivé aplikace mohou narušit systémovou konfiguraci."</string>
-    <!-- no translation found for permlab_writeSecureSettings (4851801872124242319) -->
-    <skip />
-    <!-- no translation found for permdesc_writeSecureSettings (2080620249472761366) -->
-    <skip />
-    <!-- no translation found for permlab_writeGservices (296370685945777755) -->
-    <skip />
-    <!-- no translation found for permdesc_writeGservices (2496928471286495053) -->
-    <skip />
-    <string name="permlab_receiveBootCompleted">"Spustit při spouštění"</string>
-    <string name="permdesc_receiveBootCompleted">"Umožňuje aplikacím spouštět se po dokončení spuštění systému. Tím se může prodlužovat doba spouštění zařízení a aplikace může svým stálým spouštěním zpomalovat celé zařízení."</string>
-    <string name="permlab_broadcastSticky">"Vysílat lepivý obsah (sticky)"</string>
-    <string name="permdesc_broadcastSticky">"Umožňuje aplikacím odesílat tzv. lepivé (sticky) vysílání, které zůstává i po ukončení vysílání. Škodlivé aplikace mohou zpomalit zařízení nebo narušit jeho stabilitu vynucením využívání příliš velké části paměti."</string>
-    <string name="permlab_readContacts">"Čtení dat o kontaktech"</string>
-    <string name="permdesc_readContacts">"Umožňuje aplikacím číst všechna data o kontaktech (adresy) uložená v zařízení. Škodlivé aplikace toho mohou využívat k odesílání vašich dat jiným osobám."</string>
-    <string name="permlab_writeContacts">"Zápis dat o kontaktech"</string>
-    <string name="permdesc_writeContacts">"Umožňuje aplikacím upravovat data o kontaktech (adresy) uložená v zařízení. Škodlivé aplikace toho mohou využívat k vymazání nebo úpravě dat o kontaktech."</string>
-    <!-- no translation found for permlab_writeOwnerData (8036840529708535113) -->
-    <skip />
-    <!-- no translation found for permdesc_writeOwnerData (5873447528845878348) -->
-    <skip />
-    <!-- no translation found for permlab_readOwnerData (1847040178513733757) -->
-    <skip />
-    <!-- no translation found for permdesc_readOwnerData (7563299529149214764) -->
-    <skip />
-    <!-- no translation found for permlab_readCalendar (2111238731453410895) -->
-    <skip />
-    <!-- no translation found for permdesc_readCalendar (4408253940601239114) -->
-    <skip />
-    <!-- no translation found for permlab_writeCalendar (7518052789370653396) -->
-    <skip />
-    <!-- no translation found for permdesc_writeCalendar (8057304232140147596) -->
-    <skip />
-    <!-- no translation found for permlab_accessMockLocation (321094551062270213) -->
-    <skip />
-    <!-- no translation found for permdesc_accessMockLocation (3651565866471419739) -->
-    <skip />
-    <!-- no translation found for permlab_accessLocationExtraCommands (8291822077788811687) -->
-    <skip />
-    <!-- no translation found for permdesc_accessLocationExtraCommands (5135782633548630731) -->
-    <skip />
-    <string name="permlab_accessFineLocation">"Používat službu GPS"</string>
-    <string name="permdesc_accessFineLocation">"Technologii GPS v zařízení lze používat, pokud je k dispozici. Toto oprávnění vyžaduje oprávnění ACCESS_LOCATION. Škodlivé aplikace toho mohou využívat k určení vaší polohy a mohou spotřebovávat zbytečně energii baterie."</string>
-    <string name="permlab_accessCoarseLocation">"Používat službu Cell ID"</string>
-    <string name="permdesc_accessCoarseLocation">"Identifikátory pro technologii využívající polohu vysílačů mobilních sítí (je-li k dispozici) se používají k určení přibližné polohy zařízení. Toto oprávnění vyžaduje oprávnění ACCESS_LOCATION. Škodlivé aplikace toho mohou využívat k určení vaší přibližné polohy."</string>
-    <string name="permlab_accessSurfaceFlinger">"Používat službu SurfaceFlinger"</string>
-    <string name="permdesc_accessSurfaceFlinger">"Umožňuje aplikacím používat funkce nižší úrovně SurfaceFlinger."</string>
-    <string name="permlab_readFrameBuffer">"Čtení vyrovnávací paměti rámce"</string>
-    <string name="permdesc_readFrameBuffer">"Umožňuje aplikacím používat čtení obsahu vyrovnávací paměti rámce."</string>
-    <!-- no translation found for permlab_modifyAudioSettings (1587341813207960943) -->
-    <skip />
-    <!-- no translation found for permdesc_modifyAudioSettings (1447143004892708149) -->
-    <skip />
-    <!-- no translation found for permlab_recordAudio (4447848534036991667) -->
-    <skip />
-    <!-- no translation found for permdesc_recordAudio (6936874682400894820) -->
-    <skip />
-    <!-- no translation found for permlab_camera (1944473855727060380) -->
-    <skip />
-    <!-- no translation found for permdesc_camera (5978058582323766022) -->
-    <skip />
-    <!-- no translation found for permlab_brick (4749832243303289777) -->
-    <skip />
-    <!-- no translation found for permdesc_brick (7428524578693695766) -->
-    <skip />
-    <!-- no translation found for permlab_reboot (8844650672567077423) -->
-    <skip />
-    <!-- no translation found for permdesc_reboot (4704919552870918328) -->
-    <skip />
-    <!-- no translation found for permlab_mount_unmount_filesystems (1009574821038043781) -->
-    <skip />
-    <!-- no translation found for permdesc_mount_unmount_filesystems (100792065894811109) -->
-    <skip />
-    <!-- no translation found for permlab_vibrate (61984555644467146) -->
-    <skip />
-    <!-- no translation found for permdesc_vibrate (7831723100758509238) -->
-    <skip />
-    <!-- no translation found for permlab_flashlight (9097145977808182652) -->
-    <skip />
-    <!-- no translation found for permdesc_flashlight (7851502731988978358) -->
-    <skip />
-    <!-- no translation found for permlab_hardware_test (4103324677866524254) -->
-    <skip />
-    <!-- no translation found for permdesc_hardware_test (7315242723603994769) -->
-    <skip />
-    <string name="permlab_callPhone">"Volat telefonní čísla"</string>
-    <string name="permdesc_callPhone">"Umožňuje aplikacím volat telefonní čísla bez vašeho zásahu. Škodlivé aplikace mohou přinést na váš telefonní účet neočekávané hovory."</string>
-    <!-- no translation found for permlab_callPrivileged (2166923597287697159) -->
-    <skip />
-    <!-- no translation found for permdesc_callPrivileged (5109789447971735501) -->
-    <skip />
-    <!-- no translation found for permlab_locationUpdates (4216418293360456836) -->
-    <skip />
-    <!-- no translation found for permdesc_locationUpdates (7635814693478743648) -->
-    <skip />
-    <!-- no translation found for permlab_checkinProperties (2260796787386280708) -->
-    <skip />
-    <!-- no translation found for permdesc_checkinProperties (3508022022841741945) -->
-    <skip />
-    <!-- no translation found for permlab_modifyPhoneState (7791696535097912313) -->
-    <skip />
-    <!-- no translation found for permdesc_modifyPhoneState (6352405226410454770) -->
-    <skip />
-    <!-- no translation found for permlab_readPhoneState (7320082586621086653) -->
-    <skip />
-    <!-- no translation found for permdesc_readPhoneState (8004450067066407969) -->
-    <skip />
-    <!-- no translation found for permlab_wakeLock (1591164750935072136) -->
-    <skip />
-    <!-- no translation found for permdesc_wakeLock (160471538196734936) -->
-    <skip />
-    <!-- no translation found for permlab_devicePower (9214865067086065548) -->
-    <skip />
-    <!-- no translation found for permdesc_devicePower (5608364066480036402) -->
-    <skip />
-    <!-- no translation found for permlab_factoryTest (7786199300637896247) -->
-    <skip />
-    <!-- no translation found for permdesc_factoryTest (3466066005210542042) -->
-    <skip />
-    <!-- no translation found for permlab_setWallpaper (2256730637138641725) -->
-    <skip />
-    <!-- no translation found for permdesc_setWallpaper (3034653140208685093) -->
-    <skip />
-    <!-- no translation found for permlab_setWallpaperHints (4192438316932517807) -->
-    <skip />
-    <!-- no translation found for permdesc_setWallpaperHints (738757439960921674) -->
-    <skip />
-    <!-- no translation found for permlab_masterClear (6155403967270586906) -->
-    <skip />
-    <!-- no translation found for permdesc_masterClear (4213553172342689754) -->
-    <skip />
-    <!-- no translation found for permlab_setTimeZone (477196167239548690) -->
-    <skip />
-    <!-- no translation found for permdesc_setTimeZone (8564892020460841198) -->
-    <skip />
-    <!-- no translation found for permlab_getAccounts (2764070033402295170) -->
-    <skip />
-    <!-- no translation found for permdesc_getAccounts (1203491378748649898) -->
-    <skip />
-    <!-- no translation found for permlab_accessNetworkState (2032916924886010827) -->
-    <skip />
-    <!-- no translation found for permdesc_accessNetworkState (7081329402551195933) -->
-    <skip />
-    <!-- no translation found for permlab_createNetworkSockets (4706698319966917864) -->
-    <skip />
-    <!-- no translation found for permdesc_createNetworkSockets (2580337178778551792) -->
-    <skip />
-    <!-- no translation found for permlab_writeApnSettings (3190585220761979369) -->
-    <skip />
-    <!-- no translation found for permdesc_writeApnSettings (4093875220468761052) -->
-    <skip />
-    <!-- no translation found for permlab_changeNetworkState (2710779001260856872) -->
-    <skip />
-    <!-- no translation found for permdesc_changeNetworkState (8076109230787022270) -->
-    <skip />
-    <!-- no translation found for permlab_accessWifiState (3613679494230374297) -->
-    <skip />
-    <!-- no translation found for permdesc_accessWifiState (8226508433563326925) -->
-    <skip />
-    <!-- no translation found for permlab_changeWifiState (6043889338995432957) -->
-    <skip />
-    <!-- no translation found for permdesc_changeWifiState (7829372845909567994) -->
-    <skip />
-    <!-- no translation found for permlab_bluetoothAdmin (5513286736585647334) -->
-    <skip />
-    <!-- no translation found for permdesc_bluetoothAdmin (1838208497914347365) -->
-    <skip />
-    <!-- no translation found for permlab_bluetooth (6378797624765639115) -->
-    <skip />
-    <!-- no translation found for permdesc_bluetooth (8592386018922265273) -->
-    <skip />
-    <!-- no translation found for permlab_disableKeyguard (4574886811903233903) -->
-    <skip />
-    <!-- no translation found for permdesc_disableKeyguard (815972646344251271) -->
-    <skip />
-    <!-- no translation found for permlab_readSyncSettings (8818819977141505127) -->
-    <skip />
-    <!-- no translation found for permdesc_readSyncSettings (8454705401908767847) -->
-    <skip />
-    <!-- no translation found for permlab_writeSyncSettings (4514911143753152941) -->
-    <skip />
-    <!-- no translation found for permdesc_writeSyncSettings (7630627689635091836) -->
-    <skip />
-    <!-- no translation found for permlab_readSyncStats (5748337739678952863) -->
-    <skip />
-    <!-- no translation found for permdesc_readSyncStats (582551457321957183) -->
-    <skip />
-    <!-- no translation found for permlab_subscribedFeedsRead (2043206814904506589) -->
-    <skip />
-    <!-- no translation found for permdesc_subscribedFeedsRead (6977343942680042449) -->
-    <skip />
-    <!-- no translation found for permlab_subscribedFeedsWrite (2556727307229571556) -->
-    <skip />
-    <!-- no translation found for permdesc_subscribedFeedsWrite (4134783294590266220) -->
-    <skip />
-    <!-- no translation found for phoneTypes:7 (1326005699931077792) -->
-  <string-array name="emailAddressTypes">
-    <item>"Výchozí"</item>
-    <item>"Zaměstnání"</item>
-    <item>"Primární"</item>
-    <item>"Vlastní…"</item>
-  </string-array>
-  <string-array name="postalAddressTypes">
-    <item>"Poštovní"</item>
-    <item>"Výchozí"</item>
-    <item>"Zaměstnání"</item>
-    <item>"Vlastní…"</item>
-  </string-array>
-    <!-- no translation found for imAddressTypes:0 (7806620012096518833) -->
-    <!-- no translation found for imAddressTypes:1 (5748846799950672787) -->
-    <!-- no translation found for imAddressTypes:2 (6196536810275073680) -->
-    <!-- no translation found for imAddressTypes:3 (8519128375350623648) -->
-    <!-- no translation found for organizationTypes:0 (1299224825223821142) -->
-    <!-- no translation found for organizationTypes:1 (2455717447227299354) -->
-    <!-- no translation found for organizationTypes:2 (7027570839313438290) -->
-    <!-- no translation found for imProtocols:0 (3318725788774688043) -->
-    <!-- no translation found for imProtocols:1 (1787713387022932886) -->
-    <!-- no translation found for imProtocols:2 (6751174158442316516) -->
-    <!-- no translation found for imProtocols:3 (1151283347465052653) -->
-    <!-- no translation found for imProtocols:4 (2157980008878817934) -->
-    <!-- no translation found for imProtocols:5 (7836237460308230767) -->
-    <!-- no translation found for imProtocols:6 (1180789904462172516) -->
-    <!-- no translation found for imProtocols:7 (21955111672779862) -->
-    <!-- no translation found for keyguard_password_enter_pin_code (6779835451906812518) -->
-    <skip />
-    <!-- no translation found for keyguard_password_wrong_pin_code (230312338493035499) -->
-    <skip />
-    <string name="keyguard_label_text">"Telefon odemknete stisknutím tlačítka nabídky a poté 0."</string>
-    <!-- no translation found for emergency_call_dialog_number_for_display (6256361184251050511) -->
-    <skip />
-    <!-- no translation found for lockscreen_carrier_default (5222269885486229730) -->
-    <skip />
-    <!-- no translation found for lockscreen_screen_locked (1922273663462058967) -->
-    <skip />
-    <!-- no translation found for lockscreen_instructions_when_pattern_enabled (7535864145009679967) -->
-    <skip />
-    <!-- no translation found for lockscreen_instructions_when_pattern_disabled (6526504555912746785) -->
-    <skip />
-    <!-- no translation found for lockscreen_pattern_instructions (8984964506352089877) -->
-    <skip />
-    <!-- no translation found for lockscreen_emergency_call (422835617844547383) -->
-    <skip />
-    <!-- no translation found for lockscreen_pattern_correct (7104753084746383672) -->
-    <skip />
-    <!-- no translation found for lockscreen_pattern_wrong (7517004470797680361) -->
-    <skip />
-    <!-- no translation found for lockscreen_plugged_in (8806977650003537118) -->
-    <skip />
-    <!-- no translation found for lockscreen_low_battery (9002637795199621345) -->
-    <skip />
-    <!-- no translation found for lockscreen_missing_sim_message_short (5051192587315492957) -->
-    <skip />
-    <!-- no translation found for lockscreen_missing_sim_message (8912914495901434841) -->
-    <skip />
-    <!-- no translation found for lockscreen_missing_sim_instructions (8125847194365725429) -->
-    <skip />
-    <!-- no translation found for lockscreen_network_locked_message (323609607922245071) -->
-    <skip />
-    <!-- no translation found for lockscreen_sim_puk_locked_message (1005803622871256359) -->
-    <skip />
-    <!-- no translation found for lockscreen_sim_puk_locked_instructions (5033160098036646955) -->
-    <skip />
-    <!-- no translation found for lockscreen_sim_locked_message (7398401200962556379) -->
-    <skip />
-    <!-- no translation found for lockscreen_sim_unlock_progress_dialog_message (5939537246164692076) -->
-    <skip />
-    <!-- no translation found for lockscreen_too_many_failed_attempts_dialog_message (6709066241494622136) -->
-    <skip />
-    <!-- no translation found for lockscreen_failed_attempts_almost_glogin (1569017295989454551) -->
-    <skip />
-    <!-- no translation found for lockscreen_too_many_failed_attempts_countdown (8823588000022797566) -->
-    <skip />
-    <!-- no translation found for lockscreen_forgot_pattern_button_text (4219994639843985488) -->
-    <skip />
-    <!-- no translation found for lockscreen_glogin_too_many_attempts (7504679498838839295) -->
-    <skip />
-    <!-- no translation found for lockscreen_glogin_instructions (6542400673357252011) -->
-    <skip />
-    <!-- no translation found for lockscreen_glogin_username_hint (6378418320242015111) -->
-    <skip />
-    <!-- no translation found for lockscreen_glogin_password_hint (3224230234042131153) -->
-    <skip />
-    <!-- no translation found for lockscreen_glogin_submit_button (5562051040043760034) -->
-    <skip />
-    <!-- no translation found for lockscreen_glogin_invalid_input (4881057177478491580) -->
-    <skip />
-    <!-- no translation found for status_bar_time_format (2168573805413119180) -->
-    <skip />
-    <!-- no translation found for hour_minute_ampm (1850330605794978742) -->
-    <skip />
-    <!-- no translation found for hour_minute_cap_ampm (1122840227537374196) -->
-    <skip />
-    <!-- no translation found for hour_ampm (7665432130905376251) -->
-    <skip />
-    <!-- no translation found for hour_cap_ampm (3600295014648400268) -->
-    <skip />
-    <!-- no translation found for status_bar_clear_all_button (2202004591253243750) -->
-    <skip />
-    <!-- no translation found for status_bar_no_notifications_title (5123133188102094464) -->
-    <skip />
-    <!-- no translation found for status_bar_ongoing_events_title (799961521630569167) -->
-    <skip />
-    <!-- no translation found for status_bar_latest_events_title (5414094466807164279) -->
-    <skip />
-    <!-- no translation found for battery_status_text_percent_format (7391464609447031944) -->
-    <skip />
-    <!-- no translation found for battery_status_charging (5078780715755132756) -->
-    <skip />
-    <!-- no translation found for battery_low_title (3665400828395001695) -->
-    <skip />
-    <!-- no translation found for battery_low_subtitle (7537149915372180016) -->
-    <skip />
-    <!-- no translation found for battery_low_percent_format (8635359708781261154) -->
-    <skip />
-    <string name="factorytest_failed">"Výrobní test skončil chybou"</string>
-    <string name="factorytest_not_system">"Akce FACTORY_TEST je podporována pouze pro sady instalované v adresáři /system/app."</string>
-    <string name="factorytest_no_action">"Nebyla nalezena žádná sada, která zajišťuje akci FACTORY_TEST."</string>
-    <string name="factorytest_reboot">"Restartovat"</string>
-    <!-- no translation found for save_password_label (4129493019621348626) -->
-    <skip />
-    <!-- no translation found for save_password_message (7412617920202682045) -->
-    <skip />
-    <!-- no translation found for save_password_notnow (3887362423496820832) -->
-    <skip />
-    <!-- no translation found for save_password_remember (4319688896716308569) -->
-    <skip />
-    <!-- no translation found for save_password_never (1836981952883642377) -->
-    <skip />
-    <!-- no translation found for open_permission_deny (6408502671105717111) -->
-    <skip />
-    <!-- no translation found for text_copied (6106873823411904723) -->
-    <skip />
-    <string name="more_item_label">"Další"</string>
-    <string name="prepend_shortcut_label">"Menu+"</string>
-    <!-- no translation found for menu_space_shortcut_label (194586306440382711) -->
-    <skip />
-    <!-- no translation found for menu_enter_shortcut_label (7214761412193519345) -->
-    <skip />
-    <!-- no translation found for menu_delete_shortcut_label (2854936426194985313) -->
-    <skip />
-    <string name="search_go">"PŘEJÍT"</string>
-    <string name="today">"Dnes"</string>
-    <string name="yesterday">"Včera"</string>
-    <string name="tomorrow">"Zítra"</string>
-    <!-- no translation found for oneMonthDurationPast (3402179395240209557) -->
-    <skip />
-    <!-- no translation found for beforeOneMonthDurationPast (7578100953282866827) -->
-    <skip />
-    <!-- no translation found for num_seconds_ago:one (7416512229671810725) -->
-    <!-- no translation found for num_seconds_ago:other (8138756910300398447) -->
-    <!-- no translation found for num_minutes_ago:one (8620869479299420562) -->
-    <!-- no translation found for num_minutes_ago:other (5065488162050522741) -->
-    <!-- no translation found for num_hours_ago:one (853404611989669641) -->
-    <!-- no translation found for num_hours_ago:other (3558873784561756849) -->
-    <!-- no translation found for num_days_ago:one (4222479980812128212) -->
-    <!-- no translation found for num_days_ago:other (5445701370433601703) -->
-    <!-- no translation found for in_num_seconds:one (4253290037777327003) -->
-    <!-- no translation found for in_num_seconds:other (1280033870920841404) -->
-    <!-- no translation found for in_num_minutes:one (1487585791027953091) -->
-    <!-- no translation found for in_num_minutes:other (6274204576475209932) -->
-    <!-- no translation found for in_num_hours:one (6501470863235186391) -->
-    <!-- no translation found for in_num_hours:other (4415358752953289251) -->
-    <!-- no translation found for in_num_days:one (5608475533104443893) -->
-    <!-- no translation found for in_num_days:other (3827193006163842267) -->
-    <!-- no translation found for preposition_for_date (2689847983632851560) -->
-    <skip />
-    <!-- no translation found for preposition_for_time (2613388053493148013) -->
-    <skip />
-    <!-- no translation found for preposition_for_year (6968468294728152393) -->
-    <skip />
-    <string name="day">"den"</string>
-    <string name="days">"dnů"</string>
-    <string name="hour">"hodinu"</string>
-    <string name="hours">"hodin"</string>
-    <string name="minute">"minutu"</string>
-    <string name="minutes">"minut"</string>
-    <string name="second">"sekund"</string>
-    <string name="seconds">"sekund"</string>
-    <string name="week">"týden"</string>
-    <string name="weeks">"týdnů"</string>
-    <!-- no translation found for year (8024790425994085153) -->
-    <skip />
-    <!-- no translation found for years (8592090054773244417) -->
-    <skip />
-    <string name="sunday">"Neděle"</string>
-    <string name="monday">"Pondělí"</string>
-    <string name="tuesday">"Úterý"</string>
-    <string name="wednesday">"Středa"</string>
-    <string name="thursday">"ÄŒtvrtek"</string>
-    <string name="friday">"Pátek"</string>
-    <string name="saturday">"Sobota"</string>
-    <string name="every_weekday">"Každý den v týdnu (Po–Pá)"</string>
-    <string name="daily">"DennÄ›"</string>
-    <string name="weekly">"Týdně (%s)"</string>
-    <string name="monthly">"Měsíčně"</string>
-    <string name="yearly">"Ročně"</string>
-    <!-- no translation found for VideoView_error_title (1024334251681931859) -->
-    <skip />
-    <!-- no translation found for VideoView_error_text_unknown (3398417247398476771) -->
-    <skip />
-    <!-- no translation found for VideoView_error_button (3144127115413163445) -->
-    <skip />
-    <string name="am">"dop."</string>
-    <string name="pm">"odp."</string>
-    <!-- no translation found for numeric_date (5120078478872821100) -->
-    <skip />
-    <!-- no translation found for wday1_date1_time1_wday2_date2_time2 (7066878981949584861) -->
-    <skip />
-    <!-- no translation found for wday1_date1_wday2_date2 (8671068747172261907) -->
-    <skip />
-    <!-- no translation found for date1_time1_date2_time2 (3645498975775629615) -->
-    <skip />
-    <!-- no translation found for date1_date2 (377057563556488062) -->
-    <skip />
-    <!-- no translation found for time1_time2 (3173474242109288305) -->
-    <skip />
-    <!-- no translation found for time_wday_date (8928955562064570313) -->
-    <skip />
-    <!-- no translation found for wday_date (8794741400546136975) -->
-    <skip />
-    <!-- no translation found for time_date (1922644512833014496) -->
-    <skip />
-    <!-- no translation found for time_wday (1422050241301754712) -->
-    <skip />
-    <!-- no translation found for full_date_month_first (6011143962222283357) -->
-    <skip />
-    <!-- no translation found for full_date_day_first (8621594762705478189) -->
-    <skip />
-    <!-- no translation found for medium_date_month_first (48990963718825728) -->
-    <skip />
-    <!-- no translation found for medium_date_day_first (2898992016440387123) -->
-    <skip />
-    <!-- no translation found for twelve_hour_time_format (6015557937879492156) -->
-    <skip />
-    <!-- no translation found for twenty_four_hour_time_format (5176807998669709535) -->
-    <skip />
-    <!-- no translation found for noon (8390796001560682897) -->
-    <skip />
-    <!-- no translation found for Noon (7698941576181064429) -->
-    <skip />
-    <!-- no translation found for midnight (7773339795626486146) -->
-    <skip />
-    <!-- no translation found for Midnight (1260172107848123187) -->
-    <skip />
-    <!-- no translation found for month_day (3356633704511426364) -->
-    <skip />
-    <!-- no translation found for month (3017405760734206414) -->
-    <skip />
-    <!-- no translation found for month_day_year (2435948225709176752) -->
-    <skip />
-    <!-- no translation found for month_year (6228414124777343135) -->
-    <skip />
-    <!-- no translation found for time_of_day (8375993139317154157) -->
-    <skip />
-    <!-- no translation found for date_and_time (9197690194373107109) -->
-    <skip />
-    <!-- no translation found for same_year_md1_md2 (9199324363135981317) -->
-    <skip />
-    <!-- no translation found for same_year_wday1_md1_wday2_md2 (6006392413355305178) -->
-    <skip />
-    <!-- no translation found for same_year_mdy1_mdy2 (1576657593937827090) -->
-    <skip />
-    <!-- no translation found for same_year_wday1_mdy1_wday2_mdy2 (9135935796468891580) -->
-    <skip />
-    <!-- no translation found for same_year_md1_time1_md2_time2 (2172964106375558081) -->
-    <skip />
-    <!-- no translation found for same_year_wday1_md1_time1_wday2_md2_time2 (1702879534101786310) -->
-    <skip />
-    <!-- no translation found for same_year_mdy1_time1_mdy2_time2 (2476443311723358767) -->
-    <skip />
-    <!-- no translation found for same_year_wday1_mdy1_time1_wday2_mdy2_time2 (1564837340334069879) -->
-    <skip />
-    <!-- no translation found for numeric_md1_md2 (8908376522875100300) -->
-    <skip />
-    <!-- no translation found for numeric_wday1_md1_wday2_md2 (3239690882018292077) -->
-    <skip />
-    <!-- no translation found for numeric_mdy1_mdy2 (8883797176939233525) -->
-    <skip />
-    <!-- no translation found for numeric_wday1_mdy1_wday2_mdy2 (4150475769255828954) -->
-    <skip />
-    <!-- no translation found for numeric_md1_time1_md2_time2 (3624746590607741419) -->
-    <skip />
-    <!-- no translation found for numeric_wday1_md1_time1_wday2_md2_time2 (4258040955467298134) -->
-    <skip />
-    <!-- no translation found for numeric_mdy1_time1_mdy2_time2 (3598215409314517987) -->
-    <skip />
-    <!-- no translation found for numeric_wday1_mdy1_time1_wday2_mdy2_time2 (264076937155877259) -->
-    <skip />
-    <!-- no translation found for same_month_md1_md2 (2393563617438036111) -->
-    <skip />
-    <!-- no translation found for same_month_wday1_md1_wday2_md2 (1208946773794057819) -->
-    <skip />
-    <!-- no translation found for same_month_mdy1_mdy2 (3713236637869030492) -->
-    <skip />
-    <!-- no translation found for same_month_wday1_mdy1_wday2_mdy2 (389638922479870472) -->
-    <skip />
-    <!-- no translation found for same_month_md1_time1_md2_time2 (7477075526337542685) -->
-    <skip />
-    <!-- no translation found for same_month_wday1_md1_time1_wday2_md2_time2 (3516978303779391173) -->
-    <skip />
-    <!-- no translation found for same_month_mdy1_time1_mdy2_time2 (7320410992514057310) -->
-    <skip />
-    <!-- no translation found for same_month_wday1_mdy1_time1_wday2_mdy2_time2 (1332950588774239228) -->
-    <skip />
-    <!-- no translation found for abbrev_month_day_year (5767271534015320250) -->
-    <skip />
-    <!-- no translation found for abbrev_month_year (8058929633673942490) -->
-    <skip />
-    <!-- no translation found for abbrev_month_day (458867920693482757) -->
-    <skip />
-    <!-- no translation found for abbrev_month (1674509986330181349) -->
-    <skip />
-    <!-- no translation found for day_of_week_long_sunday (9057662850446501884) -->
-    <skip />
-    <!-- no translation found for day_of_week_long_monday (7358451993082888343) -->
-    <skip />
-    <!-- no translation found for day_of_week_long_tuesday (2282901451170509613) -->
-    <skip />
-    <!-- no translation found for day_of_week_long_wednesday (2100217950343286482) -->
-    <skip />
-    <!-- no translation found for day_of_week_long_thursday (5475158963242863176) -->
-    <skip />
-    <!-- no translation found for day_of_week_long_friday (4081018004819837155) -->
-    <skip />
-    <!-- no translation found for day_of_week_long_saturday (1929694088305891795) -->
-    <skip />
-    <!-- no translation found for day_of_week_medium_sunday (6462580883948669820) -->
-    <skip />
-    <!-- no translation found for day_of_week_medium_monday (6960587654241349502) -->
-    <skip />
-    <!-- no translation found for day_of_week_medium_tuesday (7004462235990108936) -->
-    <skip />
-    <!-- no translation found for day_of_week_medium_wednesday (5688564741951314696) -->
-    <skip />
-    <!-- no translation found for day_of_week_medium_thursday (1784339868453982400) -->
-    <skip />
-    <!-- no translation found for day_of_week_medium_friday (4314577583604069357) -->
-    <skip />
-    <!-- no translation found for day_of_week_medium_saturday (70321191398427845) -->
-    <skip />
-    <!-- no translation found for day_of_week_short_sunday (7403409454572591357) -->
-    <skip />
-    <!-- no translation found for day_of_week_short_monday (5278358100012478239) -->
-    <skip />
-    <!-- no translation found for day_of_week_short_tuesday (5121116040712487059) -->
-    <skip />
-    <!-- no translation found for day_of_week_short_wednesday (1601079579293330319) -->
-    <skip />
-    <!-- no translation found for day_of_week_short_thursday (5863422096017401812) -->
-    <skip />
-    <!-- no translation found for day_of_week_short_friday (2916686031099723960) -->
-    <skip />
-    <!-- no translation found for day_of_week_short_saturday (8521564973195542073) -->
-    <skip />
-    <!-- no translation found for day_of_week_shorter_sunday (1650484495176707638) -->
-    <skip />
-    <!-- no translation found for day_of_week_shorter_monday (9133193697786876074) -->
-    <skip />
-    <!-- no translation found for day_of_week_shorter_tuesday (4012095408481489663) -->
-    <skip />
-    <!-- no translation found for day_of_week_shorter_wednesday (6279056612496078470) -->
-    <skip />
-    <!-- no translation found for day_of_week_shorter_thursday (2748599403545071011) -->
-    <skip />
-    <!-- no translation found for day_of_week_shorter_friday (5037282109124849673) -->
-    <skip />
-    <!-- no translation found for day_of_week_shorter_saturday (3208167155877833783) -->
-    <skip />
-    <!-- no translation found for day_of_week_shortest_sunday (4683862964821549758) -->
-    <skip />
-    <!-- no translation found for day_of_week_shortest_monday (6701142261471667000) -->
-    <skip />
-    <!-- no translation found for day_of_week_shortest_tuesday (9098171980161292477) -->
-    <skip />
-    <!-- no translation found for day_of_week_shortest_wednesday (655049238289460956) -->
-    <skip />
-    <!-- no translation found for day_of_week_shortest_thursday (7816913627500884083) -->
-    <skip />
-    <!-- no translation found for day_of_week_shortest_friday (903301878650619398) -->
-    <skip />
-    <!-- no translation found for day_of_week_shortest_saturday (5359692489649817988) -->
-    <skip />
-    <!-- no translation found for month_long_january (7128497801440564337) -->
-    <skip />
-    <!-- no translation found for month_long_february (7808570514581190617) -->
-    <skip />
-    <!-- no translation found for month_long_march (2061328556983796034) -->
-    <skip />
-    <!-- no translation found for month_long_april (6575007959043269919) -->
-    <skip />
-    <!-- no translation found for month_long_may (8404051103463071121) -->
-    <skip />
-    <!-- no translation found for month_long_june (6255771619238859451) -->
-    <skip />
-    <!-- no translation found for month_long_july (4129177743136800884) -->
-    <skip />
-    <!-- no translation found for month_long_august (5494331003296804494) -->
-    <skip />
-    <!-- no translation found for month_long_september (2691137479752033087) -->
-    <skip />
-    <!-- no translation found for month_long_october (7501261567327243313) -->
-    <skip />
-    <!-- no translation found for month_long_november (8759690753068763664) -->
-    <skip />
-    <!-- no translation found for month_long_december (4505008719696569497) -->
-    <skip />
-    <!-- no translation found for month_medium_january (2315492772833932512) -->
-    <skip />
-    <!-- no translation found for month_medium_february (118412521324313430) -->
-    <skip />
-    <!-- no translation found for month_medium_march (5546835583839352358) -->
-    <skip />
-    <!-- no translation found for month_medium_april (7052559668687733702) -->
-    <skip />
-    <!-- no translation found for month_medium_may (2825303871720116018) -->
-    <skip />
-    <!-- no translation found for month_medium_june (829843667101495271) -->
-    <skip />
-    <!-- no translation found for month_medium_july (5029778226925324789) -->
-    <skip />
-    <!-- no translation found for month_medium_august (8851230594641162805) -->
-    <skip />
-    <!-- no translation found for month_medium_september (8420590486625304647) -->
-    <skip />
-    <!-- no translation found for month_medium_october (1787382806172930239) -->
-    <skip />
-    <!-- no translation found for month_medium_november (675513809622370603) -->
-    <skip />
-    <!-- no translation found for month_medium_december (2934948295928978783) -->
-    <skip />
-    <!-- no translation found for month_shortest_january (6070060405144675883) -->
-    <skip />
-    <!-- no translation found for month_shortest_february (5632605004902176653) -->
-    <skip />
-    <!-- no translation found for month_shortest_march (4304231552356086624) -->
-    <skip />
-    <!-- no translation found for month_shortest_april (1166434066469385532) -->
-    <skip />
-    <!-- no translation found for month_shortest_may (9131326028845529001) -->
-    <skip />
-    <!-- no translation found for month_shortest_june (1875723154506665289) -->
-    <skip />
-    <!-- no translation found for month_shortest_july (2003596275389810773) -->
-    <skip />
-    <!-- no translation found for month_shortest_august (9120245162625763214) -->
-    <skip />
-    <!-- no translation found for month_shortest_september (7980651111022693669) -->
-    <skip />
-    <!-- no translation found for month_shortest_october (3640405450427788312) -->
-    <skip />
-    <!-- no translation found for month_shortest_november (4002935318566146993) -->
-    <skip />
-    <!-- no translation found for month_shortest_december (6213739417171334040) -->
-    <skip />
-    <!-- no translation found for elapsed_time_short_format_mm_ss (1294409362352514646) -->
-    <skip />
-    <!-- no translation found for elapsed_time_short_format_h_mm_ss (2997059666628785039) -->
-    <skip />
-    <!-- no translation found for selectAll (691691810023908884) -->
-    <skip />
-    <!-- no translation found for cut (5845613239192595662) -->
-    <skip />
-    <!-- no translation found for cutAll (4474519683293791451) -->
-    <skip />
-    <!-- no translation found for copy (8603721575469529820) -->
-    <skip />
-    <!-- no translation found for copyAll (4777548804630476932) -->
-    <skip />
-    <!-- no translation found for paste (6458036735811828538) -->
-    <skip />
-    <!-- no translation found for copyUrl (5785708478767435812) -->
-    <skip />
-    <!-- no translation found for inputMethod (7911866729148111492) -->
-    <skip />
-    <!-- no translation found for editTextMenuTitle (3984253728638788023) -->
-    <skip />
-    <!-- no translation found for low_internal_storage_view_title (5997772070488639934) -->
-    <skip />
-    <!-- no translation found for low_internal_storage_view_text (2230118755295375293) -->
-    <skip />
-    <!-- no translation found for ok (4003878536083514869) -->
-    <skip />
-    <!-- no translation found for cancel (1527674037280267012) -->
-    <skip />
-    <!-- no translation found for yes (8185296114406773873) -->
-    <skip />
-    <!-- no translation found for no (2300685350903156262) -->
-    <skip />
-    <!-- no translation found for capital_on (8418242581217554942) -->
-    <skip />
-    <!-- no translation found for capital_off (8870368560477693851) -->
-    <skip />
-    <!-- no translation found for whichApplication (2828159696176255212) -->
-    <skip />
-    <!-- no translation found for alwaysUse (6433627451071144629) -->
-    <skip />
-    <!-- no translation found for clearDefaultHintMsg (5742432113023174321) -->
-    <skip />
-    <!-- no translation found for chooseActivity (7588691622928031978) -->
-    <skip />
-    <!-- no translation found for noApplications (4068560364116066745) -->
-    <skip />
-    <!-- no translation found for aerr_title (2654390351574026098) -->
-    <skip />
-    <!-- no translation found for aerr_application (4917288809565116720) -->
-    <skip />
-    <!-- no translation found for aerr_process (1273819861108073461) -->
-    <skip />
-    <!-- no translation found for anr_title (3305935690891435915) -->
-    <skip />
-    <!-- no translation found for anr_activity_application (1653036325679156678) -->
-    <skip />
-    <!-- no translation found for anr_activity_process (2674027618362070465) -->
-    <skip />
-    <!-- no translation found for anr_application_process (2163656674970221928) -->
-    <skip />
-    <!-- no translation found for anr_process (7747550780123472160) -->
-    <skip />
-    <!-- no translation found for force_close (9020954128872810669) -->
-    <skip />
-    <!-- no translation found for wait (7973775702304037058) -->
-    <skip />
-    <!-- no translation found for debug (857932504764728770) -->
-    <skip />
-    <!-- no translation found for sendText (6158329286172492543) -->
-    <skip />
-    <!-- no translation found for volume_ringtone (4121694816346562058) -->
-    <skip />
-    <!-- no translation found for volume_music (4869950240104717493) -->
-    <skip />
-    <!-- no translation found for volume_call (5723421277753250395) -->
-    <skip />
-    <!-- no translation found for volume_alarm (2752102730973081294) -->
-    <skip />
-    <!-- no translation found for volume_unknown (6908187627672375742) -->
-    <skip />
-    <!-- no translation found for ringtone_default (2873893375149093475) -->
-    <skip />
-    <!-- no translation found for ringtone_default_with_actual (5474076151665761913) -->
-    <skip />
-    <!-- no translation found for ringtone_silent (7477159279081654685) -->
-    <skip />
-    <!-- no translation found for ringtone_picker_title (7055241890764367884) -->
-    <skip />
-    <!-- no translation found for ringtone_unknown (6888219771401173795) -->
-    <skip />
-    <!-- no translation found for wifi_available:one (8168012881468888470) -->
-    <!-- no translation found for wifi_available:other (4666122955807117718) -->
-    <!-- no translation found for wifi_available_detailed:one (5107769161192143259) -->
-    <!-- no translation found for wifi_available_detailed:other (853347657960575809) -->
-    <!-- no translation found for select_character (3735110139249491726) -->
-    <skip />
-    <!-- no translation found for sms_control_default_app_name (7522184737840550841) -->
-    <skip />
-    <!-- no translation found for sms_control_title (2742400596989418394) -->
-    <skip />
-    <!-- no translation found for sms_control_message (3447126217666595989) -->
-    <skip />
-    <!-- no translation found for sms_control_yes (8839660939359273650) -->
-    <skip />
-    <!-- no translation found for sms_control_no (909756849988183801) -->
-    <skip />
-    <!-- no translation found for date_time_set (2495199891239480952) -->
-    <skip />
-    <!-- no translation found for default_permission_group (7742780381379652409) -->
-    <skip />
-    <!-- no translation found for no_permissions (85461124044682315) -->
-    <skip />
-    <!-- no translation found for perms_hide (4145325555929151849) -->
-    <skip />
-    <!-- no translation found for perms_show_all (6040194843455403173) -->
-    <skip />
-    <!-- no translation found for googlewebcontenthelper_loading (2140804350507245589) -->
-    <skip />
-    <!-- no translation found for usb_storage_title (8699631567051394409) -->
-    <skip />
-    <!-- no translation found for usb_storage_message (5344039189213308733) -->
-    <skip />
-    <!-- no translation found for usb_storage_button_mount (6700104384375121662) -->
-    <skip />
-    <!-- no translation found for usb_storage_button_unmount (465869657252626688) -->
-    <skip />
-    <!-- no translation found for usb_storage_error_message (3192564550748426087) -->
-    <skip />
-    <!-- no translation found for usb_storage_notification_title (6237028017872246940) -->
-    <skip />
-    <!-- no translation found for usb_storage_notification_message (7371717280517625905) -->
-    <skip />
-    <!-- no translation found for select_input_method (2658280517827502015) -->
-    <skip />
-    <!-- no translation found for fast_scroll_alphabet (1017432309285755759) -->
-    <skip />
-    <!-- no translation found for fast_scroll_numeric_alphabet (3092587363718901074) -->
-    <skip />
-    <!-- no translation found for candidates_style (7738463880139922176) -->
-    <skip />
-</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 37632f8e4491..e0c0a64ee7f5 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -817,6 +817,5 @@
     <skip />
     <!-- no translation found for permdesc_pkgUsageStats (891553695716752835) -->
     <skip />
-    <!-- no translation found for tutorial_double_tap_to_zoom_message (9111326385548696308) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 3015957a1039..d9c417434a30 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -818,6 +818,5 @@
     <skip />
     <!-- no translation found for permdesc_pkgUsageStats (891553695716752835) -->
     <skip />
-    <!-- no translation found for tutorial_double_tap_to_zoom_message (9111326385548696308) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 4cb3ee1c004c..d9cf3d5122ac 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1,765 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="byteShort">"B"</string>
-    <string name="kilobyteShort">"KB"</string>
-    <string name="megabyteShort">"MB"</string>
-    <string name="gigabyteShort">"GB"</string>
-    <string name="terabyteShort">"TB"</string>
-    <string name="petabyteShort">"PB"</string>
-    <string name="untitled">"&lt;untitled&gt;"</string>
-    <string name="ellipsis">"…"</string>
-    <string name="emptyPhoneNumber">"(No phone number)"</string>
-    <string name="unknownName">"(Unknown)"</string>
-    <string name="defaultVoiceMailAlphaTag">"Voicemail"</string>
-    <string name="defaultMsisdnAlphaTag">"MSISDN1"</string>
-    <string name="mmiError">"Connection problem or invalid MMI code."</string>
-    <string name="serviceEnabled">"Service was enabled."</string>
-    <string name="serviceEnabledFor">"Service was enabled for:"</string>
-    <string name="serviceDisabled">"Service has been disabled."</string>
-    <string name="serviceRegistered">"Registration was successful."</string>
-    <string name="serviceErased">"Erasure was successful."</string>
-    <string name="passwordIncorrect">"Incorrect password."</string>
-    <string name="mmiComplete">"MMI complete."</string>
-    <string name="badPin">"The old PIN you typed is not correct."</string>
-    <string name="badPuk">"The PUK you typed is not correct."</string>
-    <string name="mismatchPin">"The PINs you entered do not match."</string>
-    <string name="invalidPin">"Type a PIN that is 4 to 8 numbers."</string>
-    <!-- no translation found for needPuk (4788728144863892764) -->
-    <skip />
-    <string name="needPuk2">"Type PUK2 to unblock SIM card."</string>
-    <string name="ClipMmi">"Incoming Caller ID"</string>
-    <string name="ClirMmi">"Outgoing Caller ID"</string>
-    <string name="CfMmi">"Call forwarding"</string>
-    <string name="CwMmi">"Call waiting"</string>
-    <string name="BaMmi">"Call barring"</string>
-    <string name="PwdMmi">"Password change"</string>
-    <string name="PinMmi">"PIN change"</string>
-    <string name="CLIRDefaultOnNextCallOn">"Caller ID defaults to restricted. Next call: Restricted"</string>
-    <string name="CLIRDefaultOnNextCallOff">"Caller ID defaults to restricted. Next call: Not restricted"</string>
-    <string name="CLIRDefaultOffNextCallOn">"Caller ID defaults to not restricted. Next call: Restricted"</string>
-    <string name="CLIRDefaultOffNextCallOff">"Caller ID defaults to not restricted. Next call: Not restricted"</string>
-    <string name="serviceNotProvisioned">"Service not provisioned."</string>
-    <string name="CLIRPermanent">"The caller ID setting cannot be changed."</string>
-    <string name="serviceClassVoice">"Voice"</string>
-    <string name="serviceClassData">"Data"</string>
-    <string name="serviceClassFAX">"FAX"</string>
-    <string name="serviceClassSMS">"SMS"</string>
-    <string name="serviceClassDataAsync">"Async"</string>
-    <string name="serviceClassDataSync">"Sync"</string>
-    <string name="serviceClassPacket">"Packet"</string>
-    <string name="serviceClassPAD">"PAD"</string>
-    <string name="cfTemplateNotForwarded">"{0}: Not forwarded"</string>
-    <string name="cfTemplateForwarded">"{0}: {1}"</string>
-    <string name="cfTemplateForwardedTime">"{0}: {1} after {2} seconds"</string>
-    <string name="cfTemplateRegistered">"{0}: Not forwarded"</string>
-    <string name="cfTemplateRegisteredTime">"{0}: Not forwarded"</string>
-    <string name="httpErrorOk">"OK"</string>
-    <string name="httpError">"The Web page contains an error."</string>
-    <string name="httpErrorLookup">"The URL could not be found."</string>
-    <string name="httpErrorUnsupportedAuthScheme">"The site authentication scheme is not supported."</string>
-    <string name="httpErrorAuth">"Authentication was unsuccessful."</string>
-    <string name="httpErrorProxyAuth">"Authentication via the proxy server was unsuccessful."</string>
-    <string name="httpErrorConnect">"The connection to the server was unsuccessful."</string>
-    <string name="httpErrorIO">"The server failed to communicate. Try again later."</string>
-    <string name="httpErrorTimeout">"The connection to the server timed out."</string>
-    <string name="httpErrorRedirectLoop">"The page contains too many server redirects."</string>
-    <string name="httpErrorUnsupportedScheme">"The protocol is not supported."</string>
-    <string name="httpErrorFailedSslHandshake">"A secure connection could not be established."</string>
-    <string name="httpErrorBadUrl">"The page could not be opened because the URL is invalid."</string>
-    <string name="httpErrorFile">"The file could not be accessed."</string>
-    <string name="httpErrorFileNotFound">"The requested file was not found."</string>
-    <string name="httpErrorTooManyRequests">"Too many requests are being processed. Try again later."</string>
-    <string name="contentServiceSync">"Sync"</string>
-    <string name="contentServiceSyncNotificationTitle">"Sync"</string>
-    <string name="contentServiceTooManyDeletesNotificationDesc">"Too many %s deletes."</string>
-    <string name="low_memory">"Phone storage is full! Delete some files to free space."</string>
-    <string name="me">"Me"</string>
-    <string name="power_dialog">"Phone options"</string>
-    <string name="silent_mode">"Silent mode"</string>
-    <string name="turn_on_radio">"Turn on wireless"</string>
-    <string name="turn_off_radio">"Turn off wireless"</string>
-    <string name="screen_lock">"Screen lock"</string>
-    <string name="power_off">"Power off"</string>
-    <string name="shutdown_progress">"Shutting down…"</string>
-    <string name="shutdown_confirm">"Your phone will shut down."</string>
-    <string name="no_recent_tasks">"No recent applications."</string>
-    <string name="global_actions">"Phone options"</string>
-    <string name="global_action_lock">"Screen lock"</string>
-    <string name="global_action_power_off">"Power off"</string>
-    <string name="global_action_toggle_silent_mode">"Silent mode"</string>
-    <string name="global_action_silent_mode_on_status">"Sound is OFF"</string>
-    <string name="global_action_silent_mode_off_status">"Sound is ON"</string>
-    <string name="safeMode">"Safe mode"</string>
-    <string name="permgrouplab_costMoney">"Cost you money"</string>
-    <string name="permgroupdesc_costMoney">"Allow applications to do things that can cost you money."</string>
-    <string name="permgrouplab_messages">"Your messages"</string>
-    <string name="permgroupdesc_messages">"Read and write your SMS, e-mail, and other messages."</string>
-    <string name="permgrouplab_personalInfo">"Your personal information"</string>
-    <string name="permgroupdesc_personalInfo">"Direct access to your contacts and calendar stored on the phone."</string>
-    <string name="permgrouplab_location">"Your location"</string>
-    <string name="permgroupdesc_location">"Monitor your physical location"</string>
-    <string name="permgrouplab_network">"Network communication"</string>
-    <string name="permgroupdesc_network">"Allow applications to access various network features."</string>
-    <string name="permgrouplab_accounts">"Your Google accounts"</string>
-    <string name="permgroupdesc_accounts">"Access the available Google accounts."</string>
-    <string name="permgrouplab_hardwareControls">"Hardware controls"</string>
-    <string name="permgroupdesc_hardwareControls">"Direct access to hardware on the handset."</string>
-    <string name="permgrouplab_phoneCalls">"Phone calls"</string>
-    <string name="permgroupdesc_phoneCalls">"Monitor, record, and process phone calls."</string>
-    <string name="permgrouplab_systemTools">"System tools"</string>
-    <string name="permgroupdesc_systemTools">"Lower-level access and control of the system."</string>
-    <string name="permgrouplab_developmentTools">"Development tools"</string>
-    <string name="permgroupdesc_developmentTools">"Features only needed for application developers."</string>
-    <string name="permlab_statusBar">"disable or modify status bar"</string>
-    <string name="permdesc_statusBar">"Allows application to disable the status bar or add and remove system icons."</string>
-    <string name="permlab_expandStatusBar">"expand/collapse status bar"</string>
-    <string name="permdesc_expandStatusBar">"Allows application to expand or collapse the status bar."</string>
-    <string name="permlab_processOutgoingCalls">"intercept outgoing calls"</string>
-    <string name="permdesc_processOutgoingCalls">"Allows application to process outgoing calls and change the number to be dialed. Malicious applications may monitor, redirect, or prevent outgoing calls."</string>
-    <string name="permlab_receiveSms">"receive SMS"</string>
-    <string name="permdesc_receiveSms">"Allows application to receive and process SMS messages. Malicious applications may monitor your messages or delete them without showing them to you."</string>
-    <string name="permlab_receiveMms">"receive MMS"</string>
-    <string name="permdesc_receiveMms">"Allows application to receive and process MMS messages. Malicious applications may monitor your messages or delete them without showing them to you."</string>
-    <string name="permlab_sendSms">"send SMS messages"</string>
-    <string name="permdesc_sendSms">"Allows application to send SMS messages. Malicious applications may cost you money by sending messages without your confirmation."</string>
-    <string name="permlab_readSms">"read SMS or MMS"</string>
-    <string name="permdesc_readSms">"Allows application to read SMS messages stored on your phone or SIM card. Malicious applications may read your confidential messages."</string>
-    <string name="permlab_writeSms">"edit SMS or MMS"</string>
-    <string name="permdesc_writeSms">"Allows application to write to SMS messages stored on your phone or SIM card. Malicious applications may delete your messages."</string>
-    <string name="permlab_receiveWapPush">"receive WAP"</string>
-    <string name="permdesc_receiveWapPush">"Allows application to receive and process WAP messages. Malicious applications may monitor your messages or delete them without showing them to you."</string>
-    <string name="permlab_getTasks">"retrieve running applications"</string>
-    <string name="permdesc_getTasks">"Allows application to retrieve information about currently and recently running tasks. May allow malicious applications to discover private information about other applications."</string>
-    <string name="permlab_reorderTasks">"reorder running applications"</string>
-    <string name="permdesc_reorderTasks">"Allows an application to move tasks to the foreground and background. Malicious applications can force themselves to the front without your control."</string>
-    <string name="permlab_setDebugApp">"enable application debugging"</string>
-    <string name="permdesc_setDebugApp">"Allows an application to turn on debugging for another application. Malicious applications can use this to kill other applications."</string>
-    <string name="permlab_changeConfiguration">"change your UI settings"</string>
-    <string name="permdesc_changeConfiguration">"Allows an application to change the current configuration, such as the locale or overall font size."</string>
-    <string name="permlab_restartPackages">"restart other applications"</string>
-    <string name="permdesc_restartPackages">"Allows an application to forcibly restart other applications."</string>
-    <string name="permlab_setProcessForeground">"keep from being stopped"</string>
-    <!-- unknown placeholder BREAK in permdesc_setProcessForeground -->
-    <skip />
-    <string name="permlab_forceBack">"force application to close"</string>
-    <string name="permdesc_forceBack">"Allows an application to force any activity that is in the foreground to close and go back. Should never be needed for normal applications."</string>
-    <string name="permlab_dump">"retrieve system internal state"</string>
-    <string name="permdesc_dump">"Allows application to retrieve internal state of the system. Malicious applications may retrieve a wide variety of private and secure information that they should never normally need."</string>
-    <string name="permlab_addSystemService">"publish low-level services"</string>
-    <string name="permdesc_addSystemService">"Allows application to publish its own low-level system services. Malicious applications may hijack the system, and steal or corrupt any data on it."</string>
-    <string name="permlab_runSetActivityWatcher">"monitor and control all application launching"</string>
-    <string name="permdesc_runSetActivityWatcher">"Allows an application to monitor and control how the system launches activities. Malicious applications may completely compromise the system. This permission is only needed for development, never for normal phone usage."</string>
-    <string name="permlab_broadcastPackageRemoved">"send package removed broadcast"</string>
-    <string name="permdesc_broadcastPackageRemoved">"Allows an application to broadcast a notification that an application package has been removed. Malicious applications may use this to kill any other running application."</string>
-    <!-- no translation found for permlab_broadcastSmsReceived (1994692154847312518) -->
-    <skip />
-    <!-- no translation found for permdesc_broadcastSmsReceived (6072362543164841432) -->
-    <skip />
-    <!-- no translation found for permlab_broadcastWapPush (3070023012636951639) -->
-    <skip />
-    <!-- no translation found for permdesc_broadcastWapPush (726912255218924336) -->
-    <skip />
-    <string name="permlab_setProcessLimit">"limit number of running processes"</string>
-    <string name="permdesc_setProcessLimit">"Allows an application to control the maximum number of processes that will run. Never needed for normal applications."</string>
-    <string name="permlab_setAlwaysFinish">"make all background applications close"</string>
-    <string name="permdesc_setAlwaysFinish">"Allows an application to control whether activities are always finished as soon as they go to the background. Never needed for normal applications."</string>
-    <string name="permlab_fotaUpdate">"automatically install system updates"</string>
-    <string name="permdesc_fotaUpdate">"Allows an application to receive notifications about pending system updates and trigger their installation. Malicious applications may use this to corrupt the system with unauthorized updates, or generally interfere with the update process."</string>
-    <string name="permlab_batteryStats">"modify battery statistics"</string>
-    <string name="permdesc_batteryStats">"Allows the modification of collected battery statistics. Not for use by normal applications."</string>
-    <string name="permlab_internalSystemWindow">"display unauthorized windows"</string>
-    <string name="permdesc_internalSystemWindow">"Allows the creation of windows that are intended to be used by the internal system user interface. Not for use by normal applications."</string>
-    <string name="permlab_systemAlertWindow">"display system-level alerts"</string>
-    <string name="permdesc_systemAlertWindow">"Allows an application to show system alert windows. Malicious applications can take over the entire screen of the phone."</string>
-    <string name="permlab_setAnimationScale">"modify global animation speed"</string>
-    <string name="permdesc_setAnimationScale">"Allows an application to change the global animation speed (faster or slower animations) at any time."</string>
-    <string name="permlab_manageAppTokens">"manage application tokens"</string>
-    <string name="permdesc_manageAppTokens">"Allows applications to create and manage their own tokens, bypassing their normal Z-ordering. Should never be needed for normal applications."</string>
-    <string name="permlab_injectEvents">"press keys and control buttons"</string>
-    <string name="permdesc_injectEvents">"Allows an application to deliver its own input events (key presses, etc.) to other applications. Malicious applications can use this to take over the phone."</string>
-    <string name="permlab_readInputState">"record what you type and actions you take"</string>
-    <string name="permdesc_readInputState">"Allows applications to watch the keys you press even when interacting with another application (such as entering a password). Should never be needed for normal applications."</string>
-    <string name="permlab_setOrientation">"change screen orientation"</string>
-    <string name="permdesc_setOrientation">"Allows an application to change the rotation of the screen at any time. Should never be needed for normal applications."</string>
-    <string name="permlab_signalPersistentProcesses">"send Linux signals to applications"</string>
-    <string name="permdesc_signalPersistentProcesses">"Allows application to request that the supplied signal be sent to all persistent processes."</string>
-    <string name="permlab_persistentActivity">"make application always run"</string>
-    <!-- unknown placeholder BREAK in permdesc_persistentActivity -->
-    <skip />
-    <string name="permlab_deletePackages">"delete applications"</string>
-    <string name="permdesc_deletePackages">"Allows an application to delete Android packages. Malicious applications can use this to delete important applications."</string>
-    <string name="permlab_clearAppUserData">"delete other applications data"</string>
-    <string name="permdesc_clearAppUserData">"Allows an application to clear user data."</string>
-    <string name="permlab_deleteCacheFiles">"delete other applications cache"</string>
-    <string name="permdesc_deleteCacheFiles">"Allows an application to delete cache files."</string>
-    <string name="permlab_getPackageSize">"measure application storage space"</string>
-    <string name="permdesc_getPackageSize">"Allows an application to retrieve its code, data, and cache sizes"</string>
-    <string name="permlab_installPackages">"directly install applications"</string>
-    <string name="permdesc_installPackages">"Allows an application to install new or updated Android packages. Malicious applications can use this to add new applications with arbitrarily powerful permissions."</string>
-    <string name="permlab_clearAppCache">"delete all application cache data"</string>
-    <string name="permdesc_clearAppCache">"Allows an application to free phone storage by deleting files in application cache directory. Access is very restricted usually to system process."</string>
-    <string name="permlab_readLogs">"read system log files"</string>
-    <!-- unknown placeholder BREAK_0 in permdesc_readLogs -->
-    <skip />
-    <!-- no translation found for permlab_diagnostic (2955142476313469329) -->
-    <skip />
-    <!-- no translation found for permdesc_diagnostic (1282409892215520166) -->
-    <skip />
-    <string name="permlab_changeComponentState">"enable or disable application components"</string>
-    <string name="permdesc_changeComponentState">"Allows an application to change whether a component of another application is enabled or not. Malicious applications can use this to disable important phone capabilities. Care must be used with permission, as it is possible to get application components into an unusable, inconsistant, or unstable state."</string>
-    <string name="permlab_setPreferredApplications">"set preferred applications"</string>
-    <string name="permdesc_setPreferredApplications">"Allows an application to modify your preferred applications. This can allow malicious applications to silently change the applications that are run, spoofing your existing applications to collect private data from you."</string>
-    <string name="permlab_writeSettings">"modify global system settings"</string>
-    <string name="permdesc_writeSettings">"Allows an application to modify the systems settings data. Malicious applications can corrupt your systems configuration."</string>
-    <!-- no translation found for permlab_writeSecureSettings (4851801872124242319) -->
-    <skip />
-    <!-- no translation found for permdesc_writeSecureSettings (2080620249472761366) -->
-    <skip />
-    <!-- no translation found for permlab_writeGservices (296370685945777755) -->
-    <skip />
-    <!-- no translation found for permdesc_writeGservices (2496928471286495053) -->
-    <skip />
-    <string name="permlab_receiveBootCompleted">"automatically start at boot"</string>
-    <string name="permdesc_receiveBootCompleted">"Allows an application to have itself started as soon as the system has finished booting. This can make it take longer to start the phone and allow the application to slow down the overall phone by always running."</string>
-    <string name="permlab_broadcastSticky">"send sticky broadcast"</string>
-    <string name="permdesc_broadcastSticky">"Allows an application to send sticky broadcasts, which remain after the broadcast ends. Malicious applications can make the phone slow or unstable by causing it to use too much memory."</string>
-    <string name="permlab_readContacts">"read contact data"</string>
-    <string name="permdesc_readContacts">"Allows an application to read all of the contact (address) data stored on your phone. Malicious applications can use this to send your data to other people."</string>
-    <string name="permlab_writeContacts">"write contact data"</string>
-    <string name="permdesc_writeContacts">"Allows an application to modify the contact (address) data stored on your phone. Malicious applications can use this to erase or modify your contact data."</string>
-    <string name="permlab_writeOwnerData">"write owner data"</string>
-    <string name="permdesc_writeOwnerData">"Allows an application to modify the phone owner data stored on your phone. Malicious applications can use this to erase or modify owner data."</string>
-    <string name="permlab_readOwnerData">"read owner data"</string>
-    <string name="permdesc_readOwnerData">"Allows an application read the phone owner data stored on your phone. Malicious applications can use this to read phone owner data."</string>
-    <string name="permlab_readCalendar">"read calendar data"</string>
-    <string name="permdesc_readCalendar">"Allows an application to read all of the calendar events stored on your phone. Malicious applications can use this to send your calendar events to other people."</string>
-    <string name="permlab_writeCalendar">"write calendar data"</string>
-    <string name="permdesc_writeCalendar">"Allows an application to modify the calendar events stored on your phone. Malicious applications can use this to erase or modify your calendar data."</string>
-    <string name="permlab_accessMockLocation">"mock location sources for testing"</string>
-    <string name="permdesc_accessMockLocation">"Create mock location sources for testing. Malicious applications can use this to override the location and/or status returned by real location sources such as GPS or Network providers."</string>
-    <!-- no translation found for permlab_accessLocationExtraCommands (8291822077788811687) -->
-    <skip />
-    <!-- no translation found for permdesc_accessLocationExtraCommands (5135782633548630731) -->
-    <skip />
-    <string name="permlab_accessFineLocation">"fine (GPS) location"</string>
-    <string name="permdesc_accessFineLocation">"Access fine location sources such as the Global Positioning System on the phone, where available. Malicious applications can use this to determine where you are, and may consume additional battery power."</string>
-    <string name="permlab_accessCoarseLocation">"coarse (network-based) location"</string>
-    <string name="permdesc_accessCoarseLocation">"Access coarse location sources such as the cellular network database to determine an approximate phone location, where available. Malicious applications can use this to determine approximately where you are."</string>
-    <string name="permlab_accessSurfaceFlinger">"access SurfaceFlinger"</string>
-    <string name="permdesc_accessSurfaceFlinger">"Allows application to use SurfaceFlinger low-level features."</string>
-    <string name="permlab_readFrameBuffer">"read frame buffer"</string>
-    <string name="permdesc_readFrameBuffer">"Allows application to use read the content of the frame buffer."</string>
-    <string name="permlab_modifyAudioSettings">"change your audio settings"</string>
-    <string name="permdesc_modifyAudioSettings">"Allows application to modify global audio settings such as volume and routing."</string>
-    <string name="permlab_recordAudio">"record audio"</string>
-    <string name="permdesc_recordAudio">"Allows application to access the audio record path."</string>
-    <string name="permlab_camera">"take pictures"</string>
-    <string name="permdesc_camera">"Allows application to take pictures with the camera. This allows the application at any time to collect images the camera is seeing."</string>
-    <string name="permlab_brick">"permanently disable phone"</string>
-    <string name="permdesc_brick">"Allows the application to disable the entire phone permanently. This is very dangerous."</string>
-    <!-- no translation found for permlab_reboot (8844650672567077423) -->
-    <skip />
-    <!-- no translation found for permdesc_reboot (4704919552870918328) -->
-    <skip />
-    <string name="permlab_mount_unmount_filesystems">"mount and unmount filesystems"</string>
-    <string name="permdesc_mount_unmount_filesystems">"Allows the application to mount and unmount filesystems for removable storage."</string>
-    <string name="permlab_vibrate">"control vibrator"</string>
-    <string name="permdesc_vibrate">"Allows the application to control the vibrator."</string>
-    <string name="permlab_flashlight">"control flashlight"</string>
-    <string name="permdesc_flashlight">"Allows the application to control the flashlight."</string>
-    <string name="permlab_hardware_test">"test hardware"</string>
-    <string name="permdesc_hardware_test">"Allows the application to control various peripherals for the purpose of hardware testing."</string>
-    <string name="permlab_callPhone">"directly call phone numbers"</string>
-    <string name="permdesc_callPhone">"Allows the application to call phone numbers without your intervention. Malicious applications may cause unexpected calls on your phone bill. Note that this does not allow the application to call emergency numbers."</string>
-    <!-- no translation found for permlab_callPrivileged (2166923597287697159) -->
-    <skip />
-    <!-- no translation found for permdesc_callPrivileged (5109789447971735501) -->
-    <skip />
-    <!-- no translation found for permlab_locationUpdates (4216418293360456836) -->
-    <skip />
-    <!-- no translation found for permdesc_locationUpdates (7635814693478743648) -->
-    <skip />
-    <!-- no translation found for permlab_checkinProperties (2260796787386280708) -->
-    <skip />
-    <!-- no translation found for permdesc_checkinProperties (3508022022841741945) -->
-    <skip />
-    <string name="permlab_modifyPhoneState">"modify phone state"</string>
-    <string name="permdesc_modifyPhoneState">"Allows the application to control the phone features of the device. An application with this permission can switch networks, turn the phone radio on and off and the like without ever notifying you."</string>
-    <string name="permlab_readPhoneState">"read phone state"</string>
-    <string name="permdesc_readPhoneState">"Allows the application to access the phone features of the device. An application with this permission can determine the phone number of this phone, whether a call is active, the number that call is connected to and the like."</string>
-    <string name="permlab_wakeLock">"prevent phone from sleeping"</string>
-    <string name="permdesc_wakeLock">"Allows an application to prevent the phone from going to sleep."</string>
-    <string name="permlab_devicePower">"power phone on or off"</string>
-    <string name="permdesc_devicePower">"Allows the application to turn the phone on or off."</string>
-    <string name="permlab_factoryTest">"run in factory test mode"</string>
-    <string name="permdesc_factoryTest">"Run as a low-level manufacturer test, allowing complete access to the phone hardware. Only available when a phone is running in manufacturer test mode."</string>
-    <string name="permlab_setWallpaper">"set wallpaper"</string>
-    <string name="permdesc_setWallpaper">"Allows the application to set the system wallpaper."</string>
-    <string name="permlab_setWallpaperHints">"set wallpaper size hints"</string>
-    <string name="permdesc_setWallpaperHints">"Allows the application to set the system wallpaper size hints."</string>
-    <string name="permlab_masterClear">"reset system to factory defaults"</string>
-    <string name="permdesc_masterClear">"Allows an application to completely reset the system to its factory settings, erasing all data, configuration, and installed applications."</string>
-    <string name="permlab_setTimeZone">"set time zone"</string>
-    <string name="permdesc_setTimeZone">"Allows an application to change the phones time zone."</string>
-    <string name="permlab_getAccounts">"discover known accounts"</string>
-    <string name="permdesc_getAccounts">"Allows an application to get the list of accounts known by the phone."</string>
-    <string name="permlab_accessNetworkState">"view network state"</string>
-    <string name="permdesc_accessNetworkState">"Allows an application to view the state of all networks."</string>
-    <string name="permlab_createNetworkSockets">"full Internet access"</string>
-    <string name="permdesc_createNetworkSockets">"Allows an application to create network sockets."</string>
-    <!-- no translation found for permlab_writeApnSettings (3190585220761979369) -->
-    <skip />
-    <!-- no translation found for permdesc_writeApnSettings (4093875220468761052) -->
-    <skip />
-    <string name="permlab_changeNetworkState">"change network connectivity"</string>
-    <string name="permdesc_changeNetworkState">"Allows an application to change the state network connectivity."</string>
-    <string name="permlab_accessWifiState">"view Wi-Fi state"</string>
-    <string name="permdesc_accessWifiState">"Allows an application to view the information about the state of Wi-Fi."</string>
-    <string name="permlab_changeWifiState">"change Wi-Fi state"</string>
-    <string name="permdesc_changeWifiState">"Allows an application to connect to and disconnect from Wi-Fi access points, and to make changes to configured Wi-Fi networks."</string>
-    <string name="permlab_bluetoothAdmin">"bluetooth administration"</string>
-    <string name="permdesc_bluetoothAdmin">"Allows an application to configure the local Bluetooth phone, and to discover and pair with remote devices."</string>
-    <string name="permlab_bluetooth">"create Bluetooth connections"</string>
-    <string name="permdesc_bluetooth">"Allows an application to view configuration of the local Bluetooth phone, and to make and accept connections with paired devices."</string>
-    <string name="permlab_disableKeyguard">"disable keylock"</string>
-    <string name="permdesc_disableKeyguard">"Allows an application to disable the keylock and any associated password security. A legitimate example of this is the phone disabling the keylock when receiving an incoming phone call, then re-enabling the keylock when the call is finished."</string>
-    <string name="permlab_readSyncSettings">"read sync settings"</string>
-    <string name="permdesc_readSyncSettings">"Allows an application to read the sync settings, such as whether sync is enabled for Contacts."</string>
-    <string name="permlab_writeSyncSettings">"write sync settings"</string>
-    <string name="permdesc_writeSyncSettings">"Allows an application to modify the sync settings, such as whether sync is enabled for Contacts."</string>
-    <string name="permlab_readSyncStats">"read sync statistics"</string>
-    <string name="permdesc_readSyncStats">"Allows an application to reafocusd the sync stats; e.g., the history of syncs that have occurred."</string>
-    <!-- no translation found for permlab_subscribedFeedsRead (2043206814904506589) -->
-    <skip />
-    <!-- no translation found for permdesc_subscribedFeedsRead (6977343942680042449) -->
-    <skip />
-    <!-- no translation found for permlab_subscribedFeedsWrite (2556727307229571556) -->
-    <skip />
-    <!-- no translation found for permdesc_subscribedFeedsWrite (4134783294590266220) -->
-    <skip />
-    <!-- no translation found for phoneTypes:0 (6070018634209800981) -->
-    <!-- no translation found for phoneTypes:1 (1514509689885965711) -->
-    <!-- no translation found for phoneTypes:2 (497473201754095234) -->
-    <!-- no translation found for phoneTypes:3 (5554432614281047787) -->
-    <!-- no translation found for phoneTypes:4 (2222084401110150993) -->
-    <!-- no translation found for phoneTypes:5 (2290007103906353121) -->
-    <!-- no translation found for phoneTypes:6 (6930783706213719251) -->
-    <!-- no translation found for phoneTypes:7 (1326005699931077792) -->
-    <!-- no translation found for emailAddressTypes:0 (1540640638077615417) -->
-    <!-- no translation found for emailAddressTypes:1 (4252853367575831977) -->
-    <!-- no translation found for emailAddressTypes:2 (7158046581744435718) -->
-    <!-- no translation found for emailAddressTypes:3 (3625034471181268169) -->
-    <!-- no translation found for postalAddressTypes:0 (5732960259696659380) -->
-    <!-- no translation found for postalAddressTypes:1 (7132240704786130285) -->
-    <!-- no translation found for postalAddressTypes:2 (1317604357745852817) -->
-    <!-- no translation found for postalAddressTypes:3 (1582953598462826702) -->
-    <!-- no translation found for imAddressTypes:0 (7806620012096518833) -->
-    <!-- no translation found for imAddressTypes:1 (5748846799950672787) -->
-    <!-- no translation found for imAddressTypes:2 (6196536810275073680) -->
-    <!-- no translation found for imAddressTypes:3 (8519128375350623648) -->
-    <!-- no translation found for organizationTypes:0 (1299224825223821142) -->
-    <!-- no translation found for organizationTypes:1 (2455717447227299354) -->
-    <!-- no translation found for organizationTypes:2 (7027570839313438290) -->
-    <!-- no translation found for imProtocols:0 (3318725788774688043) -->
-    <!-- no translation found for imProtocols:1 (1787713387022932886) -->
-    <!-- no translation found for imProtocols:2 (6751174158442316516) -->
-    <!-- no translation found for imProtocols:3 (1151283347465052653) -->
-    <!-- no translation found for imProtocols:4 (2157980008878817934) -->
-    <!-- no translation found for imProtocols:5 (7836237460308230767) -->
-    <!-- no translation found for imProtocols:6 (1180789904462172516) -->
-    <!-- no translation found for imProtocols:7 (21955111672779862) -->
-    <string name="keyguard_password_enter_pin_code">"Enter PIN code:"</string>
-    <string name="keyguard_password_wrong_pin_code">"Incorrect PIN code!"</string>
-    <string name="keyguard_label_text">"To unlock, press Menu then 0."</string>
-    <string name="emergency_call_dialog_number_for_display">"Emergency number"</string>
-    <string name="lockscreen_carrier_default">"(No service)"</string>
-    <string name="lockscreen_screen_locked">"Screen locked"</string>
-    <string name="lockscreen_instructions_when_pattern_enabled">"Press Menu to unlock or place emergency call."</string>
-    <string name="lockscreen_instructions_when_pattern_disabled">"Press Menu to unlock."</string>
-    <string name="lockscreen_pattern_instructions">"Draw pattern to unlock:"</string>
-    <string name="lockscreen_emergency_call">"Emergency call"</string>
-    <string name="lockscreen_pattern_correct">"Correct!"</string>
-    <string name="lockscreen_pattern_wrong">"Sorry, try again:"</string>
-    <string name="lockscreen_plugged_in">"Charging (<xliff:g id="NUMBER">%d%%</xliff:g>)"</string>
-    <string name="lockscreen_low_battery">"Connect your charger."</string>
-    <string name="lockscreen_missing_sim_message_short">"No SIM card."</string>
-    <string name="lockscreen_missing_sim_message">"No SIM card in phone."</string>
-    <string name="lockscreen_missing_sim_instructions">"Please insert a SIM card."</string>
-    <!-- no translation found for lockscreen_network_locked_message (323609607922245071) -->
-    <skip />
-    <string name="lockscreen_sim_puk_locked_message">"SIM card is PUK-locked."</string>
-    <string name="lockscreen_sim_puk_locked_instructions">"Please contact Customer Care."</string>
-    <string name="lockscreen_sim_locked_message">"SIM card is locked."</string>
-    <string name="lockscreen_sim_unlock_progress_dialog_message">"Unlocking SIM card…"</string>
-    <string name="lockscreen_too_many_failed_attempts_dialog_message">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%d</xliff:g> times. "\n\n"Please try again in <xliff:g id="NUMBER_1">%d</xliff:g> seconds."</string>
-    <string name="lockscreen_failed_attempts_almost_glogin">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%d</xliff:g> times. After <xliff:g id="NUMBER_1">%d</xliff:g> more unsuccessful attempts, you will be asked to unlock your phone using your Google sign-in."\n\n" Please try again in <xliff:g id="NUMBER_2">%d</xliff:g> seconds."</string>
-    <string name="lockscreen_too_many_failed_attempts_countdown">"Try again in <xliff:g id="NUMBER">%d</xliff:g> seconds."</string>
-    <string name="lockscreen_forgot_pattern_button_text">"Forgot pattern?"</string>
-    <string name="lockscreen_glogin_too_many_attempts">"Too many pattern attempts!"</string>
-    <string name="lockscreen_glogin_instructions">"To unlock,"\n"sign in with your Google account:"</string>
-    <string name="lockscreen_glogin_username_hint">"Username (email)"</string>
-    <string name="lockscreen_glogin_password_hint">"Password"</string>
-    <string name="lockscreen_glogin_submit_button">"Sign in"</string>
-    <string name="lockscreen_glogin_invalid_input">"Invalid username or password."</string>
-    <!-- unknown placeholder FORMAT in status_bar_time_format -->
-    <skip />
-    <!-- no translation found for hour_minute_ampm (1850330605794978742) -->
-    <skip />
-    <!-- no translation found for hour_minute_cap_ampm (1122840227537374196) -->
-    <skip />
-    <!-- no translation found for hour_ampm (7665432130905376251) -->
-    <skip />
-    <!-- no translation found for hour_cap_ampm (3600295014648400268) -->
-    <skip />
-    <string name="status_bar_clear_all_button">"Clear notifications"</string>
-    <string name="status_bar_no_notifications_title">"No notifications"</string>
-    <string name="status_bar_ongoing_events_title">"Ongoing"</string>
-    <string name="status_bar_latest_events_title">"Notifications"</string>
-    <string name="battery_status_text_percent_format">"<xliff:g id="NUMBER">%d</xliff:g>"</string>
-    <string name="battery_status_charging">"Charging…"</string>
-    <string name="battery_low_title">"Please connect charger"</string>
-    <string name="battery_low_subtitle">"The battery is getting low:"</string>
-    <string name="battery_low_percent_format">"less than <xliff:g id="NUMBER">%d%%</xliff:g> remaining."</string>
-    <string name="factorytest_failed">"Factory test failed"</string>
-    <string name="factorytest_not_system">"The FACTORY_TEST action is only supported for packages installed in /system/app."</string>
-    <string name="factorytest_no_action">"No package was found that provides the FACTORY_TEST action."</string>
-    <string name="factorytest_reboot">"Reboot"</string>
-    <string name="save_password_label">"Confirm"</string>
-    <string name="save_password_message">"Do you want the browser to remember this password?"</string>
-    <string name="save_password_notnow">"Not now"</string>
-    <string name="save_password_remember">"Remember"</string>
-    <string name="save_password_never">"Never"</string>
-    <string name="open_permission_deny">"You do not have permission to open this page."</string>
-    <string name="text_copied">"Text copied to clipboard."</string>
-    <string name="more_item_label">"More"</string>
-    <string name="prepend_shortcut_label">"Menu+"</string>
-    <!-- no translation found for menu_space_shortcut_label (194586306440382711) -->
-    <skip />
-    <!-- no translation found for menu_enter_shortcut_label (7214761412193519345) -->
-    <skip />
-    <!-- no translation found for menu_delete_shortcut_label (2854936426194985313) -->
-    <skip />
-    <string name="search_go">"Search"</string>
-    <string name="today">"Today"</string>
-    <string name="yesterday">"Yesterday"</string>
-    <string name="tomorrow">"Tomorrow"</string>
-    <string name="oneMonthDurationPast">"1 month ago"</string>
-    <!-- no translation found for beforeOneMonthDurationPast (7578100953282866827) -->
-    <skip />
-    <!-- no translation found for num_seconds_ago:one (7416512229671810725) -->
-    <!-- no translation found for num_seconds_ago:other (8138756910300398447) -->
-    <!-- no translation found for num_minutes_ago:one (8620869479299420562) -->
-    <!-- no translation found for num_minutes_ago:other (5065488162050522741) -->
-    <!-- no translation found for num_hours_ago:one (853404611989669641) -->
-    <!-- no translation found for num_hours_ago:other (3558873784561756849) -->
-    <!-- no translation found for num_days_ago:one (4222479980812128212) -->
-    <!-- no translation found for num_days_ago:other (5445701370433601703) -->
-    <!-- no translation found for in_num_seconds:one (4253290037777327003) -->
-    <!-- no translation found for in_num_seconds:other (1280033870920841404) -->
-    <!-- no translation found for in_num_minutes:one (1487585791027953091) -->
-    <!-- no translation found for in_num_minutes:other (6274204576475209932) -->
-    <!-- no translation found for in_num_hours:one (6501470863235186391) -->
-    <!-- no translation found for in_num_hours:other (4415358752953289251) -->
-    <!-- no translation found for in_num_days:one (5608475533104443893) -->
-    <!-- no translation found for in_num_days:other (3827193006163842267) -->
-    <string name="preposition_for_date">"on %s"</string>
-    <string name="preposition_for_time">"at %s"</string>
-    <string name="preposition_for_year">"in %s"</string>
-    <string name="day">"day"</string>
-    <string name="days">"days"</string>
-    <string name="hour">"hour"</string>
-    <string name="hours">"hours"</string>
-    <string name="minute">"min"</string>
-    <string name="minutes">"mins"</string>
-    <string name="second">"sec"</string>
-    <string name="seconds">"secs"</string>
-    <string name="week">"week"</string>
-    <string name="weeks">"weeks"</string>
-    <string name="year">"year"</string>
-    <string name="years">"years"</string>
-    <string name="sunday">"Sunday"</string>
-    <string name="monday">"Monday"</string>
-    <string name="tuesday">"Tuesday"</string>
-    <string name="wednesday">"Wednesday"</string>
-    <string name="thursday">"Thursday"</string>
-    <string name="friday">"Friday"</string>
-    <string name="saturday">"Saturday"</string>
-    <string name="every_weekday">"Every weekday (Mon–Fri)"</string>
-    <string name="daily">"Daily"</string>
-    <string name="weekly">"Weekly on <xliff:g id="DAY">%s</xliff:g>"</string>
-    <string name="monthly">"Monthly"</string>
-    <string name="yearly">"Yearly"</string>
-    <string name="VideoView_error_title">"Cannot play video"</string>
-    <string name="VideoView_error_text_unknown">"Sorry, this video cannot be played."</string>
-    <string name="VideoView_error_button">"OK"</string>
-    <string name="am">"AM"</string>
-    <string name="pm">"PM"</string>
-    <!-- unknown placeholder FORMAT in numeric_date -->
-    <skip />
-    <!-- unknown placeholder FORMAT in wday1_date1_time1_wday2_date2_time2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in wday1_date1_wday2_date2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in date1_time1_date2_time2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in date1_date2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in time1_time2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in time_wday_date -->
-    <skip />
-    <!-- unknown placeholder FORMAT in wday_date -->
-    <skip />
-    <!-- unknown placeholder FORMAT in time_date -->
-    <skip />
-    <!-- unknown placeholder FORMAT in time_wday -->
-    <skip />
-    <!-- no translation found for full_date_month_first (6011143962222283357) -->
-    <skip />
-    <!-- no translation found for full_date_day_first (8621594762705478189) -->
-    <skip />
-    <!-- no translation found for medium_date_month_first (48990963718825728) -->
-    <skip />
-    <!-- no translation found for medium_date_day_first (2898992016440387123) -->
-    <skip />
-    <!-- no translation found for twelve_hour_time_format (6015557937879492156) -->
-    <skip />
-    <!-- no translation found for twenty_four_hour_time_format (5176807998669709535) -->
-    <skip />
-    <string name="noon">"noon"</string>
-    <string name="Noon">"Noon"</string>
-    <string name="midnight">"midnight"</string>
-    <string name="Midnight">"Midnight"</string>
-    <!-- unknown placeholder FORMAT in month_day -->
-    <skip />
-    <!-- unknown placeholder FORMAT in month -->
-    <skip />
-    <!-- unknown placeholder FORMAT in month_day_year -->
-    <skip />
-    <!-- unknown placeholder FORMAT in month_year -->
-    <skip />
-    <!-- no translation found for time_of_day (8375993139317154157) -->
-    <skip />
-    <!-- no translation found for date_and_time (9197690194373107109) -->
-    <skip />
-    <!-- unknown placeholder FORMAT in same_year_md1_md2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in same_year_wday1_md1_wday2_md2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in same_year_mdy1_mdy2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in same_year_wday1_mdy1_wday2_mdy2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in same_year_md1_time1_md2_time2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in same_year_wday1_md1_time1_wday2_md2_time2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in same_year_mdy1_time1_mdy2_time2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in same_year_wday1_mdy1_time1_wday2_mdy2_time2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in numeric_md1_md2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in numeric_wday1_md1_wday2_md2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in numeric_mdy1_mdy2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in numeric_wday1_mdy1_wday2_mdy2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in numeric_md1_time1_md2_time2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in numeric_wday1_md1_time1_wday2_md2_time2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in numeric_mdy1_time1_mdy2_time2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in numeric_wday1_mdy1_time1_wday2_mdy2_time2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in same_month_md1_md2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in same_month_wday1_md1_wday2_md2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in same_month_mdy1_mdy2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in same_month_wday1_mdy1_wday2_mdy2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in same_month_md1_time1_md2_time2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in same_month_wday1_md1_time1_wday2_md2_time2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in same_month_mdy1_time1_mdy2_time2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in same_month_wday1_mdy1_time1_wday2_mdy2_time2 -->
-    <skip />
-    <!-- unknown placeholder FORMAT in abbrev_month_day_year -->
-    <skip />
-    <!-- unknown placeholder FORMAT in abbrev_month_year -->
-    <skip />
-    <!-- unknown placeholder FORMAT in abbrev_month_day -->
-    <skip />
-    <!-- unknown placeholder FORMAT in abbrev_month -->
-    <skip />
-    <string name="day_of_week_long_sunday">"Sunday"</string>
-    <string name="day_of_week_long_monday">"Monday"</string>
-    <string name="day_of_week_long_tuesday">"Tuesday"</string>
-    <string name="day_of_week_long_wednesday">"Wednesday"</string>
-    <string name="day_of_week_long_thursday">"Thursday"</string>
-    <string name="day_of_week_long_friday">"Friday"</string>
-    <string name="day_of_week_long_saturday">"Saturday"</string>
-    <string name="day_of_week_medium_sunday">"Sun"</string>
-    <string name="day_of_week_medium_monday">"Mon"</string>
-    <string name="day_of_week_medium_tuesday">"Tue"</string>
-    <string name="day_of_week_medium_wednesday">"Wed"</string>
-    <string name="day_of_week_medium_thursday">"Thu"</string>
-    <string name="day_of_week_medium_friday">"Fri"</string>
-    <string name="day_of_week_medium_saturday">"Sat"</string>
-    <string name="day_of_week_short_sunday">"Su"</string>
-    <string name="day_of_week_short_monday">"Mo"</string>
-    <string name="day_of_week_short_tuesday">"Tu"</string>
-    <string name="day_of_week_short_wednesday">"We"</string>
-    <string name="day_of_week_short_thursday">"Th"</string>
-    <string name="day_of_week_short_friday">"Fr"</string>
-    <string name="day_of_week_short_saturday">"Sa"</string>
-    <string name="day_of_week_shorter_sunday">"Su"</string>
-    <string name="day_of_week_shorter_monday">"M"</string>
-    <string name="day_of_week_shorter_tuesday">"Tu"</string>
-    <string name="day_of_week_shorter_wednesday">"W"</string>
-    <string name="day_of_week_shorter_thursday">"Th"</string>
-    <string name="day_of_week_shorter_friday">"F"</string>
-    <string name="day_of_week_shorter_saturday">"Sa"</string>
-    <string name="day_of_week_shortest_sunday">"S"</string>
-    <string name="day_of_week_shortest_monday">"M"</string>
-    <string name="day_of_week_shortest_tuesday">"T"</string>
-    <string name="day_of_week_shortest_wednesday">"W"</string>
-    <string name="day_of_week_shortest_thursday">"T"</string>
-    <string name="day_of_week_shortest_friday">"F"</string>
-    <string name="day_of_week_shortest_saturday">"S"</string>
-    <string name="month_long_january">"January"</string>
-    <string name="month_long_february">"February"</string>
-    <string name="month_long_march">"March"</string>
-    <string name="month_long_april">"April"</string>
-    <string name="month_long_may">"May"</string>
-    <string name="month_long_june">"June"</string>
-    <string name="month_long_july">"July"</string>
-    <string name="month_long_august">"August"</string>
-    <string name="month_long_september">"September"</string>
-    <string name="month_long_october">"October"</string>
-    <string name="month_long_november">"November"</string>
-    <string name="month_long_december">"December"</string>
-    <string name="month_medium_january">"Jan"</string>
-    <string name="month_medium_february">"Feb"</string>
-    <string name="month_medium_march">"Mar"</string>
-    <string name="month_medium_april">"Apr"</string>
-    <string name="month_medium_may">"May"</string>
-    <string name="month_medium_june">"Jun"</string>
-    <string name="month_medium_july">"Jul"</string>
-    <string name="month_medium_august">"Aug"</string>
-    <string name="month_medium_september">"Sep"</string>
-    <string name="month_medium_october">"Oct"</string>
-    <string name="month_medium_november">"Nov"</string>
-    <string name="month_medium_december">"Dec"</string>
-    <string name="month_shortest_january">"J"</string>
-    <string name="month_shortest_february">"F"</string>
-    <string name="month_shortest_march">"M"</string>
-    <string name="month_shortest_april">"A"</string>
-    <string name="month_shortest_may">"M"</string>
-    <string name="month_shortest_june">"J"</string>
-    <string name="month_shortest_july">"J"</string>
-    <string name="month_shortest_august">"A"</string>
-    <string name="month_shortest_september">"S"</string>
-    <string name="month_shortest_october">"O"</string>
-    <string name="month_shortest_november">"N"</string>
-    <string name="month_shortest_december">"D"</string>
-    <!-- unknown placeholder FORMAT in elapsed_time_short_format_mm_ss -->
-    <skip />
-    <!-- unknown placeholder FORMAT in elapsed_time_short_format_h_mm_ss -->
-    <skip />
-    <string name="selectAll">"Select all"</string>
-    <string name="cut">"Cut"</string>
-    <string name="cutAll">"Cut all"</string>
-    <string name="copy">"Copy"</string>
-    <string name="copyAll">"Copy all"</string>
-    <string name="paste">"Paste"</string>
-    <string name="copyUrl">"Copy URL"</string>
-    <!-- no translation found for inputMethod (7911866729148111492) -->
-    <skip />
-    <!-- no translation found for editTextMenuTitle (3984253728638788023) -->
-    <skip />
-    <string name="low_internal_storage_view_title">"Low on space"</string>
-    <string name="low_internal_storage_view_text">"Your phone is running low on internal storage space."</string>
-    <string name="ok">"OK"</string>
-    <string name="cancel">"Cancel"</string>
-    <string name="yes">"OK"</string>
-    <string name="no">"Cancel"</string>
-    <string name="capital_on">"ON"</string>
-    <string name="capital_off">"OFF"</string>
-    <string name="whichApplication">"Complete action using"</string>
-    <string name="alwaysUse">"Use by default for this action."</string>
-    <string name="clearDefaultHintMsg">"Clear default in Home Settings &gt; Applications &gt; Manage applications."</string>
-    <string name="chooseActivity">"Select an action"</string>
-    <string name="noApplications">"No applications can perform this action."</string>
-    <string name="aerr_title">"Sorry!"</string>
-    <string name="aerr_application">"The application <xliff:g id="APPLICATION">%1$s</xliff:g> (process <xliff:g id="PROCESS">%2$s</xliff:g>) has stopped unexpectedly. Please try again."</string>
-    <string name="aerr_process">"The process <xliff:g id="PROCESS">%1$s</xliff:g> has stopped unexpectedly. Please try again."</string>
-    <string name="anr_title">"Application unresponsive"</string>
-    <string name="anr_activity_application">"Activity <xliff:g id="ACTIVITY">%1$s</xliff:g> (in application <xliff:g id="APPLICATION">%2$s</xliff:g>) is not responding."</string>
-    <string name="anr_activity_process">"Activity <xliff:g id="ACTIVITY">%1$s</xliff:g> (in process <xliff:g id="PROCESS">%2$s</xliff:g>) is not responding."</string>
-    <string name="anr_application_process">"Application <xliff:g id="APPLICATION">%1$s</xliff:g> (in process <xliff:g id="PROCESS">%2$s</xliff:g>) is not responding."</string>
-    <string name="anr_process">"Process <xliff:g id="PROCESS">%1$s</xliff:g> is not responding."</string>
-    <string name="force_close">"Force close"</string>
-    <string name="wait">"Wait"</string>
-    <string name="debug">"Debug"</string>
-    <string name="sendText">"Select an action for text"</string>
-    <string name="volume_ringtone">"Ringer volume"</string>
-    <string name="volume_music">"Music/video volume"</string>
-    <string name="volume_call">"In-call volume"</string>
-    <string name="volume_alarm">"Alarm volume"</string>
-    <string name="volume_unknown">"Volume"</string>
-    <string name="ringtone_default">"Default ringtone"</string>
-    <string name="ringtone_default_with_actual">"Default ringtone (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
-    <string name="ringtone_silent">"Silent"</string>
-    <string name="ringtone_picker_title">"Select a ringtone"</string>
-    <string name="ringtone_unknown">"Unknown ringtone"</string>
-    <!-- no translation found for wifi_available:one (8168012881468888470) -->
-    <!-- no translation found for wifi_available:other (4666122955807117718) -->
-    <!-- no translation found for wifi_available_detailed:one (5107769161192143259) -->
-    <!-- no translation found for wifi_available_detailed:other (853347657960575809) -->
-    <string name="select_character">"Select character to insert"</string>
-    <!-- no translation found for sms_control_default_app_name (7522184737840550841) -->
-    <skip />
-    <string name="sms_control_title">"Sending SMS messages"</string>
-    <string name="sms_control_message">"A large number of SMS messages are being sent. Select \"OK\" to continue, or \"Cancel\" to stop sending."</string>
-    <string name="sms_control_yes">"OK"</string>
-    <string name="sms_control_no">"Cancel"</string>
-    <string name="date_time_set">"Set"</string>
-    <string name="default_permission_group">"Default"</string>
-    <string name="no_permissions">"No permissions required"</string>
-    <!-- no translation found for perms_hide (4145325555929151849) -->
-    <skip />
-    <!-- no translation found for perms_show_all (6040194843455403173) -->
-    <skip />
-    <!-- no translation found for googlewebcontenthelper_loading (2140804350507245589) -->
-    <skip />
-    <!-- no translation found for usb_storage_title (8699631567051394409) -->
-    <skip />
-    <!-- no translation found for usb_storage_message (5344039189213308733) -->
-    <skip />
-    <!-- no translation found for usb_storage_button_mount (6700104384375121662) -->
-    <skip />
-    <!-- no translation found for usb_storage_button_unmount (465869657252626688) -->
-    <skip />
-    <!-- no translation found for usb_storage_error_message (3192564550748426087) -->
-    <skip />
-    <!-- no translation found for usb_storage_notification_title (6237028017872246940) -->
-    <skip />
-    <!-- no translation found for usb_storage_notification_message (7371717280517625905) -->
-    <skip />
-    <!-- no translation found for select_input_method (2658280517827502015) -->
-    <skip />
-    <!-- no translation found for fast_scroll_alphabet (1017432309285755759) -->
-    <skip />
-    <!-- no translation found for fast_scroll_numeric_alphabet (3092587363718901074) -->
-    <skip />
-    <!-- no translation found for candidates_style (7738463880139922176) -->
-    <skip />
+    <string name="byteShort">B</string>
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index f8881b6f4dbc..dc1744552739 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -817,6 +817,5 @@
     <skip />
     <!-- no translation found for permdesc_pkgUsageStats (891553695716752835) -->
     <skip />
-    <!-- no translation found for tutorial_double_tap_to_zoom_message (9111326385548696308) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 47f1bf49dad5..95e30528a109 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -817,6 +817,5 @@
     <skip />
     <!-- no translation found for permdesc_pkgUsageStats (891553695716752835) -->
     <skip />
-    <!-- no translation found for tutorial_double_tap_to_zoom_message (9111326385548696308) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 710c49340ce4..2cf7b43b2cf3 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -817,6 +817,5 @@
     <skip />
     <!-- no translation found for permdesc_pkgUsageStats (891553695716752835) -->
     <skip />
-    <!-- no translation found for tutorial_double_tap_to_zoom_message (9111326385548696308) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 0eba7f55144d..24e3cb6e7cad 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -558,12 +558,12 @@
     <!-- no translation found for relative_time (1818557177829411417) -->
     <skip />
     <string name="time_wday">"<xliff:g id="WEEKDAY">%2$s</xliff:g>、<xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
-    <string name="full_date_month_first">"<xliff:g id="YEAR">yyyy</xliff:g>\'å¹´\'<xliff:g id="MONTH">MMMM</xliff:g><xliff:g id="DAY">d</xliff:g>\'æ—¥\'"</string>
-    <string name="full_date_day_first">"<xliff:g id="YEAR">yyyy</xliff:g>\'å¹´\'<xliff:g id="MONTH">MMMM</xliff:g><xliff:g id="DAY">d</xliff:g>\'æ—¥\'"</string>
-    <string name="medium_date_month_first">"<xliff:g id="YEAR">yyyy</xliff:g>\'å¹´\'<xliff:g id="MONTH">MMM</xliff:g><xliff:g id="DAY">d</xliff:g>\'æ—¥\'"</string>
-    <string name="medium_date_day_first">"<xliff:g id="YEAR">yyyy</xliff:g>\'å¹´\'<xliff:g id="MONTH">MMM</xliff:g><xliff:g id="DAY">d</xliff:g>\'æ—¥\'"</string>
-    <string name="twelve_hour_time_format">"<xliff:g id="HOUR">h</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g> <xliff:g id="AMPM">a</xliff:g>"</string>
-    <string name="twenty_four_hour_time_format">"<xliff:g id="HOUR">H</xliff:g>:<xliff:g id="MINUTE">mm</xliff:g>"</string>
+    <string name="full_date_month_first">"<xliff:g id="YEAR">yyyy</xliff:g>'\'\'å¹´\'\''<xliff:g id="MONTH">MMMM</xliff:g><xliff:g id="DAY">d</xliff:g>'\'\'æ—¥\'\''"</string>
+    <string name="full_date_day_first">"<xliff:g id="YEAR">yyyy</xliff:g>'\'\'å¹´\'\''<xliff:g id="MONTH">MMMM</xliff:g><xliff:g id="DAY">d</xliff:g>'\'\'æ—¥\'\''"</string>
+    <string name="medium_date_month_first">"<xliff:g id="YEAR">yyyy</xliff:g>'\'\'å¹´\'\''<xliff:g id="MONTH">MMM</xliff:g><xliff:g id="DAY">d</xliff:g>'\'\'æ—¥\'\''"</string>
+    <string name="medium_date_day_first">"<xliff:g id="YEAR">yyyy</xliff:g>'\'\'å¹´\'\''<xliff:g id="MONTH">MMM</xliff:g><xliff:g id="DAY">d</xliff:g>'\'\'æ—¥\'\''"</string>
+    <string name="twelve_hour_time_format">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
+    <string name="twenty_four_hour_time_format">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
     <string name="noon">"正午"</string>
     <string name="Noon">"正午"</string>
     <string name="midnight">"午前0時"</string>
@@ -573,7 +573,8 @@
     <!-- no translation found for month (7026169712234774086) -->
     <skip />
     <string name="month_day_year">"<xliff:g id="YEAR">%Y</xliff:g>å¹´<xliff:g id="MONTH">%B</xliff:g><xliff:g id="DAY">%-d</xliff:g>æ—¥"</string>
-    <string name="month_year">"<xliff:g id="YEAR">%Y</xliff:g>å¹´ <xliff:g id="MONTH">%B</xliff:g>"</string>
+    <!-- no translation found for month_year (9219019380312413367) -->
+    <skip />
     <string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
     <string name="date_and_time">"<xliff:g id="YEAR">%Y</xliff:g>å¹´<xliff:g id="MONTH">%B</xliff:g><xliff:g id="DAY">%-d</xliff:g>æ—¥<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
     <string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g><xliff:g id="DAY1">%3$s</xliff:g>日~<xliff:g id="MONTH2">%7$s</xliff:g><xliff:g id="DAY2">%8$s</xliff:g>日"</string>
@@ -816,6 +817,5 @@
     <skip />
     <!-- no translation found for permdesc_pkgUsageStats (891553695716752835) -->
     <skip />
-    <!-- no translation found for tutorial_double_tap_to_zoom_message (9111326385548696308) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 4272684f8bb6..140f32f16527 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -817,6 +817,5 @@
     <skip />
     <!-- no translation found for permdesc_pkgUsageStats (891553695716752835) -->
     <skip />
-    <!-- no translation found for tutorial_double_tap_to_zoom_message (9111326385548696308) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 9f4955773541..466f2b175619 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -262,10 +262,8 @@
     <string name="permdesc_reboot">"Lar applikasjonen tvinge telefonen til å starte på nytt."</string>
     <string name="permlab_mount_unmount_filesystems">"montere og avmontere filsystemer"</string>
     <string name="permdesc_mount_unmount_filesystems">"Lar applikasjonen montere og avmontere filsystemer for uttagbar lagring."</string>
-    <!-- no translation found for permlab_mount_format_filesystems (5523285143576718981) -->
-    <skip />
-    <!-- no translation found for permdesc_mount_format_filesystems (574060044906047386) -->
-    <skip />
+    <string name="permlab_mount_format_filesystems">"formatere ekstern lagringsplass"</string>
+    <string name="permdesc_mount_format_filesystems">"Lar applikasjonen formatere ekstern lagringsplass."</string>
     <string name="permlab_vibrate">"kontrollere vibratoren"</string>
     <string name="permdesc_vibrate">"Lar applikasjonen kontrollere vibratoren."</string>
     <string name="permlab_flashlight">"kontrollere lommelykten"</string>
@@ -280,10 +278,8 @@
     <string name="permdesc_locationUpdates">"Lar applikasjonen slå av/på varsling om plasseringsendringer fra radioen. Ikke ment for vanlige applikasjoner."</string>
     <string name="permlab_checkinProperties">"få tilgang til egenskaper for innsjekking"</string>
     <string name="permdesc_checkinProperties">"Gir lese- og skrivetilgang til egenskaper lastet opp av innsjekkingstjenesten. Ikke ment for vanlige applikasjoner."</string>
-    <!-- no translation found for permlab_bindGadget (2519859363977647275) -->
-    <skip />
-    <!-- no translation found for permdesc_bindGadget (7865866514555126333) -->
-    <skip />
+    <string name="permlab_bindGadget">"velg gadgeter"</string>
+    <string name="permdesc_bindGadget">"Lar applikasjonen fortelle systemet hvilke gadgeter som kan brukes av hvilke applikasjoner. Med denne rettigheten kan applikasjoner andre applikasjoner tilgang til personlig data. Ikke ment for vanlige applikasjoner."</string>
     <string name="permlab_modifyPhoneState">"endre telefontilstand"</string>
     <string name="permdesc_modifyPhoneState">"Lar applikasjonen kontrollere telefonfunksjonaliteten i enheten. En applikasjon med denne rettigheten kan endre nettverk, slå telefonens radio av eller på og lignende uten noensinne å varsle brukeren."</string>
     <string name="permlab_readPhoneState">"lese telefontilstand"</string>
@@ -312,10 +308,8 @@
     <string name="permdesc_writeApnSettings">"Lar applikasjonen to endre APN-innstillinger slik som mellomtjener eller port for hvilket som helst aksesspunkt."</string>
     <string name="permlab_changeNetworkState">"endre nettverkskonnektivitet"</string>
     <string name="permdesc_changeNetworkState">"Lar applikasjonen endre tilstanden til nettverkskonnektivitet."</string>
-    <!-- no translation found for permlab_changeBackgroundDataSetting (1400666012671648741) -->
-    <skip />
-    <!-- no translation found for permdesc_changeBackgroundDataSetting (1001482853266638864) -->
-    <skip />
+    <string name="permlab_changeBackgroundDataSetting">"endre innstilling for bakgrunnsdata"</string>
+    <string name="permdesc_changeBackgroundDataSetting">"Lar applikasjonen endre innstillingen for bakgrunnsdata."</string>
     <string name="permlab_accessWifiState">"se tilstand for trådløse nettverk"</string>
     <string name="permdesc_accessWifiState">"Lar applikasjonen få se informasjon om tilstanden til de trådløse nettene."</string>
     <string name="permlab_changeWifiState">"endre tilstand for trådløse nettverk"</string>
@@ -336,14 +330,10 @@
     <string name="permdesc_subscribedFeedsRead">"Lar applikasjonen hente detaljer om hvilke nyhetskilder som synkroniseres."</string>
     <string name="permlab_subscribedFeedsWrite">"endre abonnement på nyhetskilder"</string>
     <string name="permdesc_subscribedFeedsWrite">"Lar applikasjonen redigere hvilke nyhetskilder som synkroniseres. Dette kan gi en ondsinnet applikasjon tilgang til å endre hvilke nyhetskilder som synkroniseres."</string>
-    <!-- no translation found for permlab_readDictionary (432535716804748781) -->
-    <skip />
-    <!-- no translation found for permdesc_readDictionary (1082972603576360690) -->
-    <skip />
-    <!-- no translation found for permlab_writeDictionary (6703109511836343341) -->
-    <skip />
-    <!-- no translation found for permdesc_writeDictionary (2241256206524082880) -->
-    <skip />
+    <string name="permlab_readDictionary">"lese brukerdefinert ordliste"</string>
+    <string name="permdesc_readDictionary">"Lar applikasjonen lese private ord, navn og uttrykk som brukeren har lagret i den brukerdefinerte ordlisten."</string>
+    <string name="permlab_writeDictionary">"skrive til brukerdefinert ordliste"</string>
+    <string name="permdesc_writeDictionary">"Lar applikasjonen skrive nye ord til den brukerdefinerte ordlisten."</string>
   <string-array name="phoneTypes">
     <item>"Hjemme"</item>
     <item>"Mobil"</item>
@@ -440,12 +430,9 @@
     <string name="factorytest_not_system">"The FACTORY_TEST action is only supported for packages installed in /system/app."</string>
     <string name="factorytest_no_action">"No package was found that provides the FACTORY_TEST action."</string>
     <string name="factorytest_reboot">"Reboot"</string>
-    <!-- no translation found for js_dialog_title (8143918455087008109) -->
-    <skip />
-    <!-- no translation found for js_dialog_title_default (6961903213729667573) -->
-    <skip />
-    <!-- no translation found for js_dialog_before_unload (1901675448179653089) -->
-    <skip />
+    <string name="js_dialog_title">"Siden \\\'<xliff:g id="TITLE">%s</xliff:g>\\\' sier:"</string>
+    <string name="js_dialog_title_default">"JavaScript"</string>
+    <string name="js_dialog_before_unload">"Naviger bort fra denne siden?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"Velg OK for å fortsette, eller Avbryt for å forbli på denne siden."</string>
     <string name="save_password_label">"Bekreft"</string>
     <string name="save_password_message">"Ønsker du at nettleseren skal huske dette passordet?"</string>
     <string name="save_password_notnow">"Ikke nå"</string>
@@ -569,17 +556,15 @@
     <string name="time_wday_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g> <xliff:g id="DATE">%3$s</xliff:g>"</string>
     <string name="wday_date">"<xliff:g id="WEEKDAY">%2$s</xliff:g> <xliff:g id="DATE">%3$s</xliff:g>"</string>
     <string name="time_date">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="DATE">%3$s</xliff:g>"</string>
-    <!-- no translation found for date_time (6104442718633642836) -->
-    <skip />
-    <!-- no translation found for relative_time (1818557177829411417) -->
-    <skip />
+    <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="time_wday">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, <xliff:g id="WEEKDAY">%2$s</xliff:g>"</string>
-    <string name="full_date_month_first">"<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>'., '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
-    <string name="full_date_day_first">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
-    <string name="medium_date_month_first">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
-    <string name="medium_date_day_first">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
-    <string name="twelve_hour_time_format">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
-    <string name="twenty_four_hour_time_format">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
+    <string name="full_date_month_first">"<xliff:g id="MONTH">MMMM</xliff:g>'\\\'\'\\\'\' \\\'\'\\\'\''<xliff:g id="DAY">d</xliff:g>'\\\'\'\\\'\'., \\\'\'\\\'\''<xliff:g id="YEAR">yyyy</xliff:g>"</string>
+    <string name="full_date_day_first">"<xliff:g id="DAY">d</xliff:g>'\\\'\'\\\'\'. \\\'\'\\\'\''<xliff:g id="MONTH">MMMM</xliff:g>'\\\'\'\\\'\' \\\'\'\\\'\''<xliff:g id="YEAR">yyyy</xliff:g>"</string>
+    <string name="medium_date_month_first">"<xliff:g id="MONTH">MMM</xliff:g>'\\\'\'\\\'\' \\\'\'\\\'\''<xliff:g id="DAY">d</xliff:g>'\\\'\'\\\'\', \\\'\'\\\'\''<xliff:g id="YEAR">yyyy</xliff:g>"</string>
+    <string name="medium_date_day_first">"<xliff:g id="DAY">d</xliff:g>'\\\'\'\\\'\'. \\\'\'\\\'\''<xliff:g id="MONTH">MMM</xliff:g>'\\\'\'\\\'\' \\\'\'\\\'\''<xliff:g id="YEAR">yyyy</xliff:g>"</string>
+    <string name="twelve_hour_time_format">"<xliff:g id="HOUR">h</xliff:g>'\\\'\'\\\'\':\\\'\'\\\'\''<xliff:g id="MINUTE">mm</xliff:g>'\\\'\'\\\'\' \\\'\'\\\'\''<xliff:g id="AMPM">a</xliff:g>"</string>
+    <string name="twenty_four_hour_time_format">"<xliff:g id="HOUR">H</xliff:g>'\\\'\'\\\'\':\\\'\'\\\'\''<xliff:g id="MINUTE">mm</xliff:g>"</string>
     <string name="noon">"middag"</string>
     <string name="Noon">"Middag"</string>
     <string name="midnight">"midnatt"</string>
@@ -596,18 +581,14 @@
     <string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>"</string>
     <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
     <string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string>
-    <!-- no translation found for same_year_wday1_mdy1_wday2_mdy2 (1345612987720788874) -->
-    <skip />
+    <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string>
     <string name="same_year_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string>
     <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string>
-    <!-- no translation found for same_year_mdy1_time1_mdy2_time2 (2959466512848524124) -->
-    <skip />
-    <!-- no translation found for same_year_wday1_mdy1_time1_wday2_mdy2_time2 (5129735426508861428) -->
-    <skip />
+    <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string>
     <string name="numeric_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>.<xliff:g id="MONTH1">%2$s</xliff:g>. – <xliff:g id="DAY2">%8$s</xliff:g>.<xliff:g id="MONTH2">%7$s</xliff:g>."</string>
     <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>.<xliff:g id="MONTH1">%2$s</xliff:g>. – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>.<xliff:g id="MONTH2">%7$s</xliff:g>."</string>
-    <!-- no translation found for numeric_mdy1_mdy2 (3933951218078638018) -->
-    <skip />
+    <string name="numeric_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>.<xliff:g id="MONTH1">%2$s</xliff:g>.<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>.<xliff:g id="MONTH2">%7$s</xliff:g>.<xliff:g id="YEAR2">%9$s</xliff:g>"</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>.<xliff:g id="MONTH1">%2$s</xliff:g>.<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>.<xliff:g id="MONTH2">%7$s</xliff:g>.<xliff:g id="YEAR2">%9$s</xliff:g>"</string>
     <string name="numeric_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>.<xliff:g id="MONTH1">%2$s</xliff:g>. <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>.<xliff:g id="MONTH2">%7$s</xliff:g>. <xliff:g id="TIME2">%10$s</xliff:g>"</string>
     <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>.<xliff:g id="MONTH1">%2$s</xliff:g>. <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>.<xliff:g id="MONTH2">%7$s</xliff:g>. <xliff:g id="TIME2">%10$s</xliff:g>"</string>
@@ -711,8 +692,7 @@
     <string name="paste">"Lim inn"</string>
     <string name="copyUrl">"Kopier URL"</string>
     <string name="inputMethod">"Inndatametode"</string>
-    <!-- no translation found for addToDictionary (726256909274177272) -->
-    <skip />
+    <string name="addToDictionary">"Legg \\\"%s\\\" til ordlisten"</string>
     <string name="editTextMenuTitle">"Rediger tekst"</string>
     <string name="low_internal_storage_view_title">"Lite plass"</string>
     <string name="low_internal_storage_view_text">"Det begynner å bli lite lagringsplass på telefonen."</string>
@@ -720,8 +700,7 @@
     <string name="cancel">"Avbryt"</string>
     <string name="yes">"OK"</string>
     <string name="no">"Avbryt"</string>
-    <!-- no translation found for dialog_alert_title (2049658708609043103) -->
-    <skip />
+    <string name="dialog_alert_title">"Merk"</string>
     <string name="capital_on">"PÃ¥"</string>
     <string name="capital_off">"Av"</string>
     <string name="whichApplication">"Complete action using"</string>
@@ -745,8 +724,7 @@
     <string name="volume_music">"Medievolum"</string>
     <string name="volume_music_hint_playing_through_bluetooth">"Spiller over Bluetooth"</string>
     <string name="volume_call">"Samtalevolum"</string>
-    <!-- no translation found for volume_bluetooth_call (2002891926351151534) -->
-    <skip />
+    <string name="volume_bluetooth_call">"Bluetooth-samtalevolum"</string>
     <string name="volume_alarm">"Alarmvolum"</string>
     <string name="volume_notification">"Varslingsvolum"</string>
     <string name="volume_unknown">"Volum"</string>
@@ -766,7 +744,7 @@
     <string name="select_character">"Sett inn tegn"</string>
     <string name="sms_control_default_app_name">"Ukjent applikasjon"</string>
     <string name="sms_control_title">"Sending SMS messages"</string>
-    <string name="sms_control_message">"A large number of SMS messages are being sent. Select \\\"OK\\\" to continue, or \\\"Cancel\\\" to stop sending."</string>
+    <string name="sms_control_message">"A large number of SMS messages are being sent. Select \\\\\\\"OK\\\\\\\" to continue, or \\\\\\\"Cancel\\\\\\\" to stop sending."</string>
     <string name="sms_control_yes">"OK"</string>
     <string name="sms_control_no">"Avbryt"</string>
     <string name="date_time_set">"Lagre"</string>
@@ -776,67 +754,39 @@
     <string name="perms_show_all"><b>"Vis alle"</b></string>
     <string name="googlewebcontenthelper_loading">"Laster inn…"</string>
     <string name="usb_storage_title">"USB koblet til"</string>
-    <string name="usb_storage_message">"Du har koblet telefonen til en datamaskin via USB. Velg \\\"Monter\\\" dersom du ønsker å kopiere filer mellom datmaskinen og minnekortet i telefonen."</string>
+    <string name="usb_storage_message">"Du har koblet telefonen til en datamaskin via USB. Velg \\\\\\\"Monter\\\\\\\" dersom du ønsker å kopiere filer mellom datmaskinen og minnekortet i telefonen."</string>
     <string name="usb_storage_button_mount">"Monter"</string>
     <string name="usb_storage_button_unmount">"Ikke monter"</string>
     <string name="usb_storage_error_message">"Det oppsto et problem med å bruke minnekortet ditt for USB-lagring."</string>
     <string name="usb_storage_notification_title">"USB tilkoblet"</string>
     <string name="usb_storage_notification_message">"Velg om du ønsker å kopiere filer til/fra en datamaskin."</string>
-    <!-- no translation found for usb_storage_stop_notification_title (2336058396663516017) -->
-    <skip />
-    <!-- no translation found for usb_storage_stop_notification_message (2591813490269841539) -->
-    <skip />
-    <!-- no translation found for usb_storage_stop_title (6014127947456185321) -->
-    <skip />
-    <!-- no translation found for usb_storage_stop_message (2390958966725232848) -->
-    <skip />
-    <!-- no translation found for usb_storage_stop_button_mount (1181858854166273345) -->
-    <skip />
-    <!-- no translation found for usb_storage_stop_button_unmount (3774611918660582898) -->
-    <skip />
-    <!-- no translation found for usb_storage_stop_error_message (3917317248440072084) -->
-    <skip />
-    <!-- no translation found for extmedia_format_title (8663247929551095854) -->
-    <skip />
-    <!-- no translation found for extmedia_format_message (3621369962433523619) -->
-    <skip />
-    <!-- no translation found for extmedia_format_button_format (4131064560127478695) -->
-    <skip />
+    <string name="usb_storage_stop_notification_title">"Slå av USB-lagring"</string>
+    <string name="usb_storage_stop_notification_message">"Velg for å slå av USB-lagring."</string>
+    <string name="usb_storage_stop_title">"Slå av USB-lagring"</string>
+    <string name="usb_storage_stop_message">"Før du slår av USB-lagring, sjekk at du har avmontert enheten i USB-verten. Velg «slå av» for å slå av USB-lagring."</string>
+    <string name="usb_storage_stop_button_mount">"Slå av"</string>
+    <string name="usb_storage_stop_button_unmount">"Avbryt"</string>
+    <string name="usb_storage_stop_error_message">"Det oppsto et problem under avslutningen av USB-lagring. Sjekk at USB-verten har avmontert og prøv igjen."</string>
+    <string name="extmedia_format_title">"Formatere minnekort"</string>
+    <string name="extmedia_format_message">"Er du sikker på at du ønsker å formatere minnekortet? Alle data på kortet vil gå tapt."</string>
+    <string name="extmedia_format_button_format">"Format"</string>
     <string name="select_input_method">"Velg inndatametode"</string>
     <string name="fast_scroll_alphabet">"ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string>
     <string name="fast_scroll_numeric_alphabet">"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string>
-    <!-- unknown quoting pattern: original -1, translation 1 -->
-    <string name="candidates_style">"TAG_FONT"<u>"kandidater"</u>"u&amp;gt;CLOSE_FONT"</string>
-    <!-- no translation found for ext_media_checking_notification_title (5457603418970994050) -->
-    <skip />
-    <!-- no translation found for ext_media_checking_notification_message (4747432538578886744) -->
-    <skip />
-    <!-- no translation found for ext_media_nofs_notification_title (780477838241212997) -->
-    <skip />
-    <!-- no translation found for ext_media_nofs_notification_message (1312266820092958014) -->
-    <skip />
-    <!-- no translation found for ext_media_unmountable_notification_title (6410723906019100189) -->
-    <skip />
-    <!-- no translation found for ext_media_unmountable_notification_message (2679412884290061775) -->
-    <skip />
-    <!-- no translation found for ext_media_badremoval_notification_title (6872152882604407837) -->
-    <skip />
-    <!-- no translation found for ext_media_badremoval_notification_message (7260183293747448241) -->
-    <skip />
-    <!-- no translation found for ext_media_safe_unmount_notification_title (6729801130790616200) -->
-    <skip />
-    <!-- no translation found for ext_media_safe_unmount_notification_message (7613960686747592770) -->
-    <skip />
-    <!-- no translation found for ext_media_nomedia_notification_title (8902518030404381318) -->
-    <skip />
-    <!-- no translation found for ext_media_nomedia_notification_message (4205117227342822275) -->
-    <skip />
-    <!-- no translation found for activity_list_empty (4168820609403385789) -->
-    <skip />
-    <!-- no translation found for permlab_pkgUsageStats (8787352074326748892) -->
-    <skip />
-    <!-- no translation found for permdesc_pkgUsageStats (891553695716752835) -->
-    <skip />
-    <!-- no translation found for tutorial_double_tap_to_zoom_message (9111326385548696308) -->
-    <skip />
+    <string name="candidates_style">"TAG_FONT"<u>"kandidater"</u>"CLOSE_FONT"</string>
+    <string name="ext_media_checking_notification_title">"Forbereder minnekort"</string>
+    <string name="ext_media_checking_notification_message">"Sjekker for feil"</string>
+    <string name="ext_media_nofs_notification_title">"Tomt minnekort"</string>
+    <string name="ext_media_nofs_notification_message">"Minnekortet er tomt eller bruker et ustøttet filsystem."</string>
+    <string name="ext_media_unmountable_notification_title">"Skadet minnekort"</string>
+    <string name="ext_media_unmountable_notification_message">"Minnekortet er skadet. Det kan være du må formatere kortet."</string>
+    <string name="ext_media_badremoval_notification_title">"Minnekortet ble tatt ut uventet"</string>
+    <string name="ext_media_badremoval_notification_message">"Avmonter minnekortet før det tas ut, for å unngå datatap."</string>
+    <string name="ext_media_safe_unmount_notification_title">"Trygt å ta ut minnekort"</string>
+    <string name="ext_media_safe_unmount_notification_message">"Minnekortet kan nå trygt tas ut."</string>
+    <string name="ext_media_nomedia_notification_title">"Minnekortet ble tatt ut"</string>
+    <string name="ext_media_nomedia_notification_message">"Minnekortet ble tatt ut. Sett inn et nytt minnekort for å øke lagringsplassen."</string>
+    <string name="activity_list_empty">"Fant ingen tilsvarende aktiviteter"</string>
+    <string name="permlab_pkgUsageStats">"oppdater statistikk over komponentbruk"</string>
+    <string name="permdesc_pkgUsageStats">"Tillater endring av innsamlet data om bruk av komponenter. Ikke ment for vanlige applikasjoner."</string>
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 7ce4c66c95ff..a2810a1f1527 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -817,6 +817,5 @@
     <skip />
     <!-- no translation found for permdesc_pkgUsageStats (891553695716752835) -->
     <skip />
-    <!-- no translation found for tutorial_double_tap_to_zoom_message (9111326385548696308) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 03c4f8b25a7b..12f16163e210 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -817,6 +817,5 @@
     <skip />
     <!-- no translation found for permdesc_pkgUsageStats (891553695716752835) -->
     <skip />
-    <!-- no translation found for tutorial_double_tap_to_zoom_message (9111326385548696308) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index d25ab8da5783..76a358dddc21 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -817,6 +817,5 @@
     <skip />
     <!-- no translation found for permdesc_pkgUsageStats (891553695716752835) -->
     <skip />
-    <!-- no translation found for tutorial_double_tap_to_zoom_message (9111326385548696308) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 447fccdaba67..13d4e9c69697 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -817,6 +817,5 @@
     <skip />
     <!-- no translation found for permdesc_pkgUsageStats (891553695716752835) -->
     <skip />
-    <!-- no translation found for tutorial_double_tap_to_zoom_message (9111326385548696308) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index e97c142be81d..419e8c2eb4b8 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -817,6 +817,5 @@
     <skip />
     <!-- no translation found for permdesc_pkgUsageStats (891553695716752835) -->
     <skip />
-    <!-- no translation found for tutorial_double_tap_to_zoom_message (9111326385548696308) -->
     <skip />
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 3f21303b6b39..593d1ff2a8a2 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1056,6 +1056,10 @@
              enabled for events such as clicking and touching. -->
         <attr name="soundEffectsEnabled" format="boolean" />
 
+        <!-- Boolean that controls whether a view should have haptic feedback
+             enabled for events such as long presses. -->
+        <attr name="hapticFeedbackEnabled" format="boolean" />
+
     </declare-styleable>
 
     <!-- Attributes that can be used with a {@link android.view.ViewGroup} or any
@@ -2035,8 +2039,18 @@
             <enum name="line" value="2" />
             <enum name="ring" value="3" />
         </attr>
+        <!-- Inner radius of the ring expressed as a ratio of the ring's width. For instance,
+             if innerRadiusRatio=9, then the inner radius equals the ring's width divided by 9.
+             This value is ignored if innerRadius is defined. Default value is 9. -->
         <attr name="innerRadiusRatio" format="float" />
+        <!-- Thickness of the ring expressed as a ratio of the ring's width. For instance,
+             if thicknessRatio=3, then the thickness equals the ring's width divided by 3.
+             This value is ignored if innerRadius is defined. Default value is 3. -->
         <attr name="thicknessRatio" format="float" />
+        <!-- Inner radius of the ring. When defined, innerRadiusRatio is ignored. -->
+        <attr name="innerRadius" format="dimension" />
+        <!-- Thickness of the ring. When defined, thicknessRatio is ignored. -->
+        <attr name="thickness" format="dimension" />
         <attr name="useLevel" />
     </declare-styleable>
     
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 103158511bdb..9175f31abca5 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1001,6 +1001,9 @@
   <public type="attr" name="content" id="0x0101025b" />
   <public type="attr" name="animateOnClick" id="0x0101025c" />
   <public type="attr" name="configure" id="0x0101025d" />
+  <public type="attr" name="hapticFeedbackEnabled" id="0x0101025e" />
+  <public type="attr" name="innerRadius" id="0x0101025f" />
+  <public type="attr" name="thickness" id="0x01010260" />
 
   <!-- The part of the UI shown by an
        {@link android.inputmethodservice.InputMethodService} that contains the
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 4700b93161d5..11749967016d 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2263,8 +2263,7 @@
     <string name="permdesc_pkgUsageStats">Allows the modification of collected component usage statistics. Not for use by normal applications.</string>
 
     <!-- Shown in the tutorial for double tap to zoom. -->
-    <string name="tutorial_double_tap_to_zoom_message">Congratulations on downloading the Android software update.  This update includes a number of great new features for you to enjoy.  One major improvement we've made is to how you zoom.  Now, when you want to zoom, just double tap on the screen.  This will bring up a zoom widget.  Drag the widget's handle clockwise to zoom in, and counter-clockwise to zoom out.</string>
-
+    <string name="tutorial_double_tap_to_zoom_message_short">Double tap to zoom</string>
 </resources>
 
 
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 82cb795deccb..3db45f0daa08 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -47,7 +47,9 @@ import java.io.IOException;
  * @attr ref android.R.styleable#GradientDrawable_visible
  * @attr ref android.R.styleable#GradientDrawable_shape
  * @attr ref android.R.styleable#GradientDrawable_innerRadiusRatio
+ * @attr ref android.R.styleable#GradientDrawable_innerRadius
  * @attr ref android.R.styleable#GradientDrawable_thicknessRatio
+ * @attr ref android.R.styleable#GradientDrawable_thickness
  * @attr ref android.R.styleable#GradientDrawable_useLevel
  * @attr ref android.R.styleable#GradientDrawableSize_width
  * @attr ref android.R.styleable#GradientDrawableSize_height
@@ -121,6 +123,8 @@ public class GradientDrawable extends Drawable {
     private Paint mLayerPaint;    // internal, used if we use saveLayer()
     private boolean mRectIsDirty;   // internal state
     private boolean mMutated;
+    private Path mRingPath;
+    private boolean mPathIsDirty;
 
     /**
      * Controls how the gradient is oriented relative to the drawable's bounds
@@ -213,6 +217,7 @@ public class GradientDrawable extends Drawable {
     }
     
     public void setShape(int shape) {
+        mRingPath = null;
         mGradientState.setShape(shape);
     }
 
@@ -248,14 +253,12 @@ public class GradientDrawable extends Drawable {
         // remember the alpha values, in case we temporarily overwrite them
         // when we modulate them with mAlpha
         final int prevFillAlpha = mFillPaint.getAlpha();
-        final int prevStrokeAlpha = mStrokePaint != null ?
-                                        mStrokePaint.getAlpha() : 0;
+        final int prevStrokeAlpha = mStrokePaint != null ? mStrokePaint.getAlpha() : 0;
         // compute the modulate alpha values
         final int currFillAlpha = modulateAlpha(prevFillAlpha);
         final int currStrokeAlpha = modulateAlpha(prevStrokeAlpha);
 
-        final boolean haveStroke = currStrokeAlpha > 0 &&
-                                   mStrokePaint.getStrokeWidth() > 0;
+        final boolean haveStroke = currStrokeAlpha > 0 && mStrokePaint.getStrokeWidth() > 0;
         final boolean haveFill = currFillAlpha > 0;
         final GradientState st = mGradientState;
         /*  we need a layer iff we're drawing both a fill and stroke, and the
@@ -264,7 +267,7 @@ public class GradientDrawable extends Drawable {
             of the fill (if any) without worrying about blending artifacts.
          */
          final boolean useLayer = haveStroke && haveFill && st.mShape != LINE &&
-                                  currStrokeAlpha < 255;
+                 currStrokeAlpha < 255;
 
         /*  Drawing with a layer is slower than direct drawing, but it
             allows us to apply paint effects like alpha and colorfilter to
@@ -336,10 +339,10 @@ public class GradientDrawable extends Drawable {
                 break;
             }
             case RING:
-                Path ring = buildRing(st);
-                canvas.drawPath(ring, mFillPaint);
+                Path path = buildRing(st);
+                canvas.drawPath(path, mFillPaint);
                 if (haveStroke) {
-                    canvas.drawPath(ring, mStrokePaint);
+                    canvas.drawPath(path, mStrokePaint);
                 }
                 break;
         }
@@ -355,6 +358,9 @@ public class GradientDrawable extends Drawable {
     }
     
     private Path buildRing(GradientState st) {
+        if (mRingPath != null && (!st.mUseLevelForShape || !mPathIsDirty)) return mRingPath;
+        mPathIsDirty = false;
+
         float sweep = st.mUseLevelForShape ? (360.0f * getLevel() / 10000.0f) : 360f;
         
         RectF bounds = new RectF(mRect);
@@ -362,9 +368,11 @@ public class GradientDrawable extends Drawable {
         float x = bounds.width() / 2.0f;
         float y = bounds.height() / 2.0f;
 
-        float thickness = bounds.width() / st.mThickness;
+        float thickness = st.mThickness != -1 ?
+                st.mThickness : bounds.width() / st.mThicknessRatio;
         // inner radius
-        float radius = bounds.width() / st.mInnerRadius;
+        float radius = st.mInnerRadius != -1 ?
+                st.mInnerRadius : bounds.width() / st.mInnerRadiusRatio;
 
         RectF innerBounds = new RectF(bounds);
         innerBounds.inset(x - radius, y - radius);
@@ -372,27 +380,33 @@ public class GradientDrawable extends Drawable {
         bounds = new RectF(innerBounds);
         bounds.inset(-thickness, -thickness);
 
-        Path path = new Path();
+        if (mRingPath == null) {
+            mRingPath = new Path();
+        } else {
+            mRingPath.reset();            
+        }
+
+        final Path ringPath = mRingPath;
         // arcTo treats the sweep angle mod 360, so check for that, since we
         // think 360 means draw the entire oval
         if (sweep < 360 && sweep > -360) {
-            path.setFillType(Path.FillType.EVEN_ODD);
+            ringPath.setFillType(Path.FillType.EVEN_ODD);
             // inner top
-            path.moveTo(x + radius, y);
+            ringPath.moveTo(x + radius, y);
             // outer top
-            path.lineTo(x + radius + thickness, y);
+            ringPath.lineTo(x + radius + thickness, y);
             // outer arc
-            path.arcTo(bounds, 0.0f, sweep, false);
+            ringPath.arcTo(bounds, 0.0f, sweep, false);
             // inner arc
-            path.arcTo(innerBounds, sweep, -sweep, false);
-            path.close();
+            ringPath.arcTo(innerBounds, sweep, -sweep, false);
+            ringPath.close();
         } else {
             // add the entire ovals
-            path.addOval(bounds, Path.Direction.CW);
-            path.addOval(innerBounds, Path.Direction.CCW);
+            ringPath.addOval(bounds, Path.Direction.CW);
+            ringPath.addOval(innerBounds, Path.Direction.CCW);
         }
 
-        return path;
+        return ringPath;
     }
 
     public void setColor(int argb) {
@@ -430,6 +444,8 @@ public class GradientDrawable extends Drawable {
     @Override
     protected void onBoundsChange(Rect r) {
         super.onBoundsChange(r);
+        mRingPath = null;
+        mPathIsDirty = true;
         mRectIsDirty = true;
     }
 
@@ -437,6 +453,7 @@ public class GradientDrawable extends Drawable {
     protected boolean onLevelChange(int level) {
         super.onLevelChange(level);
         mRectIsDirty = true;
+        mPathIsDirty = true;
         invalidateSelf();
         return true;
     }
@@ -462,8 +479,9 @@ public class GradientDrawable extends Drawable {
 
             mRect.set(bounds.left + inset, bounds.top + inset,
                       bounds.right - inset, bounds.bottom - inset);
-            
-            if (st.mColors != null) {
+
+            final int[] colors = st.mColors;
+            if (colors != null) {
                 RectF r = mRect;
                 float x0, x1, y0, y1;
 
@@ -505,8 +523,7 @@ public class GradientDrawable extends Drawable {
                     }
 
                     mFillPaint.setShader(new LinearGradient(x0, y0, x1, y1,
-                                                            st.mColors, st.mPositions,
-                                                            Shader.TileMode.CLAMP));
+                            colors, st.mPositions, Shader.TileMode.CLAMP));
                 } else if (st.mGradient == RADIAL_GRADIENT) {
                     x0 = r.left + (r.right - r.left) * st.mCenterX;
                     y0 = r.top + (r.bottom - r.top) * st.mCenterY;
@@ -514,30 +531,38 @@ public class GradientDrawable extends Drawable {
                     final float level = st.mUseLevel ? (float) getLevel() / 10000.0f : 1.0f;
 
                     mFillPaint.setShader(new RadialGradient(x0, y0,
-                            level * st.mGradientRadius, st.mColors, null,
+                            level * st.mGradientRadius, colors, null,
                             Shader.TileMode.CLAMP));
                 } else if (st.mGradient == SWEEP_GRADIENT) {
                     x0 = r.left + (r.right - r.left) * st.mCenterX;
                     y0 = r.top + (r.bottom - r.top) * st.mCenterY;
 
-                    float[] positions = null;
-                    int[] colors = st.mColors;
+                    int[] tempColors = colors;
+                    float[] tempPositions = null;
 
                     if (st.mUseLevel) {
-                        final int length = st.mColors.length;
-                        colors = new int[length + 1];
-                        System.arraycopy(st.mColors, 0, colors, 0, length);
-                        colors[length] = st.mColors[length - 1];
+                        tempColors = st.mTempColors;
+                        final int length = colors.length;
+                        if (tempColors == null || tempColors.length != length + 1) {
+                            tempColors = st.mTempColors = new int[length + 1];
+                        }
+                        System.arraycopy(colors, 0, tempColors, 0, length);
+                        tempColors[length] = colors[length - 1];
 
+                        tempPositions = st.mTempPositions;
                         final float fraction = 1.0f / (float) (length - 1);
-                        positions = new float[length + 1];
+                        if (tempPositions == null || tempPositions.length != length + 1) {
+                            tempPositions = st.mTempPositions = new float[length + 1];
+                        }
+
                         final float level = (float) getLevel() / 10000.0f;
                         for (int i = 0; i < length; i++) {
-                            positions[i] = i * fraction * level;
+                            tempPositions[i] = i * fraction * level;
                         }
-                        positions[length] = 1.0f;
+                        tempPositions[length] = 1.0f;
+
                     }
-                    mFillPaint.setShader(new SweepGradient(x0, y0, colors, positions));
+                    mFillPaint.setShader(new SweepGradient(x0, y0, tempColors, tempPositions));
                 }
             }
         }
@@ -561,10 +586,18 @@ public class GradientDrawable extends Drawable {
                 com.android.internal.R.styleable.GradientDrawable_shape, RECTANGLE);
         
         if (shapeType == RING) {
-            st.mInnerRadius = a.getFloat(
-                    com.android.internal.R.styleable.GradientDrawable_innerRadiusRatio, 3.0f);
-            st.mThickness = a.getFloat(
-                    com.android.internal.R.styleable.GradientDrawable_thicknessRatio, 9.0f);
+            st.mInnerRadius = a.getDimensionPixelSize(
+                    com.android.internal.R.styleable.GradientDrawable_innerRadius, -1);
+            if (st.mInnerRadius == -1) {
+                st.mInnerRadiusRatio = a.getFloat(
+                        com.android.internal.R.styleable.GradientDrawable_innerRadiusRatio, 3.0f);
+            }
+            st.mThickness = a.getDimensionPixelSize(
+                    com.android.internal.R.styleable.GradientDrawable_thickness, -1);
+            if (st.mThickness == -1) {
+                st.mThicknessRatio = a.getFloat(
+                        com.android.internal.R.styleable.GradientDrawable_thicknessRatio, 9.0f);
+            }
             st.mUseLevelForShape = a.getBoolean(
                     com.android.internal.R.styleable.GradientDrawable_useLevel, true);
         }
@@ -808,6 +841,8 @@ public class GradientDrawable extends Drawable {
         public int mGradient = LINEAR_GRADIENT;
         public Orientation mOrientation;
         public int[] mColors;
+        public int[] mTempColors; // no need to copy
+        public float[] mTempPositions; // no need to copy
         public float[] mPositions;
         public boolean mHasSolidColor;
         public int mSolidColor;
@@ -820,8 +855,10 @@ public class GradientDrawable extends Drawable {
         public Rect mPadding;
         public int mWidth = -1;
         public int mHeight = -1;
-        public float mInnerRadius;
-        public float mThickness;
+        public float mInnerRadiusRatio;
+        public float mThicknessRatio;
+        public int mInnerRadius;
+        public int mThickness;
         private float mCenterX = 0.5f;
         private float mCenterY = 0.5f;
         private float mGradientRadius = 0.5f;
@@ -844,17 +881,25 @@ public class GradientDrawable extends Drawable {
             mGradient = state.mGradient;
             mOrientation = state.mOrientation;
             mColors = state.mColors.clone();
-            mPositions = state.mPositions.clone();
+            if (state.mPositions != null) {
+                mPositions = state.mPositions.clone();
+            }
             mHasSolidColor = state.mHasSolidColor;
             mStrokeWidth = state.mStrokeWidth;
             mStrokeColor = state.mStrokeColor;
             mStrokeDashWidth = state.mStrokeDashWidth;
             mStrokeDashGap = state.mStrokeDashGap;
             mRadius = state.mRadius;
-            mRadiusArray = state.mRadiusArray.clone();
-            mPadding = new Rect(state.mPadding);
+            if (state.mRadiusArray != null) {
+                mRadiusArray = state.mRadiusArray.clone();
+            }
+            if (state.mPadding != null) {
+                mPadding = new Rect(state.mPadding);
+            }
             mWidth = state.mWidth;
             mHeight = state.mHeight;
+            mInnerRadiusRatio = state.mInnerRadiusRatio;
+            mThicknessRatio = state.mThicknessRatio;
             mInnerRadius = state.mInnerRadius;
             mThickness = state.mThickness;
             mCenterX = state.mCenterX;
diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java
index e4b821a905c0..cb16cb711b42 100644
--- a/graphics/java/android/graphics/drawable/RotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/RotateDrawable.java
@@ -88,6 +88,13 @@ public class RotateDrawable extends Drawable implements Drawable.Callback {
         canvas.restoreToCount(saveCount);
     }
 
+    /**
+     * Returns the drawable rotated by this RotateDrawable.
+     */
+    public Drawable getDrawable() {
+        return mState.mDrawable;
+    }
+
     @Override
     public int getChangingConfigurations() {
         return super.getChangingConfigurations()
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index b3322c9634bb..7125ab1e689e 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -63,6 +63,13 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
         }
     }
 
+    /**
+     * Returns the drawable scaled by this ScaleDrawable.
+     */
+    public Drawable getDrawable() {
+        return mScaleState.mDrawable;
+    }
+
     private static float getPercent(TypedArray a, int name) {
         String s = a.getString(name);
         if (s != null) {
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 6bd54ba6611e..7437f6526660 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -29,8 +29,27 @@ class AudioSystem
 {
 public:
 
+    enum stream_type {
+        DEFAULT         =-1,
+        VOICE_CALL      = 0,
+        SYSTEM          = 1,
+        RING            = 2,
+        MUSIC           = 3,
+        ALARM           = 4,
+        NOTIFICATION    = 5,
+        BLUETOOTH_SCO   = 6,
+        NUM_STREAM_TYPES
+    };
+
+    enum audio_output_type {
+        AUDIO_OUTPUT_DEFAULT      =-1,
+        AUDIO_OUTPUT_HARDWARE     = 0,
+        AUDIO_OUTPUT_A2DP         = 1,
+        NUM_AUDIO_OUTPUT_TYPES
+    };
+
     enum audio_format {
-        DEFAULT = 0,
+        FORMAT_DEFAULT = 0,
         PCM_16_BIT,
         PCM_8_BIT,
         INVALID_FORMAT
@@ -96,9 +115,11 @@ public:
     static float linearToLog(int volume);
     static int logToLinear(float volume);
 
-    static status_t getOutputSamplingRate(int* samplingRate);
-    static status_t getOutputFrameCount(int* frameCount);
-    static status_t getOutputLatency(uint32_t* latency);
+    static status_t getOutputSamplingRate(int* samplingRate, int stream = DEFAULT);
+    static status_t getOutputFrameCount(int* frameCount, int stream = DEFAULT);
+    static status_t getOutputLatency(uint32_t* latency, int stream = DEFAULT);
+
+    static bool routedToA2dpOutput(int streamType);
     
     static status_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount, 
         size_t* buffSize);
@@ -117,9 +138,10 @@ private:
         virtual void binderDied(const wp<IBinder>& who);
         
         // IAudioFlingerClient
-        virtual void audioOutputChanged(uint32_t frameCount, uint32_t samplingRate, uint32_t latency);
+        virtual void a2dpEnabledChanged(bool enabled);
         
     };
+    static int getOutput(int streamType);
 
     static sp<AudioFlingerClient> gAudioFlingerClient;
 
@@ -128,9 +150,10 @@ private:
     static Mutex gLock;
     static sp<IAudioFlinger> gAudioFlinger;
     static audio_error_callback gAudioErrorCallback;
-    static int gOutSamplingRate;
-    static int gOutFrameCount;
-    static uint32_t gOutLatency;
+    static int gOutSamplingRate[NUM_AUDIO_OUTPUT_TYPES];
+    static int gOutFrameCount[NUM_AUDIO_OUTPUT_TYPES];
+    static uint32_t gOutLatency[NUM_AUDIO_OUTPUT_TYPES];
+    static bool gA2dpEnabled;
     
     static size_t gInBuffSize;
     // previous parameters for recording buffer size queries
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 5b2bab98bb27..659f5f8aa335 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -42,19 +42,6 @@ class audio_track_cblk_t;
 class AudioTrack
 {
 public:
-
-    enum stream_type {
-        DEFAULT         =-1,
-        VOICE_CALL      = 0,
-        SYSTEM          = 1,
-        RING            = 2,
-        MUSIC           = 3,
-        ALARM           = 4,
-        NOTIFICATION    = 5,
-        BLUETOOTH_SCO   = 6,
-        NUM_STREAM_TYPES
-    };
-
     enum channel_index {
         MONO   = 0,
         LEFT   = 0,
@@ -128,7 +115,7 @@ public:
      * Parameters:
      *
      * streamType:         Select the type of audio stream this track is attached to
-     *                     (e.g. AudioTrack::MUSIC).
+     *                     (e.g. AudioSystem::MUSIC).
      * sampleRate:         Track sampling rate in Hz.
      * format:             PCM sample format (e.g AudioSystem::PCM_16_BIT for signed
      *                     16 bits per sample).
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index df601d7ca03f..6f13fe0b52c2 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -65,11 +65,11 @@ public:
     /* query the audio hardware state. This state never changes,
      * and therefore can be cached.
      */
-    virtual     uint32_t    sampleRate() const = 0;
-    virtual     int         channelCount() const = 0;
-    virtual     int         format() const = 0;
-    virtual     size_t      frameCount() const = 0;
-    virtual     uint32_t    latency() const = 0;
+    virtual     uint32_t    sampleRate(int output) const = 0;
+    virtual     int         channelCount(int output) const = 0;
+    virtual     int         format(int output) const = 0;
+    virtual     size_t      frameCount(int output) const = 0;
+    virtual     uint32_t    latency(int output) const = 0;
 
     /* set/get the audio hardware state. This will probably be used by
      * the preference panel, mostly.
@@ -117,6 +117,9 @@ public:
     
     // force AudioFlinger thread out of standby
     virtual     void        wakeUp() = 0;
+
+    // is A2DP output enabled
+    virtual     bool        isA2dpEnabled() const = 0;
 };
 
 
diff --git a/include/media/IAudioFlingerClient.h b/include/media/IAudioFlingerClient.h
index 10c3e0fd9f38..c3deb0b4e8f2 100644
--- a/include/media/IAudioFlingerClient.h
+++ b/include/media/IAudioFlingerClient.h
@@ -32,7 +32,7 @@ public:
     DECLARE_META_INTERFACE(AudioFlingerClient);
 
     // Notifies a change of audio output from/to hardware to/from A2DP.
-    virtual void audioOutputChanged(uint32_t frameCount, uint32_t samplingRate, uint32_t latency) = 0;
+    virtual void a2dpEnabledChanged(bool enabled) = 0;
 
 };
 
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index 49e45d138ffd..0dff84e87ce1 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -38,6 +38,7 @@ public:
     virtual	status_t		setVideoEncoder(int ve) = 0;
     virtual	status_t		setAudioEncoder(int ae) = 0;
     virtual	status_t		setOutputFile(const char* path) = 0;
+    virtual	status_t		setOutputFile(int fd, int64_t offset, int64_t length) = 0;
     virtual	status_t		setVideoSize(int width, int height) = 0;
     virtual	status_t		setVideoFrameRate(int frames_per_second) = 0;
     virtual	status_t		prepare() = 0;
diff --git a/include/media/PVMediaRecorder.h b/include/media/PVMediaRecorder.h
index 5fee0d6a7ead..f795d040e950 100644
--- a/include/media/PVMediaRecorder.h
+++ b/include/media/PVMediaRecorder.h
@@ -43,6 +43,7 @@ public:
     status_t setCamera(const sp<ICamera>& camera);
     status_t setPreviewSurface(const sp<ISurface>& surface);
     status_t setOutputFile(const char *path);
+    status_t setOutputFile(int fd, int64_t offset, int64_t length);
     status_t prepare();
     status_t start();
     status_t stop();
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index a901d32ee3c9..436e8f1d0cf2 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -102,6 +102,7 @@ public:
     status_t    setVideoEncoder(int ve);
     status_t    setAudioEncoder(int ae);
     status_t    setOutputFile(const char* path);
+    status_t    setOutputFile(int fd, int64_t offset, int64_t length);
     status_t    setVideoSize(int width, int height);
     status_t    setVideoFrameRate(int frames_per_second);
     status_t    prepare();
diff --git a/include/ui/ISurface.h b/include/ui/ISurface.h
index 1c8043dbf048..87b320f431b8 100644
--- a/include/ui/ISurface.h
+++ b/include/ui/ISurface.h
@@ -25,6 +25,8 @@
 #include <utils/RefBase.h>
 #include <ui/PixelFormat.h>
 
+#include <hardware/hardware.h>
+
 namespace android {
 
 typedef int32_t    SurfaceID;
@@ -49,16 +51,8 @@ public:
     class BufferHeap {
     public:
         enum {
-            /* flip source image horizontally */
-            FLIP_H    = 0x01,
-            /* flip source image vertically */
-            FLIP_V    = 0x02,
             /* rotate source image 90 degrees */
-            ROT_90    = 0x04,
-            /* rotate source image 180 degrees */
-            ROT_180   = 0x03,
-            /* rotate source image 270 degrees */
-            ROT_270   = 0x07,
+            ROT_90    = HAL_TRANSFORM_ROT_90,
         };
         BufferHeap();
         
diff --git a/include/utils/logger.h b/include/utils/logger.h
deleted file mode 100644
index 3a08019a8866..000000000000
--- a/include/utils/logger.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* utils/logger.h
-** 
-** Copyright 2007, The Android Open Source Project
-**
-** This file is dual licensed.  It may be redistributed and/or modified
-** under the terms of the Apache 2.0 License OR version 2 of the GNU
-** General Public License.
-*/
-
-#ifndef _UTILS_LOGGER_H
-#define _UTILS_LOGGER_H
-
-#include <stdint.h>
-
-struct logger_entry {
-    uint16_t    len;    /* length of the payload */
-    uint16_t    __pad;  /* no matter what, we get 2 bytes of padding */
-    int32_t     pid;    /* generating process's pid */
-    int32_t     tid;    /* generating process's tid */
-    int32_t     sec;    /* seconds since Epoch */
-    int32_t     nsec;   /* nanoseconds */
-    char        msg[0]; /* the entry's payload */
-};
-
-#define LOGGER_LOG_MAIN		"log/main"
-#define LOGGER_LOG_RADIO	"log/radio"
-#define LOGGER_LOG_EVENTS	"log/events"
-
-#define LOGGER_ENTRY_MAX_LEN		(4*1024)
-#define LOGGER_ENTRY_MAX_PAYLOAD	\
-	(LOGGER_ENTRY_MAX_LEN - sizeof(struct logger_entry))
-
-#ifdef HAVE_IOCTL
-
-#include <sys/ioctl.h>
-
-#define __LOGGERIO	0xAE
-
-#define LOGGER_GET_LOG_BUF_SIZE		_IO(__LOGGERIO, 1) /* size of log */
-#define LOGGER_GET_LOG_LEN		_IO(__LOGGERIO, 2) /* used log len */
-#define LOGGER_GET_NEXT_ENTRY_LEN	_IO(__LOGGERIO, 3) /* next entry len */
-#define LOGGER_FLUSH_LOG		_IO(__LOGGERIO, 4) /* flush log */
-
-#endif // HAVE_IOCTL
-
-#endif /* _UTILS_LOGGER_H */
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 017a298c6927..d347f14caeee 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -47,6 +47,15 @@
 #include "A2dpAudioInterface.h"
 #endif
 
+// ----------------------------------------------------------------------------
+// the sim build doesn't have gettid
+
+#ifndef HAVE_GETTID
+# define gettid getpid
+#endif
+
+// ----------------------------------------------------------------------------
+
 namespace android {
 
 //static const nsecs_t kStandbyTimeInNsecs = seconds(3);
@@ -59,6 +68,13 @@ static const float MAX_GAIN = 4096.0f;
 static const int8_t kMaxTrackRetries = 50;
 static const int8_t kMaxTrackStartupRetries = 50;
 
+static const int kStartSleepTime = 30000;
+static const int kStopSleepTime = 30000;
+
+// Maximum number of pending buffers allocated by OutputTrack::write()
+static const uint8_t kMaxOutputTrackBuffers = 5;
+
+
 #define AUDIOFLINGER_SECURITY_ENABLED 1
 
 // ----------------------------------------------------------------------------
@@ -98,13 +114,10 @@ static bool settingsAllowed() {
 // ----------------------------------------------------------------------------
 
 AudioFlinger::AudioFlinger()
-    : BnAudioFlinger(), Thread(false),
-        mMasterVolume(0), mMasterMute(true), mHardwareAudioMixer(0), mA2dpAudioMixer(0),
-        mAudioMixer(0), mAudioHardware(0), mA2dpAudioInterface(0), mHardwareOutput(0),
-        mA2dpOutput(0), mOutput(0), mRequestedOutput(0), mAudioRecordThread(0),
-        mSampleRate(0), mFrameCount(0), mChannelCount(0), mFormat(0), mMixBuffer(0),
-        mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mStandby(false),
-        mInWrite(false), mA2dpDisableCount(0), mA2dpSuppressed(false)
+    : BnAudioFlinger(),
+        mAudioHardware(0), mA2dpAudioInterface(0),
+        mA2dpEnabled(false), mA2dpEnabledReq(false),
+        mForcedSpeakerCount(0), mForcedRoute(0), mRouteRestoreTime(0), mMusicMuteSaved(false)
 {
     mHardwareStatus = AUDIO_HW_IDLE;
     mAudioHardware = AudioHardwareInterface::create();
@@ -113,42 +126,43 @@ AudioFlinger::AudioFlinger()
         // open 16-bit output stream for s/w mixer
         mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
         status_t status;
-        mHardwareOutput = mAudioHardware->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);
+        AudioStreamOut *hwOutput = mAudioHardware->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);
         mHardwareStatus = AUDIO_HW_IDLE;
-        if (mHardwareOutput) {
-            mHardwareAudioMixer = new AudioMixer(getOutputFrameCount(mHardwareOutput), mHardwareOutput->sampleRate());
-            mRequestedOutput = mHardwareOutput;
-            doSetOutput(mHardwareOutput);
-
-            // FIXME - this should come from settings
-            setMasterVolume(1.0f);
-            setRouting(AudioSystem::MODE_NORMAL, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL);
-            setRouting(AudioSystem::MODE_RINGTONE, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL);
-            setRouting(AudioSystem::MODE_IN_CALL, AudioSystem::ROUTE_EARPIECE, AudioSystem::ROUTE_ALL);
-            setMode(AudioSystem::MODE_NORMAL);
-            mMasterMute = false;
+        if (hwOutput) {
+            mHardwareMixerThread = new MixerThread(this, hwOutput, AudioSystem::AUDIO_OUTPUT_HARDWARE);
         } else {
-            LOGE("Failed to initialize output stream, status: %d", status);
+            LOGE("Failed to initialize hardware output stream, status: %d", status);
         }
         
 #ifdef WITH_A2DP
         // Create A2DP interface
         mA2dpAudioInterface = new A2dpAudioInterface();
-        mA2dpOutput = mA2dpAudioInterface->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);       
-        mA2dpAudioMixer = new AudioMixer(getOutputFrameCount(mA2dpOutput), mA2dpOutput->sampleRate());
-
-        // create a buffer big enough for both hardware and A2DP audio output.
-        size_t hwFrameCount = getOutputFrameCount(mHardwareOutput);
-        size_t a2dpFrameCount = getOutputFrameCount(mA2dpOutput);
-        size_t frameCount = (hwFrameCount > a2dpFrameCount ? hwFrameCount : a2dpFrameCount);
-#else
-        size_t frameCount = getOutputFrameCount(mHardwareOutput);
+        AudioStreamOut *a2dpOutput = mA2dpAudioInterface->openOutputStream(AudioSystem::PCM_16_BIT, 0, 0, &status);
+        if (a2dpOutput) {
+            mA2dpMixerThread = new MixerThread(this, a2dpOutput, AudioSystem::AUDIO_OUTPUT_A2DP);
+            if (hwOutput) {  
+                uint32_t frameCount = ((a2dpOutput->bufferSize()/a2dpOutput->frameSize()) * hwOutput->sampleRate()) / a2dpOutput->sampleRate();
+                MixerThread::OutputTrack *a2dpOutTrack = new MixerThread::OutputTrack(mA2dpMixerThread,
+                                                            hwOutput->sampleRate(),
+                                                            AudioSystem::PCM_16_BIT,
+                                                            hwOutput->channelCount(),
+                                                            frameCount);
+                mHardwareMixerThread->setOuputTrack(a2dpOutTrack);                
+            }
+        } else {
+            LOGE("Failed to initialize A2DP output stream, status: %d", status);
+        }
 #endif
-        // FIXME - Current mixer implementation only supports stereo output: Always
-        // Allocate a stereo buffer even if HW output is mono.
-        mMixBuffer = new int16_t[frameCount * 2];
-        memset(mMixBuffer, 0, frameCount * 2 * sizeof(int16_t));
-        
+ 
+        // FIXME - this should come from settings
+        setRouting(AudioSystem::MODE_NORMAL, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL);
+        setRouting(AudioSystem::MODE_RINGTONE, AudioSystem::ROUTE_SPEAKER, AudioSystem::ROUTE_ALL);
+        setRouting(AudioSystem::MODE_IN_CALL, AudioSystem::ROUTE_EARPIECE, AudioSystem::ROUTE_ALL);
+        setMode(AudioSystem::MODE_NORMAL);
+
+        setMasterVolume(1.0f);
+        setMasterMute(false);
+
         // Start record thread
         mAudioRecordThread = new AudioRecordThread(mAudioHardware);
         if (mAudioRecordThread != 0) {
@@ -162,7 +176,7 @@ AudioFlinger::AudioFlinger()
     property_get("ro.audio.silent", value, "0");
     if (atoi(value)) {
         LOGD("Silence is golden");
-        mMasterMute = true;
+        setMasterMute(true);
     }
 }
 
@@ -172,63 +186,35 @@ AudioFlinger::~AudioFlinger()
         mAudioRecordThread->exit();
         mAudioRecordThread.clear();        
     }
+    mHardwareMixerThread.clear();
     delete mAudioHardware;
     // deleting mA2dpAudioInterface also deletes mA2dpOutput;
+#ifdef WITH_A2DP
+    mA2dpMixerThread.clear();
     delete mA2dpAudioInterface;
-    delete [] mMixBuffer;
-    delete mHardwareAudioMixer;
-    delete mA2dpAudioMixer;
-}
- 
-void AudioFlinger::setOutput(AudioStreamOut* output)
-{
-    mRequestedOutput = output;
-    mWaitWorkCV.broadcast();
-}
-
-void AudioFlinger::doSetOutput(AudioStreamOut* output)
-{
-    mSampleRate = output->sampleRate();
-    mChannelCount = output->channelCount();
-
-    // FIXME - Current mixer implementation only supports stereo output
-    if (mChannelCount == 1) {
-        LOGE("Invalid audio hardware channel count");
-    }
-    mFormat = output->format();
-    mFrameCount = getOutputFrameCount(output);
-    mAudioMixer = (output == mA2dpOutput ? mA2dpAudioMixer : mHardwareAudioMixer);
-    mOutput = output;
-    notifyOutputChange_l();
+#endif
 }
 
-size_t AudioFlinger::getOutputFrameCount(AudioStreamOut* output) 
-{
-    return output->bufferSize() / output->channelCount() / sizeof(int16_t);
-}
 
 #ifdef WITH_A2DP
-bool AudioFlinger::streamDisablesA2dp(int streamType)
+void AudioFlinger::setA2dpEnabled(bool enable)
 {
-    return (streamType == AudioTrack::SYSTEM ||
-            streamType == AudioTrack::RING ||
-            streamType == AudioTrack::ALARM ||
-            streamType == AudioTrack::VOICE_CALL ||
-            streamType == AudioTrack::BLUETOOTH_SCO ||
-            streamType == AudioTrack::NOTIFICATION);
+    LOGV_IF(enable, "set output to A2DP\n");
+    LOGV_IF(!enable, "set output to hardware audio\n");
+
+    mA2dpEnabledReq = enable;
+    mA2dpMixerThread->wakeUp();
 }
+#endif // WITH_A2DP
 
-void AudioFlinger::setA2dpEnabled(bool enable)
+bool AudioFlinger::streamForcedToSpeaker(int streamType)
 {
-    if (enable) {
-        LOGD("set output to A2DP\n");
-        setOutput(mA2dpOutput);
-    } else {
-        LOGD("set output to hardware audio\n");
-        setOutput(mHardwareOutput);
-    }
+    // NOTE that streams listed here must not be routed to A2DP by default:
+    // AudioSystem::routedToA2dpOutput(streamType) == false
+    return (streamType == AudioSystem::RING ||
+            streamType == AudioSystem::ALARM ||
+            streamType == AudioSystem::NOTIFICATION);
 }
-#endif // WITH_A2DP
 
 status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
 {
@@ -251,40 +237,6 @@ status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
     return NO_ERROR;
 }
 
-status_t AudioFlinger::dumpTracks(int fd, const Vector<String16>& args)
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-    result.append("Tracks:\n");
-    result.append("   Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
-    for (size_t i = 0; i < mTracks.size(); ++i) {
-        wp<Track> wTrack = mTracks[i];
-        if (wTrack != 0) {
-            sp<Track> track = wTrack.promote();
-            if (track != 0) {
-                track->dump(buffer, SIZE);
-                result.append(buffer);
-            }
-        }
-    }
-
-    result.append("Active Tracks:\n");
-    result.append("   Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
-    for (size_t i = 0; i < mActiveTracks.size(); ++i) {
-        wp<Track> wTrack = mTracks[i];
-        if (wTrack != 0) {
-            sp<Track> track = wTrack.promote();
-            if (track != 0) {
-                track->dump(buffer, SIZE);
-                result.append(buffer);
-            }
-        }
-    }
-    write(fd, result.string(), result.size());
-    return NO_ERROR;
-}
 
 status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
 {
@@ -292,18 +244,6 @@ status_t AudioFlinger::dumpInternals(int fd, const Vector<String16>& args)
     char buffer[SIZE];
     String8 result;
 
-    snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", audioMixer()->trackNames());
-    result.append(buffer);
-    snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
-    result.append(buffer);
-    snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
-    result.append(buffer);
-    snprintf(buffer, SIZE, "standby: %d\n", mStandby);
-    result.append(buffer);
     snprintf(buffer, SIZE, "Hardware status: %d\n", mHardwareStatus);
     result.append(buffer);
     write(fd, result.string(), result.size());
@@ -332,8 +272,12 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
         AutoMutex lock(&mLock);
 
         dumpClients(fd, args);
-        dumpTracks(fd, args);
         dumpInternals(fd, args);
+        mHardwareMixerThread->dump(fd, args);
+#ifdef WITH_A2DP
+        mA2dpMixerThread->dump(fd, args);
+#endif
+
         if (mAudioHardware) {
             mAudioHardware->dumpState(fd, args);
         }
@@ -341,336 +285,135 @@ status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
     return NO_ERROR;
 }
 
-// Thread virtuals
-bool AudioFlinger::threadLoop()
+// IAudioFlinger interface
+
+
+sp<IAudioTrack> AudioFlinger::createTrack(
+        pid_t pid,
+        int streamType,
+        uint32_t sampleRate,
+        int format,
+        int channelCount,
+        int frameCount,
+        uint32_t flags,
+        const sp<IMemory>& sharedBuffer,
+        status_t *status)
 {
-    unsigned long sleepTime = kBufferRecoveryInUsecs;
-    int16_t* curBuf = mMixBuffer;
-    Vector< sp<Track> > tracksToRemove;
-    size_t enabledTracks = 0;
-    nsecs_t standbyTime = systemTime();    
-    nsecs_t outputSwitchStandbyTime = 0;
+    sp<MixerThread::Track> track;
+    sp<TrackHandle> trackHandle;
+    sp<Client> client;
+    wp<Client> wclient;
+    status_t lStatus;
 
-    do {
-        enabledTracks = 0;
-        { // scope for the mLock
-        
-            Mutex::Autolock _l(mLock);
-            const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
+    if (streamType >= AudioSystem::NUM_STREAM_TYPES) {
+        LOGE("invalid stream type");
+        lStatus = BAD_VALUE;
+        goto Exit;
+    }
 
-            // put audio hardware into standby after short delay
-            if UNLIKELY(!activeTracks.size() && systemTime() > standbyTime) {
-                // wait until we have something to do...
-                LOGV("Audio hardware entering standby\n");
-                mHardwareStatus = AUDIO_HW_STANDBY;
-                if (!mStandby) {
-                    mOutput->standby();
-                    mStandby = true;
-                }
-                if (outputSwitchStandbyTime) {
-                    AudioStreamOut *output = (mOutput == mHardwareOutput) ? mA2dpOutput : mHardwareOutput;
-                    output->standby();
-                    outputSwitchStandbyTime = 0;
-                }
-                mHardwareStatus = AUDIO_HW_IDLE;
-                // we're about to wait, flush the binder command buffer
-                IPCThreadState::self()->flushCommands();
-                mWaitWorkCV.wait(mLock);
-                LOGV("Audio hardware exiting standby\n");
-                standbyTime = systemTime() + kStandbyTimeInNsecs;
-                continue;
-            }
+    {
+        Mutex::Autolock _l(mLock);
 
-            // check for change in output
-            if (mRequestedOutput != mOutput) {
+        wclient = mClients.valueFor(pid);
 
-                // put current output into standby mode
-                if (mOutput) {
-                    outputSwitchStandbyTime = systemTime() + milliseconds(mOutput->latency());
-                }
+        if (wclient != NULL) {
+            client = wclient.promote();
+        } else {
+            client = new Client(this, pid);
+            mClients.add(pid, client);
+        }
+#ifdef WITH_A2DP
+        if (isA2dpEnabled() && AudioSystem::routedToA2dpOutput(streamType)) {
+            track = mA2dpMixerThread->createTrack(client, streamType, sampleRate, format,
+                    channelCount, frameCount, sharedBuffer, &lStatus);            
+        } else 
+#endif
+        {
+            track = mHardwareMixerThread->createTrack(client, streamType, sampleRate, format,
+                    channelCount, frameCount, sharedBuffer, &lStatus);            
+        }
+        if (track != NULL) {
+            trackHandle = new TrackHandle(track);
+            lStatus = NO_ERROR;            
+        }
+    }
 
-                // change output
-                doSetOutput(mRequestedOutput);
-            }
-            if (outputSwitchStandbyTime && systemTime() > outputSwitchStandbyTime) {
-                AudioStreamOut *output = (mOutput == mHardwareOutput) ? mA2dpOutput : mHardwareOutput;
-                output->standby();
-                outputSwitchStandbyTime = 0;
-            }
+Exit:
+    if(status) {
+        *status = lStatus;
+    }
+    return trackHandle;
+}
 
-            // find out which tracks need to be processed
-            size_t count = activeTracks.size();
-            for (size_t i=0 ; i<count ; i++) {
-                sp<Track> t = activeTracks[i].promote();
-                if (t == 0) continue;
+uint32_t AudioFlinger::sampleRate(int output) const
+{
+#ifdef WITH_A2DP
+     if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
+         return mA2dpMixerThread->sampleRate();
+     }
+#endif
+     return mHardwareMixerThread->sampleRate();
+}
 
-                Track* const track = t.get();
-                audio_track_cblk_t* cblk = track->cblk();
+int AudioFlinger::channelCount(int output) const
+{
+#ifdef WITH_A2DP
+     if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
+         return mA2dpMixerThread->channelCount();
+     }
+#endif
+     return mHardwareMixerThread->channelCount();
+}
 
-                // The first time a track is added we wait
-                // for all its buffers to be filled before processing it
-                mAudioMixer->setActiveTrack(track->name());
-                if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
-                        !track->isPaused())
-                {
-                    //LOGD("u=%08x, s=%08x [OK]", u, s);
+int AudioFlinger::format(int output) const
+{
+#ifdef WITH_A2DP
+     if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
+         return mA2dpMixerThread->format();
+     }
+#endif
+     return mHardwareMixerThread->format();
+}
 
-                    // compute volume for this track
-                    int16_t left, right;
-                    if (track->isMuted() || mMasterMute || track->isPausing()) {
-                        left = right = 0;
-                        if (track->isPausing()) {
-                            LOGV("paused(%d)", track->name());
-                            track->setPaused();
-                        }
-                    } else {
-                        float typeVolume = mStreamTypes[track->type()].volume;
-                        float v = mMasterVolume * typeVolume;
-                        float v_clamped = v * cblk->volume[0];
-                        if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
-                        left = int16_t(v_clamped);
-                        v_clamped = v * cblk->volume[1];
-                        if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
-                        right = int16_t(v_clamped);
-                    }
+size_t AudioFlinger::frameCount(int output) const
+{
+#ifdef WITH_A2DP
+     if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
+         return mA2dpMixerThread->frameCount();
+     }
+#endif
+     return mHardwareMixerThread->frameCount();
+}
 
-                    // XXX: these things DON'T need to be done each time
-                    mAudioMixer->setBufferProvider(track);
-                    mAudioMixer->enable(AudioMixer::MIXING);
+uint32_t AudioFlinger::latency(int output) const
+{
+#ifdef WITH_A2DP
+     if (output == AudioSystem::AUDIO_OUTPUT_A2DP) {
+         return mA2dpMixerThread->latency();
+     }
+#endif
+     return mHardwareMixerThread->latency();
+}
 
-                    int param;
-                    if ( track->mFillingUpStatus == Track::FS_FILLED) {
-                        // no ramp for the first volume setting
-                        track->mFillingUpStatus = Track::FS_ACTIVE;
-                        if (track->mState == TrackBase::RESUMING) {
-                            track->mState = TrackBase::ACTIVE;
-                            param = AudioMixer::RAMP_VOLUME;
-                        } else {
-                            param = AudioMixer::VOLUME;
-                        }
-                    } else {
-                        param = AudioMixer::RAMP_VOLUME;
-                    }
-                    mAudioMixer->setParameter(param, AudioMixer::VOLUME0, left);
-                    mAudioMixer->setParameter(param, AudioMixer::VOLUME1, right);
-                    mAudioMixer->setParameter(
-                        AudioMixer::TRACK,
-                        AudioMixer::FORMAT, track->format());
-                    mAudioMixer->setParameter(
-                        AudioMixer::TRACK,
-                        AudioMixer::CHANNEL_COUNT, track->channelCount());
-                    mAudioMixer->setParameter(
-                        AudioMixer::RESAMPLE,
-                        AudioMixer::SAMPLE_RATE,
-                        int(cblk->sampleRate));
-
-                    // reset retry count
-                    track->mRetryCount = kMaxTrackRetries;
-                    enabledTracks++;
-                } else {
-                    //LOGD("u=%08x, s=%08x [NOT READY]", u, s);
-                    if (track->isStopped()) {
-                        track->reset();
-                    }
-                    if (track->isTerminated() || track->isStopped() || track->isPaused()) {
-                        // We have consumed all the buffers of this track.
-                        // Remove it from the list of active tracks.
-                        LOGV("remove(%d) from active list", track->name());
-                        tracksToRemove.add(track);
-                    } else {
-                        // No buffers for this track. Give it a few chances to
-                        // fill a buffer, then remove it from active list.
-                        if (--(track->mRetryCount) <= 0) {
-                            LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
-                            tracksToRemove.add(track);
-                        }
-                    }
-                    // LOGV("disable(%d)", track->name());
-                    mAudioMixer->disable(AudioMixer::MIXING);
-                }
-            }
-
-            // remove all the tracks that need to be...
-            count = tracksToRemove.size();
-            if (UNLIKELY(count)) {
-                for (size_t i=0 ; i<count ; i++) {
-                    const sp<Track>& track = tracksToRemove[i];
-                    removeActiveTrack(track);
-                    if (track->isTerminated()) {
-                        mTracks.remove(track);
-                        deleteTrackName(track->mName);
-                    }
-                }
-            }  
-       }
-        if (LIKELY(enabledTracks)) {
-            // mix buffers...
-            mAudioMixer->process(curBuf);
-
-            // output audio to hardware
-            mLastWriteTime = systemTime();
-            mInWrite = true;
-            size_t mixBufferSize = mFrameCount*mChannelCount*sizeof(int16_t);
-            mOutput->write(curBuf, mixBufferSize);
-            mNumWrites++;
-            mInWrite = false;
-            mStandby = false;
-            nsecs_t temp = systemTime();
-            standbyTime = temp + kStandbyTimeInNsecs;
-            nsecs_t delta = temp - mLastWriteTime;
-            nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 2;
-            if (delta > maxPeriod) {
-                LOGW("write blocked for %llu msecs", ns2ms(delta));
-                mNumDelayedWrites++;
-            }
-            sleepTime = kBufferRecoveryInUsecs;
-        } else {
-            // There was nothing to mix this round, which means all
-            // active tracks were late. Sleep a little bit to give
-            // them another chance. If we're too late, the audio
-            // hardware will zero-fill for us.
-//            LOGV("no buffers - usleep(%lu)", sleepTime);
-            usleep(sleepTime);
-            if (sleepTime < kMaxBufferRecoveryInUsecs) {
-                sleepTime += kBufferRecoveryInUsecs;
-            }
-        }
-
-        // finally let go of all our tracks, without the lock held
-        // since we can't guarantee the destructors won't acquire that
-        // same lock.
-        tracksToRemove.clear();
-    } while (true);
-
-    return false;
-}
-
-status_t AudioFlinger::readyToRun()
-{
-    if (mSampleRate == 0) {
-        LOGE("No working audio driver found.");
-        return NO_INIT;
-    }
-    LOGI("AudioFlinger's main thread ready to run.");
-    return NO_ERROR;
-}
-
-void AudioFlinger::onFirstRef()
-{
-    run("AudioFlinger", ANDROID_PRIORITY_URGENT_AUDIO);
-}
-
-// IAudioFlinger interface
-sp<IAudioTrack> AudioFlinger::createTrack(
-        pid_t pid,
-        int streamType,
-        uint32_t sampleRate,
-        int format,
-        int channelCount,
-        int frameCount,
-        uint32_t flags,
-        const sp<IMemory>& sharedBuffer,
-        status_t *status)
-{
-    sp<Track> track;
-    sp<TrackHandle> trackHandle;
-    sp<Client> client;
-    wp<Client> wclient;
-    status_t lStatus;
-
-    if (streamType >= AudioTrack::NUM_STREAM_TYPES) {
-        LOGE("invalid stream type");
-        lStatus = BAD_VALUE;
-        goto Exit;
-    }
-
-    // Resampler implementation limits input sampling rate to 2 x output sampling rate.
-    if (sampleRate > MAX_SAMPLE_RATE || sampleRate > mSampleRate*2) {
-        LOGE("Sample rate out of range: %d", sampleRate);
-        lStatus = BAD_VALUE;
-        goto Exit;
-    }
-
-    {
-        Mutex::Autolock _l(mLock);
-
-        if (mSampleRate == 0) {
-            LOGE("Audio driver not initialized.");
-            lStatus = NO_INIT;
-            goto Exit;
-        }
-
-        wclient = mClients.valueFor(pid);
-
-        if (wclient != NULL) {
-            client = wclient.promote();
-        } else {
-            client = new Client(this, pid);
-            mClients.add(pid, client);
-        }
-
-        track = new Track(this, client, streamType, sampleRate, format,
-                channelCount, frameCount, sharedBuffer);
-        mTracks.add(track);
-        trackHandle = new TrackHandle(track);
-
-        lStatus = NO_ERROR;
-    }
-
-Exit:
-    if(status) {
-        *status = lStatus;
-    }
-    return trackHandle;
-}
-
-uint32_t AudioFlinger::sampleRate() const
-{
-    return mSampleRate;
-}
-
-int AudioFlinger::channelCount() const
-{
-    return mChannelCount;
-}
-
-int AudioFlinger::format() const
-{
-    return mFormat;
-}
-
-size_t AudioFlinger::frameCount() const
-{
-    return mFrameCount;
-}
-
-uint32_t AudioFlinger::latency() const
-{
-    if (mOutput) {
-        return mOutput->latency();
-    }
-    else {
-        return 0;
-    }
-}
-
-status_t AudioFlinger::setMasterVolume(float value)
-{
-    // check calling permissions
-    if (!settingsAllowed()) {
-        return PERMISSION_DENIED;
-    }
+status_t AudioFlinger::setMasterVolume(float value)
+{
+    // check calling permissions
+    if (!settingsAllowed()) {
+        return PERMISSION_DENIED;
+    }
 
     // when hw supports master volume, don't scale in sw mixer
     AutoMutex lock(mHardwareLock);
     mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
     if (mAudioHardware->setMasterVolume(value) == NO_ERROR) {
-        mMasterVolume = 1.0f;
-    }
-    else {
-        mMasterVolume = value;
+        value = 1.0f;
     }
     mHardwareStatus = AUDIO_HW_IDLE;
+    mHardwareMixerThread->setMasterVolume(value);
+#ifdef WITH_A2DP
+    mA2dpMixerThread->setMasterVolume(value);
+#endif
+    
     return NO_ERROR;
 }
 
@@ -688,20 +431,17 @@ status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask)
     }
 
 #ifdef WITH_A2DP
-    LOGD("setRouting %d %d %d\n", mode, routes, mask);
+    LOGD("setRouting %d %d %d, tid %d, calling tid %d\n", mode, routes, mask, gettid(), IPCThreadState::self()->getCallingPid());
     if (mode == AudioSystem::MODE_NORMAL && 
             (mask & AudioSystem::ROUTE_BLUETOOTH_A2DP)) {
         AutoMutex lock(&mLock);
 
         bool enableA2dp = false;
         if (routes & AudioSystem::ROUTE_BLUETOOTH_A2DP) {
-            if (mA2dpDisableCount > 0)
-                mA2dpSuppressed = true;
-            else
-                enableA2dp = true;
+            enableA2dp = true;
         }
         setA2dpEnabled(enableA2dp);
-        LOGD("setOutput done\n");
+        LOGV("setOutput done\n");
     }
 #endif
 
@@ -714,6 +454,12 @@ status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask)
         err = mAudioHardware->getRouting(mode, &r);
         if (err == NO_ERROR) {
             r = (r & ~mask) | (routes & mask);
+            if (mode == AudioSystem::MODE_NORMAL || 
+                (mode == AudioSystem::MODE_CURRENT && getMode() == AudioSystem::MODE_NORMAL)) {
+                mSavedRoute = r;
+                r |= mForcedRoute;
+                LOGV("setRouting mSavedRoute %08x mForcedRoute %08x\n", mSavedRoute, mForcedRoute);
+            }
             mHardwareStatus = AUDIO_HW_SET_ROUTING;
             err = mAudioHardware->setRouting(mode, r);
         }
@@ -726,9 +472,14 @@ uint32_t AudioFlinger::getRouting(int mode) const
 {
     uint32_t routes = 0;
     if ((mode >= AudioSystem::MODE_CURRENT) && (mode < AudioSystem::NUM_MODES)) {
-        mHardwareStatus = AUDIO_HW_GET_ROUTING;
-        mAudioHardware->getRouting(mode, &routes);
-        mHardwareStatus = AUDIO_HW_IDLE;
+        if (mode == AudioSystem::MODE_NORMAL || 
+            (mode == AudioSystem::MODE_CURRENT && getMode() == AudioSystem::MODE_NORMAL)) {
+            routes = mSavedRoute;                
+        } else {
+            mHardwareStatus = AUDIO_HW_GET_ROUTING;
+            mAudioHardware->getRouting(mode, &routes);
+            mHardwareStatus = AUDIO_HW_IDLE;
+        }
     } else {
         LOGW("Illegal value: getRouting(%d)", mode);
     }
@@ -791,19 +542,21 @@ status_t AudioFlinger::setMasterMute(bool muted)
     if (!settingsAllowed()) {
         return PERMISSION_DENIED;
     }
-
-    mMasterMute = muted;
+    mHardwareMixerThread->setMasterMute(muted);
+#ifdef WITH_A2DP
+    mA2dpMixerThread->setMasterMute(muted);
+#endif
     return NO_ERROR;
 }
 
 float AudioFlinger::masterVolume() const
 {
-    return mMasterVolume;
+    return mHardwareMixerThread->masterVolume();
 }
 
 bool AudioFlinger::masterMute() const
 {
-    return mMasterMute;
+    return mHardwareMixerThread->masterMute();
 }
 
 status_t AudioFlinger::setStreamVolume(int stream, float value)
@@ -813,14 +566,25 @@ status_t AudioFlinger::setStreamVolume(int stream, float value)
         return PERMISSION_DENIED;
     }
 
-    if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
+    if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
         return BAD_VALUE;
     }
 
-    mStreamTypes[stream].volume = value;
+    mHardwareMixerThread->setStreamVolume(stream, value);
+#ifdef WITH_A2DP
+    mA2dpMixerThread->setStreamVolume(stream, value);
+#endif
+
     status_t ret = NO_ERROR;
-    if (stream == AudioTrack::VOICE_CALL ||
-        stream == AudioTrack::BLUETOOTH_SCO) {
+    if (stream == AudioSystem::VOICE_CALL ||
+        stream == AudioSystem::BLUETOOTH_SCO) {
+        
+        if (stream == AudioSystem::VOICE_CALL) {
+            value = (float)AudioSystem::logToLinear(value)/100.0f;
+        } else { // (type == AudioSystem::BLUETOOTH_SCO)
+            value = 1.0f;
+        }
+
         AutoMutex lock(mHardwareLock);
         mHardwareStatus = AUDIO_SET_VOICE_VOLUME;
         ret = mAudioHardware->setVoiceVolume(value);
@@ -837,59 +601,58 @@ status_t AudioFlinger::setStreamMute(int stream, bool muted)
         return PERMISSION_DENIED;
     }
 
-    if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
+    if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
         return BAD_VALUE;
     }
+    
 #ifdef WITH_A2DP
-    if (stream == AudioTrack::MUSIC) 
+    mA2dpMixerThread->setStreamMute(stream, muted);
+#endif
+    if (stream == AudioSystem::MUSIC) 
     {
-        AutoMutex lock(&mLock);
-        if (mA2dpDisableCount > 0)
+        AutoMutex lock(&mHardwareLock);
+        if (mForcedRoute != 0)
             mMusicMuteSaved = muted;
         else
-            mStreamTypes[stream].mute = muted;
+            mHardwareMixerThread->setStreamMute(stream, muted);
     } else {
-        mStreamTypes[stream].mute = muted;
+        mHardwareMixerThread->setStreamMute(stream, muted);
     }
-#else
-    mStreamTypes[stream].mute = muted;
-#endif
+
+    
+
     return NO_ERROR;
 }
 
 float AudioFlinger::streamVolume(int stream) const
 {
-    if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
+    if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
         return 0.0f;
     }
-    return mStreamTypes[stream].volume;
+    return mHardwareMixerThread->streamVolume(stream);
 }
 
 bool AudioFlinger::streamMute(int stream) const
 {
-    if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) {
+    if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
         return true;
     }
-#ifdef WITH_A2DP
-    if (stream == AudioTrack::MUSIC && mA2dpDisableCount > 0) 
+    
+    if (stream == AudioSystem::MUSIC && mForcedRoute != 0) 
     {
         return mMusicMuteSaved;
     }
-#endif
-    return mStreamTypes[stream].mute;
+    return mHardwareMixerThread->streamMute(stream);
 }
 
 bool AudioFlinger::isMusicActive() const
 {
-    size_t count = mActiveTracks.size();
-    for (size_t i = 0 ; i < count ; ++i) {
-        sp<Track> t = mActiveTracks[i].promote();
-        if (t == 0) continue;
-        Track* const track = t.get();
-        if (t->mStreamType == AudioTrack::MUSIC)
-            return true;
-    }
-    return false;
+ #ifdef WITH_A2DP
+     if (isA2dpEnabled()) {
+         return mA2dpMixerThread->isMusicActive();
+     }
+ #endif
+    return mHardwareMixerThread->isMusicActive();
 }
 
 status_t AudioFlinger::setParameter(const char* key, const char* value)
@@ -897,6 +660,8 @@ status_t AudioFlinger::setParameter(const char* key, const char* value)
     status_t result, result2;
     AutoMutex lock(mHardwareLock);
     mHardwareStatus = AUDIO_SET_PARAMETER;
+    
+    LOGV("setParameter() key %s, value %s, tid %d, calling tid %d", key, value, gettid(), IPCThreadState::self()->getCallingPid());
     result = mAudioHardware->setParameter(key, value);
     if (mA2dpAudioInterface) {
         result2 = mA2dpAudioInterface->setParameter(key, value);
@@ -907,9 +672,15 @@ status_t AudioFlinger::setParameter(const char* key, const char* value)
     return result;
 }
 
+size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
+{
+    return mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
+}
 
 void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
 {
+    
+    LOGV("registerClient() %p, tid %d, calling tid %d", client.get(), gettid(), IPCThreadState::self()->getCallingPid());
     Mutex::Autolock _l(mLock);
 
     sp<IBinder> binder = client->asBinder();
@@ -917,21 +688,13 @@ void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
         LOGV("Adding notification client %p", binder.get());
         binder->linkToDeath(this);
         mNotificationClients.add(binder);
+        client->a2dpEnabledChanged(isA2dpEnabled());
     }
 }
 
-
-size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
-{
-    return mAudioHardware->getInputBufferSize(sampleRate, format, channelCount);
-}
-
-void AudioFlinger::wakeUp()
-{
-    mWaitWorkCV.broadcast();
-}
-
 void AudioFlinger::binderDied(const wp<IBinder>& who) {
+    
+    LOGV("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(), IPCThreadState::self()->getCallingPid());
     Mutex::Autolock _l(mLock);
 
     IBinder *binder = who.unsafe_get();
@@ -945,33 +708,684 @@ void AudioFlinger::binderDied(const wp<IBinder>& who) {
     }
 }
 
-// must be called with mLock held
-void AudioFlinger::notifyOutputChange_l()
+void AudioFlinger::handleOutputSwitch()
 {
-    size_t size = mNotificationClients.size();
-    uint32_t latency = mOutput->latency();
-    for (size_t i = 0; i < size; i++) {
-        sp<IBinder> binder = mNotificationClients.itemAt(i).promote();
-        if (binder != NULL) {
-            LOGV("Notifying output change to client %p", binder.get());
-            sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder);
-            client->audioOutputChanged(mFrameCount, mSampleRate, latency);
+    if (mA2dpEnabled != mA2dpEnabledReq)
+    {
+        Mutex::Autolock _l(mLock);
+
+        if (mA2dpEnabled != mA2dpEnabledReq)
+        {
+            mA2dpEnabled = mA2dpEnabledReq;
+            SortedVector < sp<MixerThread::Track> > tracks;
+            SortedVector < wp<MixerThread::Track> > activeTracks;
+            
+            // We hold mA2dpMixerThread mLock already 
+            Mutex::Autolock _l(mHardwareMixerThread->mLock);
+            
+            // Transfer tracks playing on MUSIC stream from one mixer to the other
+            if (mA2dpEnabled) {
+                mHardwareMixerThread->getTracks(tracks, activeTracks);
+                mA2dpMixerThread->putTracks(tracks, activeTracks);
+            } else {
+                mA2dpMixerThread->getTracks(tracks, activeTracks);
+                mHardwareMixerThread->putTracks(tracks, activeTracks);
+            }            
+            
+            // Notify AudioSystem of the A2DP activation/deactivation
+            size_t size = mNotificationClients.size();
+            for (size_t i = 0; i < size; i++) {
+                sp<IBinder> binder = mNotificationClients.itemAt(i).promote();
+                if (binder != NULL) {
+                    LOGV("Notifying output change to client %p", binder.get());
+                    sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder);
+                    client->a2dpEnabledChanged(mA2dpEnabled);
+                }
+            }
+
+            mHardwareMixerThread->wakeUp();
         }
     }
 }
 
 void AudioFlinger::removeClient(pid_t pid)
 {
+    LOGV("removeClient() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
     Mutex::Autolock _l(mLock);
     mClients.removeItem(pid);
 }
 
-status_t AudioFlinger::addTrack(const sp<Track>& track)
+void AudioFlinger::wakeUp()
 {
-    Mutex::Autolock _l(mLock);
+    mHardwareMixerThread->wakeUp();
+#ifdef WITH_A2DP
+    mA2dpMixerThread->wakeUp();
+#endif // WITH_A2DP
+}
 
-    // here the track could be either new, or restarted
-    // in both cases "unstop" the track
+bool AudioFlinger::isA2dpEnabled() const
+{
+    return mA2dpEnabledReq;
+}
+
+void AudioFlinger::handleForcedSpeakerRoute(int command)
+{
+    switch(command) {
+    case ACTIVE_TRACK_ADDED:
+        {
+            AutoMutex lock(mHardwareLock);
+            if (mForcedSpeakerCount++ == 0) {
+                mRouteRestoreTime = 0;
+                mMusicMuteSaved = mHardwareMixerThread->streamMute(AudioSystem::MUSIC);
+                if (mForcedRoute == 0 && !(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) {
+                    LOGV("Route forced to Speaker ON %08x", mSavedRoute | AudioSystem::ROUTE_SPEAKER);
+                    mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, true);
+                    mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
+                    mAudioHardware->setMasterVolume(0);
+                    usleep(mHardwareMixerThread->latency()*1000);
+                    mHardwareStatus = AUDIO_HW_SET_ROUTING;
+                    mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute | AudioSystem::ROUTE_SPEAKER);
+                    mHardwareStatus = AUDIO_HW_IDLE;
+                    // delay track start so that audio hardware has time to siwtch routes
+                    usleep(kStartSleepTime);
+                    mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
+                    mAudioHardware->setMasterVolume(mHardwareMixerThread->masterVolume());
+                    mHardwareStatus = AUDIO_HW_IDLE;
+                }
+                mForcedRoute = AudioSystem::ROUTE_SPEAKER;
+            }
+            LOGV("mForcedSpeakerCount incremented to %d", mForcedSpeakerCount);
+        }
+        break;
+    case ACTIVE_TRACK_REMOVED:
+        {
+            AutoMutex lock(mHardwareLock);
+            if (mForcedSpeakerCount > 0){
+                if (--mForcedSpeakerCount == 0) {
+                    mRouteRestoreTime = systemTime() + milliseconds(kStopSleepTime/1000);
+                }
+                LOGV("mForcedSpeakerCount decremented to %d", mForcedSpeakerCount);            
+            } else {
+                LOGE("mForcedSpeakerCount is already zero");            
+            }            
+        }
+        break;
+    case CHECK_ROUTE_RESTORE_TIME:
+    case FORCE_ROUTE_RESTORE:
+        if (mRouteRestoreTime) {
+            AutoMutex lock(mHardwareLock);
+            if (mRouteRestoreTime && 
+               (systemTime() > mRouteRestoreTime || command == FORCE_ROUTE_RESTORE)) {
+                mHardwareMixerThread->setStreamMute(AudioSystem::MUSIC, mMusicMuteSaved);
+                mForcedRoute = 0;
+                if (!(mSavedRoute & AudioSystem::ROUTE_SPEAKER)) {
+                    mHardwareStatus = AUDIO_HW_SET_ROUTING;
+                    mAudioHardware->setRouting(AudioSystem::MODE_NORMAL, mSavedRoute);
+                    mHardwareStatus = AUDIO_HW_IDLE;
+                    LOGV("Route forced to Speaker OFF %08x", mSavedRoute);
+                }
+                mRouteRestoreTime = 0;
+            }
+        }
+        break;
+    }
+}
+
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int outputType)
+    :   Thread(false),
+        mAudioFlinger(audioFlinger), mAudioMixer(0), mOutput(output), mOutputType(outputType), 
+        mSampleRate(0), mFrameCount(0), mChannelCount(0), mFormat(0), mMixBuffer(0),
+        mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mStandby(false),
+        mInWrite(false)
+{
+    mSampleRate = output->sampleRate();
+    mChannelCount = output->channelCount();
+
+    // FIXME - Current mixer implementation only supports stereo output
+    if (mChannelCount == 1) {
+        LOGE("Invalid audio hardware channel count");
+    }
+
+    mFormat = output->format();
+    mFrameCount = output->bufferSize() / output->channelCount() / sizeof(int16_t);
+    mAudioMixer = new AudioMixer(mFrameCount, output->sampleRate());
+
+    // FIXME - Current mixer implementation only supports stereo output: Always
+    // Allocate a stereo buffer even if HW output is mono.
+    mMixBuffer = new int16_t[mFrameCount * 2];
+    memset(mMixBuffer, 0, mFrameCount * 2 * sizeof(int16_t));
+}
+
+AudioFlinger::MixerThread::~MixerThread()
+{
+    delete [] mMixBuffer;
+    delete mAudioMixer;
+}
+
+status_t AudioFlinger::MixerThread::dump(int fd, const Vector<String16>& args)
+{
+    dumpInternals(fd, args);
+    dumpTracks(fd, args);
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::MixerThread::dumpTracks(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "Output %d mixer thread tracks\n", mOutputType);
+    result.append(buffer);
+    result.append("   Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
+    for (size_t i = 0; i < mTracks.size(); ++i) {
+        wp<Track> wTrack = mTracks[i];
+        if (wTrack != 0) {
+            sp<Track> track = wTrack.promote();
+            if (track != 0) {
+                track->dump(buffer, SIZE);
+                result.append(buffer);
+            }
+        }
+    }
+
+    snprintf(buffer, SIZE, "Output %d mixer thread active tracks\n", mOutputType);
+    result.append(buffer);
+    result.append("   Name Clien Typ Fmt Chn Buf S M F SRate LeftV RighV Serv User\n");
+    for (size_t i = 0; i < mActiveTracks.size(); ++i) {
+        wp<Track> wTrack = mTracks[i];
+        if (wTrack != 0) {
+            sp<Track> track = wTrack.promote();
+            if (track != 0) {
+                track->dump(buffer, SIZE);
+                result.append(buffer);
+            }
+        }
+    }
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>& args)
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+    String8 result;
+
+    snprintf(buffer, SIZE, "Output %d mixer thread internals\n", mOutputType);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "AudioMixer tracks: %08x\n", mAudioMixer->trackNames());
+    result.append(buffer);
+    snprintf(buffer, SIZE, "last write occurred (msecs): %llu\n", ns2ms(systemTime() - mLastWriteTime));
+    result.append(buffer);
+    snprintf(buffer, SIZE, "total writes: %d\n", mNumWrites);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "delayed writes: %d\n", mNumDelayedWrites);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "blocked in write: %d\n", mInWrite);
+    result.append(buffer);
+    snprintf(buffer, SIZE, "standby: %d\n", mStandby);
+    result.append(buffer);
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+// Thread virtuals
+bool AudioFlinger::MixerThread::threadLoop()
+{
+    unsigned long sleepTime = kBufferRecoveryInUsecs;
+    int16_t* curBuf = mMixBuffer;
+    Vector< sp<Track> > tracksToRemove;
+    size_t enabledTracks = 0;
+    nsecs_t standbyTime = systemTime();   
+    size_t mixBufferSize = mFrameCount*mChannelCount*sizeof(int16_t);
+    nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 2;
+
+#ifdef WITH_A2DP
+    bool outputTrackActive = false;
+#endif
+
+    do {
+        enabledTracks = 0;
+        { // scope for the mLock
+        
+            Mutex::Autolock _l(mLock);
+
+#ifdef WITH_A2DP
+            if (mOutputType == AudioSystem::AUDIO_OUTPUT_A2DP) {
+                mAudioFlinger->handleOutputSwitch();
+            }
+            if (mOutputTrack != NULL && !mAudioFlinger->isA2dpEnabled()) {
+                if (outputTrackActive) {
+                    mOutputTrack->stop();
+                    outputTrackActive = false;
+                }
+            }
+#endif
+
+            const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
+
+            // put audio hardware into standby after short delay
+            if UNLIKELY(!activeTracks.size() && systemTime() > standbyTime) {
+                // wait until we have something to do...
+                LOGV("Audio hardware entering standby, output %d\n", mOutputType);
+//                mAudioFlinger->mHardwareStatus = AUDIO_HW_STANDBY;
+                if (!mStandby) {
+                    mOutput->standby();
+                    mStandby = true;
+                }
+                
+#ifdef WITH_A2DP
+                if (outputTrackActive) {
+                    mOutputTrack->stop();
+                    outputTrackActive = false;
+                }
+#endif
+                if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
+                    mAudioFlinger->handleForcedSpeakerRoute(FORCE_ROUTE_RESTORE);
+                }                
+//                mHardwareStatus = AUDIO_HW_IDLE;
+                // we're about to wait, flush the binder command buffer
+                IPCThreadState::self()->flushCommands();
+                mWaitWorkCV.wait(mLock);
+                LOGV("Audio hardware exiting standby, output %d\n", mOutputType);
+                standbyTime = systemTime() + kStandbyTimeInNsecs;
+                continue;
+            }
+
+            // Forced route to speaker is handled by hardware mixer thread
+            if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
+                mAudioFlinger->handleForcedSpeakerRoute(CHECK_ROUTE_RESTORE_TIME);
+            }
+
+            // find out which tracks need to be processed
+            size_t count = activeTracks.size();
+            for (size_t i=0 ; i<count ; i++) {
+                sp<Track> t = activeTracks[i].promote();
+                if (t == 0) continue;
+
+                Track* const track = t.get();
+                audio_track_cblk_t* cblk = track->cblk();
+
+                // The first time a track is added we wait
+                // for all its buffers to be filled before processing it
+                mAudioMixer->setActiveTrack(track->name());
+                if (cblk->framesReady() && (track->isReady() || track->isStopped()) &&
+                        !track->isPaused())
+                {
+                    //LOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
+
+                    // compute volume for this track
+                    int16_t left, right;
+                    if (track->isMuted() || mMasterMute || track->isPausing()) {
+                        left = right = 0;
+                        if (track->isPausing()) {
+                            LOGV("paused(%d)", track->name());
+                            track->setPaused();
+                        }
+                    } else {
+                        float typeVolume = mStreamTypes[track->type()].volume;
+                        float v = mMasterVolume * typeVolume;
+                        float v_clamped = v * cblk->volume[0];
+                        if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
+                        left = int16_t(v_clamped);
+                        v_clamped = v * cblk->volume[1];
+                        if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
+                        right = int16_t(v_clamped);
+                    }
+
+                    // XXX: these things DON'T need to be done each time
+                    mAudioMixer->setBufferProvider(track);
+                    mAudioMixer->enable(AudioMixer::MIXING);
+
+                    int param;
+                    if ( track->mFillingUpStatus == Track::FS_FILLED) {
+                        // no ramp for the first volume setting
+                        track->mFillingUpStatus = Track::FS_ACTIVE;
+                        if (track->mState == TrackBase::RESUMING) {
+                            track->mState = TrackBase::ACTIVE;
+                            param = AudioMixer::RAMP_VOLUME;
+                        } else {
+                            param = AudioMixer::VOLUME;
+                        }
+                    } else {
+                        param = AudioMixer::RAMP_VOLUME;
+                    }
+                    mAudioMixer->setParameter(param, AudioMixer::VOLUME0, left);
+                    mAudioMixer->setParameter(param, AudioMixer::VOLUME1, right);
+                    mAudioMixer->setParameter(
+                        AudioMixer::TRACK,
+                        AudioMixer::FORMAT, track->format());
+                    mAudioMixer->setParameter(
+                        AudioMixer::TRACK,
+                        AudioMixer::CHANNEL_COUNT, track->channelCount());
+                    mAudioMixer->setParameter(
+                        AudioMixer::RESAMPLE,
+                        AudioMixer::SAMPLE_RATE,
+                        int(cblk->sampleRate));
+
+                    // reset retry count
+                    track->mRetryCount = kMaxTrackRetries;
+                    enabledTracks++;
+                } else {
+                    //LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
+                    if (track->isStopped()) {
+                        track->reset();
+                    }
+                    if (track->isTerminated() || track->isStopped() || track->isPaused()) {
+                        // We have consumed all the buffers of this track.
+                        // Remove it from the list of active tracks.
+                        LOGV("remove(%d) from active list", track->name());
+                        tracksToRemove.add(track);
+                    } else {
+                        // No buffers for this track. Give it a few chances to
+                        // fill a buffer, then remove it from active list.
+                        if (--(track->mRetryCount) <= 0) {
+                            LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
+                            tracksToRemove.add(track);
+                        }
+                    }
+                    // LOGV("disable(%d)", track->name());
+                    mAudioMixer->disable(AudioMixer::MIXING);
+                }
+            }
+
+            // remove all the tracks that need to be...
+            count = tracksToRemove.size();
+            if (UNLIKELY(count)) {
+                for (size_t i=0 ; i<count ; i++) {
+                    const sp<Track>& track = tracksToRemove[i];
+                    removeActiveTrack(track);
+                    if (track->isTerminated()) {
+                        mTracks.remove(track);
+                        deleteTrackName(track->mName);
+                    }
+                }
+            }  
+       }
+        
+        if (LIKELY(enabledTracks)) {
+            // mix buffers...
+            mAudioMixer->process(curBuf);
+
+#ifdef WITH_A2DP
+            if (mOutputTrack != NULL && mAudioFlinger->isA2dpEnabled()) {
+                if (!outputTrackActive) {
+                    LOGV("starting output track in mixer for output %d", mOutputType);
+                    mOutputTrack->start();
+                    outputTrackActive = true;
+                }
+                mOutputTrack->write(curBuf, mFrameCount);
+            }
+#endif
+
+            // output audio to hardware
+            mLastWriteTime = systemTime();
+            mInWrite = true;
+            mOutput->write(curBuf, mixBufferSize);
+            mNumWrites++;
+            mInWrite = false;
+            mStandby = false;
+            nsecs_t temp = systemTime();
+            standbyTime = temp + kStandbyTimeInNsecs;
+            nsecs_t delta = temp - mLastWriteTime;
+            if (delta > maxPeriod) {
+                LOGW("write blocked for %llu msecs", ns2ms(delta));
+                mNumDelayedWrites++;
+            }
+            sleepTime = kBufferRecoveryInUsecs;
+        } else {         
+#ifdef WITH_A2DP
+            if (mOutputTrack != NULL && mAudioFlinger->isA2dpEnabled()) {
+                if (outputTrackActive) {
+                    mOutputTrack->write(curBuf, 0);
+                    if (mOutputTrack->bufferQueueEmpty()) {
+                        mOutputTrack->stop();
+                        outputTrackActive = false;
+                    } else {
+                        standbyTime = systemTime() + kStandbyTimeInNsecs;
+                    }
+                }
+            }
+#endif
+            // There was nothing to mix this round, which means all
+            // active tracks were late. Sleep a little bit to give
+            // them another chance. If we're too late, the audio
+            // hardware will zero-fill for us.
+//            LOGV("no buffers - usleep(%lu)", sleepTime);
+            usleep(sleepTime);
+            if (sleepTime < kMaxBufferRecoveryInUsecs) {
+                sleepTime += kBufferRecoveryInUsecs;
+            }
+        }
+
+        // finally let go of all our tracks, without the lock held
+        // since we can't guarantee the destructors won't acquire that
+        // same lock.
+        tracksToRemove.clear();
+    } while (true);
+
+    return false;
+}
+
+status_t AudioFlinger::MixerThread::readyToRun()
+{
+    if (mSampleRate == 0) {
+        LOGE("No working audio driver found.");
+        return NO_INIT;
+    }
+    LOGI("AudioFlinger's thread ready to run for output %d", mOutputType);
+    return NO_ERROR;
+}
+
+void AudioFlinger::MixerThread::onFirstRef()
+{
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+
+    snprintf(buffer, SIZE, "Mixer Thread for output %d", mOutputType);
+
+    run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);
+}
+
+
+sp<AudioFlinger::MixerThread::Track>  AudioFlinger::MixerThread::createTrack(
+        const sp<AudioFlinger::Client>& client,
+        int streamType,
+        uint32_t sampleRate,
+        int format,
+        int channelCount,
+        int frameCount,
+        const sp<IMemory>& sharedBuffer,
+        status_t *status)
+{
+    sp<Track> track;
+    status_t lStatus;
+    
+    // Resampler implementation limits input sampling rate to 2 x output sampling rate.
+    if (sampleRate > MAX_SAMPLE_RATE || sampleRate > mSampleRate*2) {
+        LOGE("Sample rate out of range: %d mSampleRate %d", sampleRate, mSampleRate);
+        lStatus = BAD_VALUE;
+        goto Exit;
+    }
+
+    {
+        Mutex::Autolock _l(mLock);
+
+        if (mSampleRate == 0) {
+            LOGE("Audio driver not initialized.");
+            lStatus = NO_INIT;
+            goto Exit;
+        }
+
+        track = new Track(this, client, streamType, sampleRate, format,
+                channelCount, frameCount, sharedBuffer);
+        mTracks.add(track);
+        lStatus = NO_ERROR;
+    }
+
+Exit:
+    if(status) {
+        *status = lStatus;
+    }
+    return track;
+}
+
+void AudioFlinger::MixerThread::getTracks(
+        SortedVector < sp<Track> >& tracks,
+        SortedVector < wp<Track> >& activeTracks)
+{
+    size_t size = mTracks.size();
+    LOGV ("MixerThread::getTracks() for output %d, mTracks.size %d, mActiveTracks.size %d", mOutputType,  mTracks.size(), mActiveTracks.size());
+    for (size_t i = 0; i < size; i++) {
+        sp<Track> t = mTracks[i];
+        if (AudioSystem::routedToA2dpOutput(t->mStreamType)) {
+            tracks.add(t);
+            int j = mActiveTracks.indexOf(t);
+            if (j >= 0) {
+                t = mActiveTracks[j].promote();
+                if (t != NULL) {
+                    activeTracks.add(t);                                    
+                }                            
+            }
+        }
+    }
+
+    size = activeTracks.size();
+    for (size_t i = 0; i < size; i++) {
+        removeActiveTrack(activeTracks[i]);
+    }
+    
+    size = tracks.size();
+    for (size_t i = 0; i < size; i++) {
+        sp<Track> t = tracks[i];
+        mTracks.remove(t);
+        deleteTrackName(t->name());
+    }
+}
+
+void AudioFlinger::MixerThread::putTracks(
+        SortedVector < sp<Track> >& tracks,
+        SortedVector < wp<Track> >& activeTracks)
+{
+
+    LOGV ("MixerThread::putTracks() for output %d, tracks.size %d, activeTracks.size %d", mOutputType,  tracks.size(), activeTracks.size());
+
+    size_t size = tracks.size();
+    for (size_t i = 0; i < size ; i++) {
+        sp<Track> t = tracks[i];
+        int name = getTrackName();
+
+        if (name < 0) return;
+        
+        t->mName = name;
+        t->mMixerThread = this;
+        mTracks.add(t);
+
+        int j = activeTracks.indexOf(t);
+        if (j >= 0) {
+            addActiveTrack(t);
+        }            
+    }
+}
+
+uint32_t AudioFlinger::MixerThread::sampleRate() const
+{
+    return mSampleRate;
+}
+
+int AudioFlinger::MixerThread::channelCount() const
+{
+    return mChannelCount;
+}
+
+int AudioFlinger::MixerThread::format() const
+{
+    return mFormat;
+}
+
+size_t AudioFlinger::MixerThread::frameCount() const
+{
+    return mFrameCount;
+}
+
+uint32_t AudioFlinger::MixerThread::latency() const
+{
+    if (mOutput) {
+        return mOutput->latency();
+    }
+    else {
+        return 0;
+    }
+}
+
+status_t AudioFlinger::MixerThread::setMasterVolume(float value)
+{
+    mMasterVolume = value;
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::MixerThread::setMasterMute(bool muted)
+{
+    mMasterMute = muted;
+    return NO_ERROR;
+}
+
+float AudioFlinger::MixerThread::masterVolume() const
+{
+    return mMasterVolume;
+}
+
+bool AudioFlinger::MixerThread::masterMute() const
+{
+    return mMasterMute;
+}
+
+status_t AudioFlinger::MixerThread::setStreamVolume(int stream, float value)
+{
+    mStreamTypes[stream].volume = value;
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::MixerThread::setStreamMute(int stream, bool muted)
+{
+    mStreamTypes[stream].mute = muted;
+    return NO_ERROR;
+}
+
+float AudioFlinger::MixerThread::streamVolume(int stream) const
+{
+    return mStreamTypes[stream].volume;
+}
+
+bool AudioFlinger::MixerThread::streamMute(int stream) const
+{
+    return mStreamTypes[stream].mute;
+}
+
+bool AudioFlinger::MixerThread::isMusicActive() const
+{
+    size_t count = mActiveTracks.size();
+    for (size_t i = 0 ; i < count ; ++i) {
+        sp<Track> t = mActiveTracks[i].promote();
+        if (t == 0) continue;
+        Track* const track = t.get();
+        if (t->mStreamType == AudioSystem::MUSIC)
+            return true;
+    }
+    return false;
+}
+
+status_t AudioFlinger::MixerThread::addTrack(const sp<Track>& track)
+{
+    status_t status = ALREADY_EXISTS;
+    Mutex::Autolock _l(mLock);
+
+    // here the track could be either new, or restarted
+    // in both cases "unstop" the track
     if (track->isPaused()) {
         track->mState = TrackBase::RESUMING;
         LOGV("PAUSED => RESUMING (%d)", track->name());
@@ -981,9 +1395,6 @@ status_t AudioFlinger::addTrack(const sp<Track>& track)
     }
     // set retry count for buffer fill
     track->mRetryCount = kMaxTrackStartupRetries;
-    LOGV("mWaitWorkCV.broadcast");
-    mWaitWorkCV.broadcast();
-
     if (mActiveTracks.indexOf(track) < 0) {
         // the track is newly added, make sure it fills up all its
         // buffers before playing. This is to ensure the client will
@@ -991,12 +1402,16 @@ status_t AudioFlinger::addTrack(const sp<Track>& track)
         track->mFillingUpStatus = Track::FS_FILLING;
         track->mResetDone = false;
         addActiveTrack(track);
-        return NO_ERROR;
+        status = NO_ERROR;
     }
-    return ALREADY_EXISTS;
+    
+    LOGV("mWaitWorkCV.broadcast");
+    mWaitWorkCV.broadcast();
+
+    return status;
 }
 
-void AudioFlinger::removeTrack(wp<Track> track, int name)
+void AudioFlinger::MixerThread::removeTrack(wp<Track> track, int name)
 {
     Mutex::Autolock _l(mLock);
     sp<Track> t = track.promote();
@@ -1005,7 +1420,7 @@ void AudioFlinger::removeTrack(wp<Track> track, int name)
     }
 }
 
-void AudioFlinger::remove_track_l(wp<Track> track, int name)
+void AudioFlinger::MixerThread::remove_track_l(wp<Track> track, int name)
 {
     sp<Track> t = track.promote();
     if (t!=NULL) {
@@ -1016,7 +1431,7 @@ void AudioFlinger::remove_track_l(wp<Track> track, int name)
     mWaitWorkCV.broadcast();
 }
 
-void AudioFlinger::destroyTrack(const sp<Track>& track)
+void AudioFlinger::MixerThread::destroyTrack(const sp<Track>& track)
 {
     // NOTE: We're acquiring a strong reference on the track before
     // acquiring the lock, this is to make sure removing it from
@@ -1033,99 +1448,58 @@ void AudioFlinger::destroyTrack(const sp<Track>& track)
     }
 }
 
-void AudioFlinger::addActiveTrack(const wp<Track>& t)
+
+void AudioFlinger::MixerThread::addActiveTrack(const wp<Track>& t)
 {
     mActiveTracks.add(t);
 
-#ifdef WITH_A2DP
-    // disable A2DP for certain stream types
-    sp<Track> track = t.promote();
-    if (streamDisablesA2dp(track->type())) {
-        if (mA2dpDisableCount++ == 0 && isA2dpEnabled()) {
-            setA2dpEnabled(false);
-            mA2dpSuppressed = true;
-            mMusicMuteSaved = mStreamTypes[AudioTrack::MUSIC].mute;
-            mStreamTypes[AudioTrack::MUSIC].mute = true;
-            LOGV("mA2dpSuppressed = true, track %d\n", track->name());
-        }
-        LOGV("mA2dpDisableCount incremented to %d, track %d\n", mA2dpDisableCount, track->name());
+    // Force routing to speaker for certain stream types
+    // The forced routing to speaker is managed by hardware mixer
+    if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
+        sp<Track> track = t.promote();
+        if (track == NULL) return;
+   
+        if (streamForcedToSpeaker(track->type())) {
+            mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_ADDED);
+        }        
     }
-#endif
-}
-
-void AudioFlinger::removeActiveTrack(const wp<Track>& t)
-{
-    mActiveTracks.remove(t);
-#ifdef WITH_A2DP
-    // disable A2DP for certain stream types
-    sp<Track> track = t.promote();
-    if (streamDisablesA2dp(track->type())) {
-        if (mA2dpDisableCount > 0) {
-            mA2dpDisableCount--;
-            LOGV("mA2dpDisableCount decremented to %d, track %d\n", mA2dpDisableCount, track->name());
-            if (mA2dpDisableCount == 0 && mA2dpSuppressed) {
-                setA2dpEnabled(true);
-                mA2dpSuppressed = false;
-                mStreamTypes[AudioTrack::MUSIC].mute = mMusicMuteSaved;
-                LOGV("mA2dpSuppressed = false, track %d\n", track->name());
-            }   
-        } else
-            LOGE("mA2dpDisableCount is already zero");
-    }
-#endif
-}
-
-int AudioFlinger::getTrackName()
-{
-    // Both mixers must have the same set of track used to avoid mismatches when
-    // switching from A2DP output to hardware output
-    int a2DpName;
-    int hwName;
-#ifdef WITH_A2DP
-    a2DpName = mA2dpAudioMixer->getTrackName();
-#endif
-    hwName = mHardwareAudioMixer->getTrackName();
-    
-    LOGW_IF((a2DpName != hwName), "getTrackName track name mismatch! A2DP %d, HW %d", a2DpName, hwName);
-    
-    return hwName;
-}
-
-void AudioFlinger::deleteTrackName(int name)
-{
-    // Both mixers must have the same set of track used to avoid mismatches when
-    // switching from A2DP output to hardware output
-    mHardwareAudioMixer->deleteTrackName(name);
-#ifdef WITH_A2DP
-    mA2dpAudioMixer->deleteTrackName(name);
-#endif
 }
 
-// ----------------------------------------------------------------------------
+void AudioFlinger::MixerThread::removeActiveTrack(const wp<Track>& t)
+{
+    mActiveTracks.remove(t);
 
-AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
-    :   RefBase(),
-        mAudioFlinger(audioFlinger),
-        mMemoryDealer(new MemoryDealer(1024*1024)),
-        mPid(pid)
+    // Force routing to speaker for certain stream types
+    // The forced routing to speaker is managed by hardware mixer
+    if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
+        sp<Track> track = t.promote();
+        if (track == NULL) return;
+
+        if (streamForcedToSpeaker(track->type())) {
+            mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_REMOVED);
+        }
+    }
+}
+
+int AudioFlinger::MixerThread::getTrackName()
 {
-    // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
+    return mAudioMixer->getTrackName();
 }
 
-AudioFlinger::Client::~Client()
+void AudioFlinger::MixerThread::deleteTrackName(int name)
 {
-    mAudioFlinger->removeClient(mPid);
+    mAudioMixer->deleteTrackName(name);
 }
 
-const sp<MemoryDealer>& AudioFlinger::Client::heap() const
+size_t AudioFlinger::MixerThread::getOutputFrameCount() 
 {
-    return mMemoryDealer;
+    return mOutput->bufferSize() / mOutput->channelCount() / sizeof(int16_t);
 }
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::TrackBase::TrackBase(
-            const sp<AudioFlinger>& audioFlinger,
+AudioFlinger::MixerThread::TrackBase::TrackBase(
+            const sp<MixerThread>& mixerThread,
             const sp<Client>& client,
             int streamType,
             uint32_t sampleRate,
@@ -1134,7 +1508,7 @@ AudioFlinger::TrackBase::TrackBase(
             int frameCount,
             const sp<IMemory>& sharedBuffer)
     :   RefBase(),
-        mAudioFlinger(audioFlinger),
+        mMixerThread(mixerThread),
         mClient(client),
         mStreamType(streamType),
         mFrameCount(0),
@@ -1143,7 +1517,7 @@ AudioFlinger::TrackBase::TrackBase(
         mFormat(format),
         mFlags(0)
 {
-    mName = audioFlinger->getTrackName();
+    mName = mixerThread->getTrackName();
     LOGV("TrackBase contructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
     if (mName < 0) {
         LOGE("no more track names availlable");
@@ -1160,41 +1534,60 @@ AudioFlinger::TrackBase::TrackBase(
        size += bufferSize;
    }
 
-    mCblkMemory = client->heap()->allocate(size);
-    if (mCblkMemory != 0) {
-        mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
-        if (mCblk) { // construct the shared structure in-place.
-            new(mCblk) audio_track_cblk_t();
-            // clear all buffers
-            mCblk->frameCount = frameCount;
-            mCblk->sampleRate = sampleRate;
-            mCblk->channels = channelCount;
-            if (sharedBuffer == 0) {
-                mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
-                memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
-                // Force underrun condition to avoid false underrun callback until first data is
-                // written to buffer
-                mCblk->flowControlFlag = 1;
-            } else {
-                mBuffer = sharedBuffer->pointer();
+   if (client != NULL) {
+        mCblkMemory = client->heap()->allocate(size);
+        if (mCblkMemory != 0) {
+            mCblk = static_cast<audio_track_cblk_t *>(mCblkMemory->pointer());
+            if (mCblk) { // construct the shared structure in-place.
+                new(mCblk) audio_track_cblk_t();
+                // clear all buffers
+                mCblk->frameCount = frameCount;
+                mCblk->sampleRate = sampleRate;
+                mCblk->channels = channelCount;
+                if (sharedBuffer == 0) {
+                    mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
+                    memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
+                    // Force underrun condition to avoid false underrun callback until first data is
+                    // written to buffer
+                    mCblk->flowControlFlag = 1;
+                } else {
+                    mBuffer = sharedBuffer->pointer();
+                }
+                mBufferEnd = (uint8_t *)mBuffer + bufferSize;
             }
-            mBufferEnd = (uint8_t *)mBuffer + bufferSize;
+        } else {
+            LOGE("not enough memory for AudioTrack size=%u", size);
+            client->heap()->dump("AudioTrack");
+            return;
         }
-    } else {
-        LOGE("not enough memory for AudioTrack size=%u", size);
-        client->heap()->dump("AudioTrack");
-        return;
-    }
+   } else {
+       mCblk = (audio_track_cblk_t *)(new uint8_t[size]);
+       if (mCblk) { // construct the shared structure in-place.
+           new(mCblk) audio_track_cblk_t();
+           // clear all buffers
+           mCblk->frameCount = frameCount;
+           mCblk->sampleRate = sampleRate;
+           mCblk->channels = channelCount;
+           mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
+           memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
+           // Force underrun condition to avoid false underrun callback until first data is
+           // written to buffer
+           mCblk->flowControlFlag = 1;
+           mBufferEnd = (uint8_t *)mBuffer + bufferSize;
+       }
+   }
 }
 
-AudioFlinger::TrackBase::~TrackBase()
+AudioFlinger::MixerThread::TrackBase::~TrackBase()
 {
-    mCblk->~audio_track_cblk_t();   // destroy our shared-structure.
+    if (mCblk) {
+        mCblk->~audio_track_cblk_t();   // destroy our shared-structure.        
+    }
     mCblkMemory.clear();            // and free the shared memory
     mClient.clear();
 }
 
-void AudioFlinger::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
+void AudioFlinger::MixerThread::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
 {
     buffer->raw = 0;
     mFrameCount = buffer->frameCount;
@@ -1202,7 +1595,7 @@ void AudioFlinger::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
     buffer->frameCount = 0;
 }
 
-bool AudioFlinger::TrackBase::step() {
+bool AudioFlinger::MixerThread::TrackBase::step() {
     bool result;
     audio_track_cblk_t* cblk = this->cblk();
 
@@ -1214,7 +1607,7 @@ bool AudioFlinger::TrackBase::step() {
     return result;
 }
 
-void AudioFlinger::TrackBase::reset() {
+void AudioFlinger::MixerThread::TrackBase::reset() {
     audio_track_cblk_t* cblk = this->cblk();
 
     cblk->user = 0;
@@ -1225,20 +1618,20 @@ void AudioFlinger::TrackBase::reset() {
     LOGV("TrackBase::reset");
 }
 
-sp<IMemory> AudioFlinger::TrackBase::getCblk() const
+sp<IMemory> AudioFlinger::MixerThread::TrackBase::getCblk() const
 {
     return mCblkMemory;
 }
 
-int AudioFlinger::TrackBase::sampleRate() const {
+int AudioFlinger::MixerThread::TrackBase::sampleRate() const {
     return mCblk->sampleRate;
 }
 
-int AudioFlinger::TrackBase::channelCount() const {
+int AudioFlinger::MixerThread::TrackBase::channelCount() const {
     return mCblk->channels;
 }
 
-void* AudioFlinger::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
+void* AudioFlinger::MixerThread::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
     audio_track_cblk_t* cblk = this->cblk();
     int16_t *bufferStart = (int16_t *)mBuffer + (offset-cblk->serverBase)*cblk->channels;
     int16_t *bufferEnd = bufferStart + frames * cblk->channels;
@@ -1257,8 +1650,8 @@ void* AudioFlinger::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::Track::Track(
-            const sp<AudioFlinger>& audioFlinger,
+AudioFlinger::MixerThread::Track::Track(
+            const sp<MixerThread>& mixerThread,
             const sp<Client>& client,
             int streamType,
             uint32_t sampleRate,
@@ -1266,7 +1659,7 @@ AudioFlinger::Track::Track(
             int channelCount,
             int frameCount,
             const sp<IMemory>& sharedBuffer)
-    :   TrackBase(audioFlinger, client, streamType, sampleRate, format, channelCount, frameCount, sharedBuffer)
+    :   TrackBase(mixerThread, client, streamType, sampleRate, format, channelCount, frameCount, sharedBuffer)
 {
     mVolume[0] = 1.0f;
     mVolume[1] = 1.0f;
@@ -1274,23 +1667,23 @@ AudioFlinger::Track::Track(
     mSharedBuffer = sharedBuffer;
 }
 
-AudioFlinger::Track::~Track()
+AudioFlinger::MixerThread::Track::~Track()
 {
     wp<Track> weak(this); // never create a strong ref from the dtor
     mState = TERMINATED;
-    mAudioFlinger->removeTrack(weak, mName);
+    mMixerThread->removeTrack(weak, mName);
 }
 
-void AudioFlinger::Track::destroy()
+void AudioFlinger::MixerThread::Track::destroy()
 {
-    mAudioFlinger->destroyTrack(this);
+    mMixerThread->destroyTrack(this);
 }
 
-void AudioFlinger::Track::dump(char* buffer, size_t size)
+void AudioFlinger::MixerThread::Track::dump(char* buffer, size_t size)
 {
     snprintf(buffer, size, "  %5d %5d %3u %3u %3u %3u %1d %1d %1d %5u %5u %5u %04x %04x\n",
             mName - AudioMixer::TRACK0,
-            mClient->pid(),
+            (mClient == NULL) ? getpid() : mClient->pid(),
             mStreamType,
             mFormat,
             mCblk->channels,
@@ -1305,7 +1698,7 @@ void AudioFlinger::Track::dump(char* buffer, size_t size)
             mCblk->user);
 }
 
-status_t AudioFlinger::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
+status_t AudioFlinger::MixerThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
 {
      audio_track_cblk_t* cblk = this->cblk();
      uint32_t framesReady;
@@ -1345,53 +1738,54 @@ getNextBuffer_exit:
      return NOT_ENOUGH_DATA;
 }
 
-bool AudioFlinger::Track::isReady() const {
+bool AudioFlinger::MixerThread::Track::isReady() const {
     if (mFillingUpStatus != FS_FILLING) return true;
 
     if (mCblk->framesReady() >= mCblk->frameCount ||
         mCblk->forceReady) {
         mFillingUpStatus = FS_FILLED;
         mCblk->forceReady = 0;
+        LOGV("Track::isReady() track %d for output %d", mName, mMixerThread->mOutputType);
         return true;
     }
     return false;
 }
 
-status_t AudioFlinger::Track::start()
+status_t AudioFlinger::MixerThread::Track::start()
 {
-    LOGV("start(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
-    mAudioFlinger->addTrack(this);
+    LOGV("start(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType);
+    mMixerThread->addTrack(this);
     return NO_ERROR;
 }
 
-void AudioFlinger::Track::stop()
+void AudioFlinger::MixerThread::Track::stop()
 {
-    LOGV("stop(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
-    Mutex::Autolock _l(mAudioFlinger->mLock);
+    LOGV("stop(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType);
+    Mutex::Autolock _l(mMixerThread->mLock);
     if (mState > STOPPED) {
         mState = STOPPED;
         // If the track is not active (PAUSED and buffers full), flush buffers
-        if (mAudioFlinger->mActiveTracks.indexOf(this) < 0) {
+        if (mMixerThread->mActiveTracks.indexOf(this) < 0) {
             reset();
         }
         LOGV("(> STOPPED) => STOPPED (%d)", mName);
     }
 }
 
-void AudioFlinger::Track::pause()
+void AudioFlinger::MixerThread::Track::pause()
 {
     LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
-    Mutex::Autolock _l(mAudioFlinger->mLock);
+    Mutex::Autolock _l(mMixerThread->mLock);
     if (mState == ACTIVE || mState == RESUMING) {
         mState = PAUSING;
         LOGV("ACTIVE/RESUMING => PAUSING (%d)", mName);
     }
 }
 
-void AudioFlinger::Track::flush()
+void AudioFlinger::MixerThread::Track::flush()
 {
     LOGV("flush(%d)", mName);
-    Mutex::Autolock _l(mAudioFlinger->mLock);
+    Mutex::Autolock _l(mMixerThread->mLock);
     if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
         return;
     }
@@ -1407,7 +1801,7 @@ void AudioFlinger::Track::flush()
     reset();
 }
 
-void AudioFlinger::Track::reset()
+void AudioFlinger::MixerThread::Track::reset()
 {
     // Do not reset twice to avoid discarding data written just after a flush and before
     // the audioflinger thread detects the track is stopped.
@@ -1422,12 +1816,12 @@ void AudioFlinger::Track::reset()
     }
 }
 
-void AudioFlinger::Track::mute(bool muted)
+void AudioFlinger::MixerThread::Track::mute(bool muted)
 {
     mMute = muted;
 }
 
-void AudioFlinger::Track::setVolume(float left, float right)
+void AudioFlinger::MixerThread::Track::setVolume(float left, float right)
 {
     mVolume[0] = left;
     mVolume[1] = right;
@@ -1435,7 +1829,289 @@ void AudioFlinger::Track::setVolume(float left, float right)
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::Track>& track)
+AudioFlinger::MixerThread::RecordTrack::RecordTrack(
+            const sp<MixerThread>& mixerThread,
+            const sp<Client>& client,
+            int streamType,
+            uint32_t sampleRate,
+            int format,
+            int channelCount,
+            int frameCount)
+    :   TrackBase(mixerThread, client, streamType, sampleRate, format,
+            channelCount, frameCount, 0),
+            mOverflow(false)
+{
+}
+
+AudioFlinger::MixerThread::RecordTrack::~RecordTrack()
+{
+    mMixerThread->deleteTrackName(mName);
+}
+
+status_t AudioFlinger::MixerThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
+{
+    audio_track_cblk_t* cblk = this->cblk();
+    uint32_t framesAvail;
+    uint32_t framesReq = buffer->frameCount;
+
+     // Check if last stepServer failed, try to step now
+    if (mFlags & TrackBase::STEPSERVER_FAILED) {
+        if (!step()) goto getNextBuffer_exit;
+        LOGV("stepServer recovered");
+        mFlags &= ~TrackBase::STEPSERVER_FAILED;
+    }
+
+    framesAvail = cblk->framesAvailable_l();
+
+    if (LIKELY(framesAvail)) {
+        uint32_t s = cblk->server;
+        uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
+
+        if (framesReq > framesAvail) {
+            framesReq = framesAvail;
+        }
+        if (s + framesReq > bufferEnd) {
+            framesReq = bufferEnd - s;
+        }
+
+        buffer->raw = getBuffer(s, framesReq);
+        if (buffer->raw == 0) goto getNextBuffer_exit;
+
+        buffer->frameCount = framesReq;
+        return NO_ERROR;
+    }
+
+getNextBuffer_exit:
+    buffer->raw = 0;
+    buffer->frameCount = 0;
+    return NOT_ENOUGH_DATA;
+}
+
+status_t AudioFlinger::MixerThread::RecordTrack::start()
+{
+    return mMixerThread->mAudioFlinger->startRecord(this);
+}
+
+void AudioFlinger::MixerThread::RecordTrack::stop()
+{
+    mMixerThread->mAudioFlinger->stopRecord(this);
+    TrackBase::reset();
+    // Force overerrun condition to avoid false overrun callback until first data is
+    // read from buffer
+    mCblk->flowControlFlag = 1;
+}
+
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::MixerThread::OutputTrack::OutputTrack(
+            const sp<MixerThread>& mixerThread,
+            uint32_t sampleRate,
+            int format,
+            int channelCount,
+            int frameCount)
+    :   Track(mixerThread, NULL, AudioSystem::SYSTEM, sampleRate, format, channelCount, frameCount, NULL),
+    mOutputMixerThread(mixerThread)
+{
+                
+    mCblk->out = 1;
+    mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
+    mCblk->volume[0] = mCblk->volume[1] = 0x1000;
+    mOutBuffer.frameCount = 0;
+    mCblk->bufferTimeoutMs = 10;
+    
+    LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channels %d mBufferEnd %p", 
+            mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channels, mBufferEnd);
+    
+}
+
+AudioFlinger::MixerThread::OutputTrack::~OutputTrack()
+{
+    stop();
+}
+
+status_t AudioFlinger::MixerThread::OutputTrack::start()
+{
+    status_t status = Track::start();
+    
+    mRetryCount = 127;
+    return status;
+}
+
+void AudioFlinger::MixerThread::OutputTrack::stop()
+{
+    Track::stop();
+    clearBufferQueue();
+    mOutBuffer.frameCount = 0;
+}
+
+void AudioFlinger::MixerThread::OutputTrack::write(int16_t* data, uint32_t frames)
+{
+    Buffer *pInBuffer;
+    Buffer inBuffer;
+    uint32_t channels = mCblk->channels;
+        
+    inBuffer.frameCount = frames;
+    inBuffer.i16 = data;
+    
+    if (mCblk->user == 0) {
+        if (mOutputMixerThread->isMusicActive()) {
+            mCblk->forceReady = 1;
+            LOGV("OutputTrack::start() force ready");
+        } else if (mCblk->frameCount > frames){
+            if (mBufferQueue.size() < kMaxOutputTrackBuffers) {
+                uint32_t startFrames = (mCblk->frameCount - frames);
+                LOGV("OutputTrack::start() write %d frames", startFrames);
+                pInBuffer = new Buffer;
+                pInBuffer->mBuffer = new int16_t[startFrames * channels];
+                pInBuffer->frameCount = startFrames;
+                pInBuffer->i16 = pInBuffer->mBuffer;
+                memset(pInBuffer->raw, 0, startFrames * channels * sizeof(int16_t));
+                mBufferQueue.add(pInBuffer);                
+            } else {
+                LOGW ("OutputTrack::write() no more buffers");
+            }
+        }        
+    }
+
+    while (1) { 
+        // First write pending buffers, then new data
+        if (mBufferQueue.size()) {
+            pInBuffer = mBufferQueue.itemAt(0);
+        } else {
+            pInBuffer = &inBuffer;
+        }
+ 
+        if (pInBuffer->frameCount == 0) {
+            break;
+        }
+        
+        if (mOutBuffer.frameCount == 0) {
+            mOutBuffer.frameCount = pInBuffer->frameCount;
+            if (obtainBuffer(&mOutBuffer) == (status_t)AudioTrack::NO_MORE_BUFFERS) {
+                break;
+            }
+        }
+            
+        uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount;
+        memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channels * sizeof(int16_t));
+        mCblk->stepUser(outFrames);
+        pInBuffer->frameCount -= outFrames;
+        pInBuffer->i16 += outFrames * channels;
+        mOutBuffer.frameCount -= outFrames;
+        mOutBuffer.i16 += outFrames * channels;            
+        
+        if (pInBuffer->frameCount == 0) {
+            if (mBufferQueue.size()) {
+                mBufferQueue.removeAt(0);
+                delete [] pInBuffer->mBuffer;
+                delete pInBuffer;
+            } else {
+                break;
+            }
+        }
+    }
+ 
+    // If we could not write all frames, allocate a buffer and queue it for next time.
+    if (inBuffer.frameCount) {
+        if (mBufferQueue.size() < kMaxOutputTrackBuffers) {
+            pInBuffer = new Buffer;
+            pInBuffer->mBuffer = new int16_t[inBuffer.frameCount * channels];
+            pInBuffer->frameCount = inBuffer.frameCount;
+            pInBuffer->i16 = pInBuffer->mBuffer;
+            memcpy(pInBuffer->raw, inBuffer.raw, inBuffer.frameCount * channels * sizeof(int16_t));
+            mBufferQueue.add(pInBuffer);
+        } else {
+            LOGW("OutputTrack::write() no more buffers");
+        }
+    }
+    
+    // Calling write() with a 0 length buffer, means that no more data will be written:
+    // If no more buffers are pending, fill output track buffer to make sure it is started 
+    // by output mixer.
+    if (frames == 0 && mBufferQueue.size() == 0 && mCblk->user < mCblk->frameCount) {
+        frames = mCblk->frameCount - mCblk->user;
+        pInBuffer = new Buffer;
+        pInBuffer->mBuffer = new int16_t[frames * channels];
+        pInBuffer->frameCount = frames;
+        pInBuffer->i16 = pInBuffer->mBuffer;
+        memset(pInBuffer->raw, 0, frames * channels * sizeof(int16_t));
+        mBufferQueue.add(pInBuffer);
+    }
+
+}
+
+status_t AudioFlinger::MixerThread::OutputTrack::obtainBuffer(AudioBufferProvider::Buffer* buffer)
+{
+    int active;
+    int timeout = 0;
+    status_t result;
+    audio_track_cblk_t* cblk = mCblk;
+    uint32_t framesReq = buffer->frameCount;
+
+    LOGV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server);
+    buffer->frameCount  = 0;
+    
+    uint32_t framesAvail = cblk->framesAvailable();
+
+    if (framesAvail == 0) {
+        return AudioTrack::NO_MORE_BUFFERS;
+    }
+
+    if (framesReq > framesAvail) {
+        framesReq = framesAvail;
+    }
+
+    uint32_t u = cblk->user;
+    uint32_t bufferEnd = cblk->userBase + cblk->frameCount;
+
+    if (u + framesReq > bufferEnd) {
+        framesReq = bufferEnd - u;
+    }
+
+    buffer->frameCount  = framesReq;
+    buffer->raw         = (void *)cblk->buffer(u);
+    return NO_ERROR;
+}
+
+
+void AudioFlinger::MixerThread::OutputTrack::clearBufferQueue()
+{
+    size_t size = mBufferQueue.size();
+    Buffer *pBuffer;
+    
+    for (size_t i = 0; i < size; i++) {
+        pBuffer = mBufferQueue.itemAt(i);
+        delete [] pBuffer->mBuffer;
+        delete pBuffer;
+    }
+    mBufferQueue.clear();
+}
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
+    :   RefBase(),
+        mAudioFlinger(audioFlinger),
+        mMemoryDealer(new MemoryDealer(1024*1024)),
+        mPid(pid)
+{
+    // 1 MB of address space is good for 32 tracks, 8 buffers each, 4 KB/buffer
+}
+
+AudioFlinger::Client::~Client()
+{
+    mAudioFlinger->removeClient(mPid);
+}
+
+const sp<MemoryDealer>& AudioFlinger::Client::heap() const
+{
+    return mMemoryDealer;
+}
+
+// ----------------------------------------------------------------------------
+
+AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::MixerThread::Track>& track)
     : BnAudioTrack(),
       mTrack(track)
 {
@@ -1496,7 +2172,7 @@ sp<IAudioRecord> AudioFlinger::openRecord(
         status_t *status)
 {
     sp<AudioRecordThread> thread;
-    sp<RecordTrack> recordTrack;
+    sp<MixerThread::RecordTrack> recordTrack;
     sp<RecordHandle> recordHandle;
     sp<Client> client;
     wp<Client> wclient;
@@ -1523,12 +2199,6 @@ sp<IAudioRecord> AudioFlinger::openRecord(
         goto Exit;
     }
 
-    if (mSampleRate == 0) {
-        LOGE("Audio driver not initialized");
-        lStatus = NO_INIT;
-        goto Exit;
-    }
-
     if (mAudioRecordThread == 0) {
         LOGE("Audio record thread not started");
         lStatus = NO_INIT;
@@ -1561,7 +2231,7 @@ sp<IAudioRecord> AudioFlinger::openRecord(
     frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount;
 
     // create new record track and pass to record thread
-    recordTrack = new RecordTrack(this, client, streamType, sampleRate,
+    recordTrack = new MixerThread::RecordTrack(mHardwareMixerThread, client, streamType, sampleRate,
             format, channelCount, frameCount);
 
     // return to handle to client
@@ -1575,97 +2245,22 @@ Exit:
     return recordHandle;
 }
 
-status_t AudioFlinger::startRecord(RecordTrack* recordTrack) {
+status_t AudioFlinger::startRecord(MixerThread::RecordTrack* recordTrack) {
     if (mAudioRecordThread != 0) {
         return mAudioRecordThread->start(recordTrack);        
     }
     return NO_INIT;
 }
 
-void AudioFlinger::stopRecord(RecordTrack* recordTrack) {
+void AudioFlinger::stopRecord(MixerThread::RecordTrack* recordTrack) {
     if (mAudioRecordThread != 0) {
         mAudioRecordThread->stop(recordTrack);
     }
 }
 
-
-// ----------------------------------------------------------------------------
-
-AudioFlinger::RecordTrack::RecordTrack(
-            const sp<AudioFlinger>& audioFlinger,
-            const sp<Client>& client,
-            int streamType,
-            uint32_t sampleRate,
-            int format,
-            int channelCount,
-            int frameCount)
-    :   TrackBase(audioFlinger, client, streamType, sampleRate, format,
-            channelCount, frameCount, 0),
-            mOverflow(false)
-{
-}
-
-AudioFlinger::RecordTrack::~RecordTrack()
-{
-    mAudioFlinger->deleteTrackName(mName);
-}
-
-status_t AudioFlinger::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
-{
-    audio_track_cblk_t* cblk = this->cblk();
-    uint32_t framesAvail;
-    uint32_t framesReq = buffer->frameCount;
-
-     // Check if last stepServer failed, try to step now
-    if (mFlags & TrackBase::STEPSERVER_FAILED) {
-        if (!step()) goto getNextBuffer_exit;
-        LOGV("stepServer recovered");
-        mFlags &= ~TrackBase::STEPSERVER_FAILED;
-    }
-
-    framesAvail = cblk->framesAvailable_l();
-
-    if (LIKELY(framesAvail)) {
-        uint32_t s = cblk->server;
-        uint32_t bufferEnd = cblk->serverBase + cblk->frameCount;
-
-        if (framesReq > framesAvail) {
-            framesReq = framesAvail;
-        }
-        if (s + framesReq > bufferEnd) {
-            framesReq = bufferEnd - s;
-        }
-
-        buffer->raw = getBuffer(s, framesReq);
-        if (buffer->raw == 0) goto getNextBuffer_exit;
-
-        buffer->frameCount = framesReq;
-        return NO_ERROR;
-    }
-
-getNextBuffer_exit:
-    buffer->raw = 0;
-    buffer->frameCount = 0;
-    return NOT_ENOUGH_DATA;
-}
-
-status_t AudioFlinger::RecordTrack::start()
-{
-    return mAudioFlinger->startRecord(this);
-}
-
-void AudioFlinger::RecordTrack::stop()
-{
-    mAudioFlinger->stopRecord(this);
-    TrackBase::reset();
-    // Force overerrun condition to avoid false overrun callback until first data is
-    // read from buffer
-    mCblk->flowControlFlag = 1;
-}
-
 // ----------------------------------------------------------------------------
 
-AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordTrack>& recordTrack)
+AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::MixerThread::RecordTrack>& recordTrack)
     : BnAudioRecord(),
     mRecordTrack(recordTrack)
 {
@@ -1786,7 +2381,7 @@ bool AudioFlinger::AudioRecordThread::threadLoop()
     return false;
 }
 
-status_t AudioFlinger::AudioRecordThread::start(RecordTrack* recordTrack)
+status_t AudioFlinger::AudioRecordThread::start(MixerThread::RecordTrack* recordTrack)
 {
     LOGV("AudioRecordThread::start");
     AutoMutex lock(&mLock);
@@ -1807,7 +2402,7 @@ status_t AudioFlinger::AudioRecordThread::start(RecordTrack* recordTrack)
     return mStartStatus;
 }
 
-void AudioFlinger::AudioRecordThread::stop(RecordTrack* recordTrack) {
+void AudioFlinger::AudioRecordThread::stop(MixerThread::RecordTrack* recordTrack) {
     LOGV("AudioRecordThread::stop");
     AutoMutex lock(&mLock);
     if (mActive && (recordTrack == mRecordTrack.get())) {
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index 38fa0017e7d1..3b5932deea5a 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -33,6 +33,7 @@
 #include <utils/MemoryDealer.h>
 #include <utils/KeyedVector.h>
 #include <utils/SortedVector.h>
+#include <utils/Vector.h>
 
 #include <hardware_legacy/AudioHardwareInterface.h>
 
@@ -55,18 +56,13 @@ class AudioBuffer;
 
 static const nsecs_t kStandbyTimeInNsecs = seconds(3);
 
-class AudioFlinger : public BnAudioFlinger, protected Thread, public IBinder::DeathRecipient 
+class AudioFlinger : public BnAudioFlinger, public IBinder::DeathRecipient 
 {
 public:
     static void instantiate();
 
     virtual     status_t    dump(int fd, const Vector<String16>& args);
 
-    // Thread virtuals
-    virtual     bool        threadLoop();
-    virtual     status_t    readyToRun();
-    virtual     void        onFirstRef();
-
     // IAudioFlinger interface
     virtual sp<IAudioTrack> createTrack(
                                 pid_t pid,
@@ -79,11 +75,11 @@ public:
                                 const sp<IMemory>& sharedBuffer,
                                 status_t *status);
 
-    virtual     uint32_t    sampleRate() const;
-    virtual     int         channelCount() const;
-    virtual     int         format() const;
-    virtual     size_t      frameCount() const;
-    virtual     size_t      latency() const;
+    virtual     uint32_t    sampleRate(int output) const;
+    virtual     int         channelCount(int output) const;
+    virtual     int         format(int output) const;
+    virtual     size_t      frameCount(int output) const;
+    virtual     uint32_t    latency(int output) const;
 
     virtual     status_t    setMasterVolume(float value);
     virtual     status_t    setMasterMute(bool muted);
@@ -108,6 +104,8 @@ public:
 
     virtual     bool        isMusicActive() const;
 
+    virtual     bool        isA2dpEnabled() const;
+
     virtual     status_t    setParameter(const char* key, const char* value);
 
     virtual     void        registerClient(const sp<IAudioFlingerClient>& client);
@@ -159,23 +157,26 @@ private:
                             AudioFlinger();
     virtual                 ~AudioFlinger();
     
-    void                    setOutput(AudioStreamOut* output);
-    void                    doSetOutput(AudioStreamOut* output);
-    size_t                  getOutputFrameCount(AudioStreamOut* output);
+    void                    setOutput(int outputType);
+    void                    doSetOutput(int outputType);
 
 #ifdef WITH_A2DP
-    static bool             streamDisablesA2dp(int streamType);
-    inline bool             isA2dpEnabled() const {
-                                return (mRequestedOutput == mA2dpOutput ||
-                                        (mOutput && mOutput == mA2dpOutput));
-                            }
     void                    setA2dpEnabled(bool enable);
 #endif
+    static bool             streamForcedToSpeaker(int streamType);
+    
+    // Management of forced route to speaker for certain track types.
+    enum force_speaker_command {
+        ACTIVE_TRACK_ADDED = 0,
+        ACTIVE_TRACK_REMOVED,
+        CHECK_ROUTE_RESTORE_TIME,
+        FORCE_ROUTE_RESTORE
+    };
+    void                    handleForcedSpeakerRoute(int command);
 
     // Internal dump utilites.
     status_t dumpPermissionDenial(int fd, const Vector<String16>& args);
     status_t dumpClients(int fd, const Vector<String16>& args);
-    status_t dumpTracks(int fd, const Vector<String16>& args);
     status_t dumpInternals(int fd, const Vector<String16>& args);
 
     // --- Client ---
@@ -194,168 +195,348 @@ private:
     };
 
 
-    // --- Track ---
     class TrackHandle;
     class RecordHandle;
     class AudioRecordThread;
 
-    // base for record and playback
-    class TrackBase : public AudioBufferProvider, public RefBase {
-
+    
+    // --- MixerThread ---
+    class MixerThread : public Thread {
     public:
-        enum track_state {
-            IDLE,
-            TERMINATED,
-            STOPPED,
-            RESUMING,
-            ACTIVE,
-            PAUSING,
-            PAUSED
+        
+        // --- Track ---
+
+        // base for record and playback
+        class TrackBase : public AudioBufferProvider, public RefBase {
+
+        public:
+            enum track_state {
+                IDLE,
+                TERMINATED,
+                STOPPED,
+                RESUMING,
+                ACTIVE,
+                PAUSING,
+                PAUSED
+            };
+
+            enum track_flags {
+                STEPSERVER_FAILED = 0x01   //  StepServer could not acquire cblk->lock mutex
+            };
+
+                                TrackBase(  const sp<MixerThread>& mixerThread,
+                                        const sp<Client>& client,
+                                        int streamType,
+                                        uint32_t sampleRate,
+                                        int format,
+                                        int channelCount,
+                                        int frameCount,
+                                        const sp<IMemory>& sharedBuffer);
+                                ~TrackBase();
+
+            virtual status_t    start() = 0;
+            virtual void        stop() = 0;
+                    sp<IMemory> getCblk() const;
+
+        protected:
+            friend class MixerThread;
+            friend class RecordHandle;
+            friend class AudioRecordThread;
+
+                                TrackBase(const TrackBase&);
+                                TrackBase& operator = (const TrackBase&);
+
+            virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) = 0;
+            virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
+
+            audio_track_cblk_t* cblk() const {
+                return mCblk;
+            }
+
+            int type() const {
+                return mStreamType;
+            }
+
+            int format() const {
+                return mFormat;
+            }
+
+            int channelCount() const ;
+
+            int sampleRate() const;
+
+            void* getBuffer(uint32_t offset, uint32_t frames) const;
+
+            int name() const {
+                return mName;
+            }
+
+            bool isStopped() const {
+                return mState == STOPPED;
+            }
+
+            bool isTerminated() const {
+                return mState == TERMINATED;
+            }
+
+            bool step();
+            void reset();
+
+            sp<MixerThread>     mMixerThread;
+            sp<Client>          mClient;
+            sp<IMemory>         mCblkMemory;
+            audio_track_cblk_t* mCblk;
+            int                 mStreamType;
+            void*               mBuffer;
+            void*               mBufferEnd;
+            uint32_t            mFrameCount;
+            int                 mName;
+            // we don't really need a lock for these
+            int                 mState;
+            int                 mClientTid;
+            uint8_t             mFormat;
+            uint8_t             mFlags;
         };
 
-        enum track_flags {
-            STEPSERVER_FAILED = 0x01   //  StepServer could not acquire cblk->lock mutex
+        // playback track
+        class Track : public TrackBase {
+        public:
+                                Track(  const sp<MixerThread>& mixerThread,
+                                        const sp<Client>& client,
+                                        int streamType,
+                                        uint32_t sampleRate,
+                                        int format,
+                                        int channelCount,
+                                        int frameCount,
+                                        const sp<IMemory>& sharedBuffer);
+                                ~Track();
+
+                    void        dump(char* buffer, size_t size);
+            virtual status_t    start();
+            virtual void        stop();
+                    void        pause();
+
+                    void        flush();
+                    void        destroy();
+                    void        mute(bool);
+                    void        setVolume(float left, float right);
+
+        protected:
+            friend class MixerThread;
+            friend class AudioFlinger;
+            friend class AudioFlinger::TrackHandle;
+
+                                Track(const Track&);
+                                Track& operator = (const Track&);
+
+            virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
+
+            bool isMuted() const {
+                return (mMute || mMixerThread->mStreamTypes[mStreamType].mute);
+            }
+
+            bool isPausing() const {
+                return mState == PAUSING;
+            }
+
+            bool isPaused() const {
+                return mState == PAUSED;
+            }
+
+            bool isReady() const;
+
+            void setPaused() { mState = PAUSED; }
+            void reset();
+
+            // we don't really need a lock for these
+            float               mVolume[2];
+            volatile bool       mMute;
+            // FILLED state is used for suppressing volume ramp at begin of playing
+            enum {FS_FILLING, FS_FILLED, FS_ACTIVE};
+            mutable uint8_t     mFillingUpStatus;
+            int8_t              mRetryCount;
+            sp<IMemory>         mSharedBuffer;
+            bool                mResetDone;
+        };  // end of Track
+
+        // record track
+        class RecordTrack : public TrackBase {
+        public:
+                                RecordTrack(  const sp<MixerThread>& mixerThread,
+                                        const sp<Client>& client,
+                                        int streamType,
+                                        uint32_t sampleRate,
+                                        int format,
+                                        int channelCount,
+                                        int frameCount);
+                                ~RecordTrack();
+
+            virtual status_t    start();
+            virtual void        stop();
+
+                    bool        overflow() { bool tmp = mOverflow; mOverflow = false; return tmp; }
+                    bool        setOverflow() { bool tmp = mOverflow; mOverflow = true; return tmp; }
+
+        private:
+            friend class AudioFlinger;
+            friend class AudioFlinger::RecordHandle;
+            friend class AudioFlinger::AudioRecordThread;
+            friend class MixerThread;
+
+                                RecordTrack(const Track&);
+                                RecordTrack& operator = (const Track&);
+
+            virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
+
+            bool                mOverflow;
         };
 
-                            TrackBase(  const sp<AudioFlinger>& audioFlinger,
-                                    const sp<Client>& client,
-                                    int streamType,
-                                    uint32_t sampleRate,
-                                    int format,
-                                    int channelCount,
-                                    int frameCount,
-                                    const sp<IMemory>& sharedBuffer);
-                            ~TrackBase();
-
-        virtual status_t    start() = 0;
-        virtual void        stop() = 0;
-                sp<IMemory> getCblk() const;
-
-    protected:
-        friend class AudioFlinger;
-        friend class RecordHandle;
-        friend class AudioRecordThread;
-
-                            TrackBase(const TrackBase&);
-                            TrackBase& operator = (const TrackBase&);
-
-        virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) = 0;
-        virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
-
-        audio_track_cblk_t* cblk() const {
-            return mCblk;
-        }
-
-        int type() const {
-            return mStreamType;
-        }
-
-        int format() const {
-            return mFormat;
-        }
-
-        int channelCount() const ;
-
-        int sampleRate() const;
-
-        void* getBuffer(uint32_t offset, uint32_t frames) const;
-
-        int name() const {
-            return mName;
-        }
-
-        bool isStopped() const {
-            return mState == STOPPED;
-        }
-
-        bool isTerminated() const {
-            return mState == TERMINATED;
-        }
-
-        bool step();
-        void reset();
-
-        sp<AudioFlinger>    mAudioFlinger;
-        sp<Client>          mClient;
-        sp<IMemory>         mCblkMemory;
-        audio_track_cblk_t* mCblk;
-        int                 mStreamType;
-        void*               mBuffer;
-        void*               mBufferEnd;
-        uint32_t            mFrameCount;
-        int                 mName;
-        // we don't really need a lock for these
-        int                 mState;
-        int                 mClientTid;
-        uint8_t             mFormat;
-        uint8_t             mFlags;
-    };
-
-    // playback track
-    class Track : public TrackBase {
-    public:
-                            Track(  const sp<AudioFlinger>& audioFlinger,
-                                    const sp<Client>& client,
+        // playback track
+        class OutputTrack : public Track {
+        public:
+            
+            class Buffer: public AudioBufferProvider::Buffer {
+            public:
+                int16_t *mBuffer;
+            };
+            
+                                OutputTrack(  const sp<MixerThread>& mixerThread,
+                                        uint32_t sampleRate,
+                                        int format,
+                                        int channelCount,
+                                        int frameCount);
+                                ~OutputTrack();
+
+            virtual status_t    start();
+            virtual void        stop();
+                    void        write(int16_t* data, uint32_t frames);
+                    bool        bufferQueueEmpty() { return (mBufferQueue.size() == 0) ? true : false; }
+
+        private:
+
+            status_t            obtainBuffer(AudioBufferProvider::Buffer* buffer);
+            void                clearBufferQueue();
+            
+            sp<MixerThread>             mOutputMixerThread;
+            Vector < Buffer* >          mBufferQueue;
+            AudioBufferProvider::Buffer mOutBuffer;
+            uint32_t                    mFramesWritten;
+            
+         };  // end of OutputTrack
+
+        MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int outputType);
+        virtual             ~MixerThread();
+
+        virtual     status_t    dump(int fd, const Vector<String16>& args);
+
+        // Thread virtuals
+        virtual     bool        threadLoop();
+        virtual     status_t    readyToRun();
+        virtual     void        onFirstRef();
+
+        virtual     uint32_t    sampleRate() const;
+        virtual     int         channelCount() const;
+        virtual     int         format() const;
+        virtual     size_t      frameCount() const;
+        virtual     uint32_t    latency() const;
+
+        virtual     status_t    setMasterVolume(float value);
+        virtual     status_t    setMasterMute(bool muted);
+
+        virtual     float       masterVolume() const;
+        virtual     bool        masterMute() const;
+
+        virtual     status_t    setStreamVolume(int stream, float value);
+        virtual     status_t    setStreamMute(int stream, bool muted);
+
+        virtual     float       streamVolume(int stream) const;
+        virtual     bool        streamMute(int stream) const;
+
+                    bool        isMusicActive() const;
+        
+                    
+        sp<Track> createTrack(
+                                    const sp<AudioFlinger::Client>& client,
                                     int streamType,
                                     uint32_t sampleRate,
                                     int format,
                                     int channelCount,
                                     int frameCount,
-                                    const sp<IMemory>& sharedBuffer);
-                            ~Track();
-
-                void        dump(char* buffer, size_t size);
-        virtual status_t    start();
-        virtual void        stop();
-                void        pause();
-
-                void        flush();
-                void        destroy();
-                void        mute(bool);
-                void        setVolume(float left, float right);
+                                    const sp<IMemory>& sharedBuffer,
+                                    status_t *status);
+
+                    void        wakeUp() { mWaitWorkCV.broadcast(); }
+                    
+                    void        getTracks(SortedVector < sp<Track> >& tracks,
+                                          SortedVector < wp<Track> >& activeTracks);
+                    void        putTracks(SortedVector < sp<Track> >& tracks,
+                                          SortedVector < wp<Track> >& activeTracks);
+                    void        setOuputTrack(OutputTrack *track) { mOutputTrack = track; }
+                    
+        struct  stream_type_t {
+            stream_type_t()
+                :   volume(1.0f),
+                    mute(false)
+            {
+            }
+            float       volume;
+            bool        mute;
+        };
 
     private:
-        friend class AudioFlinger;
-        friend class TrackHandle;
-
-                            Track(const Track&);
-                            Track& operator = (const Track&);
-
-        virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
-
-        bool isMuted() const {
-            return (mMute || mAudioFlinger->mStreamTypes[mStreamType].mute);
-        }
-
-        bool isPausing() const {
-            return mState == PAUSING;
-        }
-
-        bool isPaused() const {
-            return mState == PAUSED;
-        }
-
-        bool isReady() const;
 
-        void setPaused() { mState = PAUSED; }
-        void reset();
 
-        // we don't really need a lock for these
-        float               mVolume[2];
-        volatile bool       mMute;
-        // FILLED state is used for suppressing volume ramp at begin of playing
-        enum {FS_FILLING, FS_FILLED, FS_ACTIVE};
-        mutable uint8_t     mFillingUpStatus;
-        int8_t              mRetryCount;
-        sp<IMemory>         mSharedBuffer;
-        bool                mResetDone;
-    };  // end of Track
+        friend class AudioFlinger;
+        friend class Track;
+        friend class TrackBase;
+        friend class RecordTrack;
+        
+        MixerThread(const Client&);
+        MixerThread& operator = (const MixerThread&);
+  
+        status_t    addTrack(const sp<Track>& track);
+        void        removeTrack(wp<Track> track, int name);
+        void        remove_track_l(wp<Track> track, int name);
+        void        destroyTrack(const sp<Track>& track);
+        int         getTrackName();
+        void        deleteTrackName(int name);
+        void        addActiveTrack(const wp<Track>& t);
+        void        removeActiveTrack(const wp<Track>& t);
+        size_t      getOutputFrameCount();
+
+        status_t    dumpInternals(int fd, const Vector<String16>& args);
+        status_t    dumpTracks(int fd, const Vector<String16>& args);
+        
+        sp<AudioFlinger>                mAudioFlinger;       
+        mutable     Mutex               mLock;
+        mutable     Condition           mWaitWorkCV;
+        SortedVector< wp<Track> >       mActiveTracks;
+        SortedVector< sp<Track> >       mTracks;
+        stream_type_t                   mStreamTypes[AudioSystem::NUM_STREAM_TYPES];
+        AudioMixer*                     mAudioMixer;
+        AudioStreamOut*                 mOutput;
+        int                             mOutputType;
+        uint32_t                        mSampleRate;
+        size_t                          mFrameCount;
+        int                             mChannelCount;
+        int                             mFormat;
+        int16_t*                        mMixBuffer;
+        float                           mMasterVolume;
+        bool                            mMasterMute;
+        nsecs_t                         mLastWriteTime;
+        int                             mNumWrites;
+        int                             mNumDelayedWrites;
+        bool                            mStandby;
+        bool                            mInWrite;
+        sp <OutputTrack>                mOutputTrack;
+    };
 
+    
     friend class AudioBuffer;
 
     class TrackHandle : public android::BnAudioTrack {
     public:
-                            TrackHandle(const sp<Track>& track);
+                            TrackHandle(const sp<MixerThread::Track>& track);
         virtual             ~TrackHandle();
         virtual status_t    start();
         virtual void        stop();
@@ -367,72 +548,20 @@ private:
         virtual status_t onTransact(
             uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
     private:
-        sp<Track> mTrack;
-    };
-
-    struct  stream_type_t {
-        stream_type_t()
-            :   volume(1.0f),
-                mute(false)
-        {
-        }
-        float       volume;
-        bool        mute;
+        sp<MixerThread::Track> mTrack;
     };
 
     friend class Client;
-    friend class Track;
+    friend class MixerThread::Track;
 
 
                 void        removeClient(pid_t pid);
 
-                status_t    addTrack(const sp<Track>& track);
-                void        removeTrack(wp<Track> track, int name);
-                void        remove_track_l(wp<Track> track, int name);
-                void        destroyTrack(const sp<Track>& track);
-                void        addActiveTrack(const wp<Track>& track);
-                void        removeActiveTrack(const wp<Track>& track);
-                int         getTrackName();
-                void        deleteTrackName(int name);
-
-                AudioMixer* audioMixer() {
-                    return mAudioMixer;
-                }
-
-    // record track
-    class RecordTrack : public TrackBase {
-    public:
-                            RecordTrack(  const sp<AudioFlinger>& audioFlinger,
-                                    const sp<Client>& client,
-                                    int streamType,
-                                    uint32_t sampleRate,
-                                    int format,
-                                    int channelCount,
-                                    int frameCount);
-                            ~RecordTrack();
-
-        virtual status_t    start();
-        virtual void        stop();
-
-                bool        overflow() { bool tmp = mOverflow; mOverflow = false; return tmp; }
-                bool        setOverflow() { bool tmp = mOverflow; mOverflow = true; return tmp; }
-
-    private:
-        friend class AudioFlinger;
-        friend class RecordHandle;
-        friend class AudioRecordThread;
-
-                            RecordTrack(const Track&);
-                            RecordTrack& operator = (const Track&);
 
-        virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
-
-        bool                mOverflow;
-    };
 
     class RecordHandle : public android::BnAudioRecord {
     public:
-        RecordHandle(const sp<RecordTrack>& recordTrack);
+        RecordHandle(const sp<MixerThread::RecordTrack>& recordTrack);
         virtual             ~RecordHandle();
         virtual status_t    start();
         virtual void        stop();
@@ -440,7 +569,7 @@ private:
         virtual status_t onTransact(
             uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
     private:
-        sp<RecordTrack> mRecordTrack;
+        sp<MixerThread::RecordTrack> mRecordTrack;
     };
 
     // record thread
@@ -453,14 +582,14 @@ private:
         virtual status_t    readyToRun() { return NO_ERROR; }
         virtual void        onFirstRef() {}
 
-                status_t    start(RecordTrack* recordTrack);
-                void        stop(RecordTrack* recordTrack);
+                status_t    start(MixerThread::RecordTrack* recordTrack);
+                void        stop(MixerThread::RecordTrack* recordTrack);
                 void        exit();
 
     private:
                 AudioRecordThread();
                 AudioHardwareInterface              *mAudioHardware;
-                sp<RecordTrack>                     mRecordTrack;
+                sp<MixerThread::RecordTrack>        mRecordTrack;
                 Mutex                               mLock;
                 Condition                           mWaitWorkCV;
                 volatile bool                       mActive;
@@ -468,48 +597,31 @@ private:
     };
 
     friend class AudioRecordThread;
+    friend class MixerThread;
 
-                status_t    startRecord(RecordTrack* recordTrack);
-                void        stopRecord(RecordTrack* recordTrack);
-
-                void notifyOutputChange_l();
+                status_t    startRecord(MixerThread::RecordTrack* recordTrack);
+                void        stopRecord(MixerThread::RecordTrack* recordTrack);
+                
+                void        handleOutputSwitch();
 
     mutable     Mutex                                       mHardwareLock;
     mutable     Mutex                                       mLock;
-    mutable     Condition                                   mWaitWorkCV;
                 DefaultKeyedVector< pid_t, wp<Client> >     mClients;
-                SortedVector< wp<Track> >                   mActiveTracks;
-                SortedVector< sp<Track> >                   mTracks;
-                float                               mMasterVolume;
-                uint32_t                            mMasterRouting;
-                bool                                mMasterMute;
-                stream_type_t                       mStreamTypes[AudioTrack::NUM_STREAM_TYPES];
-
-                AudioMixer*                         mHardwareAudioMixer;
-                AudioMixer*                         mA2dpAudioMixer;
-                AudioMixer*                         mAudioMixer;
+
+                sp<MixerThread>                     mA2dpMixerThread;
+                sp<MixerThread>                     mHardwareMixerThread;
                 AudioHardwareInterface*             mAudioHardware;
                 AudioHardwareInterface*             mA2dpAudioInterface;
-                AudioStreamOut*                     mHardwareOutput;
-                AudioStreamOut*                     mA2dpOutput;
-                AudioStreamOut*                     mOutput;
-                AudioStreamOut*                     mRequestedOutput;
                 sp<AudioRecordThread>               mAudioRecordThread;
-                uint32_t                            mSampleRate;
-                size_t                              mFrameCount;
-                int                                 mChannelCount;
-                int                                 mFormat;
-                int16_t*                            mMixBuffer;
+                bool                                mA2dpEnabled;
+                bool                                mA2dpEnabledReq;
     mutable     int                                 mHardwareStatus;
-                nsecs_t                             mLastWriteTime;
-                int                                 mNumWrites;
-                int                                 mNumDelayedWrites;
-                bool                                mStandby;
-                bool                                mInWrite;
-                int                                 mA2dpDisableCount;
-                bool                                mA2dpSuppressed;
-                bool                                mMusicMuteSaved;
                 SortedVector< wp<IBinder> >         mNotificationClients;
+                int                                 mForcedSpeakerCount;
+                uint32_t                            mSavedRoute;
+                uint32_t                            mForcedRoute;
+                nsecs_t                             mRouteRestoreTime;
+                bool                                mMusicMuteSaved;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk
index 53ba3bc6e4e0..496e2717fb4a 100644
--- a/libs/surfaceflinger/Android.mk
+++ b/libs/surfaceflinger/Android.mk
@@ -16,9 +16,7 @@ LOCAL_SRC_FILES:= \
     LayerBitmap.cpp \
     LayerDim.cpp \
     LayerOrientationAnim.cpp \
-    LayerScreenshot.cpp \
     OrientationAnimation.cpp \
-    RFBServer.cpp \
     SurfaceFlinger.cpp \
     Tokenizer.cpp \
     Transform.cpp \
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 31e63ef2c6b1..f65d66984d7f 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -186,7 +186,9 @@ void Layer::onDraw(const Region& clip) const
         copybit_device_t* copybit = mFlinger->getBlitEngine();
         copybit->set_parameter(copybit, COPYBIT_TRANSFORM, getOrientation());
         copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
-        copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
+        copybit->set_parameter(copybit, COPYBIT_DITHER,
+                s.flags & ISurfaceComposer::eLayerDither ?
+                        COPYBIT_ENABLE : COPYBIT_DISABLE);
 
         region_iterator it(clip);
         err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index 9277a64daa4c..0cf53f796b6b 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -26,6 +26,8 @@
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
+#include <hardware/hardware.h>
+
 #include "clz.h"
 #include "LayerBase.h"
 #include "LayerBlur.h"
@@ -229,15 +231,10 @@ Point LayerBase::getPhysicalSize() const
     return Point(front.w, front.h);
 }
 
-Transform LayerBase::getDrawingStateTransform() const
-{
-    return drawingState().transform;
-}
-
 void LayerBase::validateVisibility(const Transform& planeTransform)
 {
     const Layer::State& s(drawingState());
-    const Transform tr(planeTransform * getDrawingStateTransform());
+    const Transform tr(planeTransform * s.transform);
     const bool transformed = tr.transformed();
    
     const Point size(getPhysicalSize());
@@ -420,7 +417,7 @@ void LayerBase::clearWithOpenGL(const Region& clip) const
 }
 
 void LayerBase::drawWithOpenGL(const Region& clip,
-        GLint textureName, const GGLSurface& t) const
+        GLint textureName, const GGLSurface& t, int transform) const
 {
     const DisplayHardware& hw(graphicPlane(0).displayHardware());
     const uint32_t fbHeight = hw.getHeight();
@@ -492,6 +489,12 @@ void LayerBase::drawWithOpenGL(const Region& clip,
 
             glMatrixMode(GL_TEXTURE);
             glLoadIdentity();
+            
+            if (transform == HAL_TRANSFORM_ROT_90) {
+                glTranslatef(0, 1, 0);
+                glRotatef(-90, 0, 0, 1);
+            }
+
             if (!(mFlags & DisplayHardware::NPOT_EXTENSION)) {
                 // find the smallest power-of-two that will accommodate our surface
                 GLuint tw = 1 << (31 - clz(t.width));
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index 2377a148650e..a020f44e8746 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -168,13 +168,6 @@ public:
      */
     virtual void validateVisibility(const Transform& globalTransform);
 
-    /**
-     * getDrawingStateTransform - returns the drawing state's transform.
-     * This is used in validateVisibility() and can be use to override or
-     * modify the transform (if so make sure to trigger a transaction).
-     */
-    virtual Transform getDrawingStateTransform() const;
-
     /**
      * lockPageFlip - called each time the screen is redrawn and returns whether
      * the visible regions need to be recomputed (this is a fairly heavy
@@ -200,10 +193,15 @@ public:
      * needsBlending - true if this surface needs blending
      */
     virtual bool needsBlending() const  { return false; }
-    
+
+    /**
+     * transformed -- true is this surface needs a to be transformed
+     */
+    virtual bool transformed() const    { return mTransformed; }
+
     /**
-     * isSecure - true if this surface is secure, that is if it prevents a
-     * screenshot to be taken,
+     * isSecure - true if this surface is secure, that is if it prevents
+     * screenshots or vns servers.
      */
     virtual bool isSecure() const       { return false; }
 
@@ -222,7 +220,6 @@ public:
     }
 
     int32_t  getOrientation() const { return mOrientation; }
-    bool transformed() const    { return mTransformed; }
     int  tx() const             { return mLeft; }
     int  ty() const             { return mTop; }
     
@@ -233,7 +230,9 @@ protected:
           GLuint createTexture() const;
     
           void drawWithOpenGL(const Region& clip,
-                  GLint textureName, const GGLSurface& surface) const;
+                  GLint textureName,
+                  const GGLSurface& surface,
+                  int transform = 0) const;
 
           void clearWithOpenGL(const Region& clip) const;
 
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index fc0a603f7f50..00fab70d491d 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -103,15 +103,6 @@ void LayerBuffer::unregisterBuffers()
         source->unregisterBuffers();
 }
 
-Transform LayerBuffer::getDrawingStateTransform() const
-{
-    Transform tr(LayerBaseClient::getDrawingStateTransform());
-    sp<Source> source(getSource());
-    if (source != 0)
-        source->updateTransform(&tr);
-    return tr;
-}
-
 uint32_t LayerBuffer::doTransaction(uint32_t flags)
 {
     sp<Source> source(getSource());
@@ -141,6 +132,14 @@ void LayerBuffer::onDraw(const Region& clip) const
     }
 }
 
+bool LayerBuffer::transformed() const
+{
+    sp<Source> source(getSource());
+    if (LIKELY(source != 0))
+        return source->transformed();
+    return false;
+}
+
 /**
  * This creates a "buffer" source for this surface
  */
@@ -316,7 +315,8 @@ void LayerBuffer::Source::postBuffer(ssize_t offset) {
 }
 void LayerBuffer::Source::unregisterBuffers() {
 }
-void LayerBuffer::Source::updateTransform(Transform* tr) const {
+bool LayerBuffer::Source::transformed() const {
+    return mLayer.mTransformed; 
 }
 
 // ---------------------------------------------------------------------------
@@ -363,6 +363,7 @@ LayerBuffer::BufferSource::BufferSource(LayerBuffer& layer,
     mLayer.setNeedsBlending((info.h_alpha - info.l_alpha) > 0);    
     mBufferSize = info.getScanlineSize(buffers.hor_stride)*buffers.ver_stride;
     mLayer.forceVisibilityTransaction();
+    
 }
 
 LayerBuffer::BufferSource::~BufferSource()
@@ -419,15 +420,9 @@ void LayerBuffer::BufferSource::setBuffer(const sp<LayerBuffer::Buffer>& buffer)
     mBuffer = buffer;
 }
 
-void LayerBuffer::BufferSource::updateTransform(Transform* tr) const
+bool LayerBuffer::BufferSource::transformed() const
 {
-    uint32_t bufTransform = mBufferHeap.transform;
-    // TODO: handle all transforms
-    if (bufTransform == ISurface::BufferHeap::ROT_90) {
-        Transform rot90;
-        rot90.set(0, -1, 1, 0);
-        *tr = (*tr) * rot90;
-    }
+    return mBufferHeap.transform ? true : Source::transformed(); 
 }
 
 void LayerBuffer::BufferSource::onDraw(const Region& clip) const 
@@ -476,7 +471,7 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const
             if (UNLIKELY(mTemporaryDealer == 0)) {
                 // allocate a memory-dealer for this the first time
                 mTemporaryDealer = mLayer.mFlinger->getSurfaceHeapManager()
-                ->createHeap(ISurfaceComposer::eHardware);
+                    ->createHeap(ISurfaceComposer::eHardware);
                 mTempBitmap.init(mTemporaryDealer);
             }
 
@@ -506,10 +501,23 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const
         copybit_image_t dst;
         hw.getDisplaySurface(&dst);
         const copybit_rect_t& drect
-        = reinterpret_cast<const copybit_rect_t&>(transformedBounds);
+            = reinterpret_cast<const copybit_rect_t&>(transformedBounds);
         const State& s(mLayer.drawingState());
         region_iterator it(clip);
-        copybit->set_parameter(copybit, COPYBIT_TRANSFORM, mLayer.getOrientation());
+        
+        // pick the right orientation for this buffer
+        int orientation = mLayer.getOrientation();
+        if (UNLIKELY(mBufferHeap.transform)) {
+            Transform rot90;
+            GraphicPlane::orientationToTransfrom(
+                    ISurfaceComposer::eOrientation90, 0, 0, &rot90);
+            const Transform& planeTransform(mLayer.graphicPlane(0).transform());
+            const Layer::State& s(mLayer.drawingState());
+            Transform tr(planeTransform * s.transform * rot90);
+            orientation = tr.getOrientation();
+        }
+        
+        copybit->set_parameter(copybit, COPYBIT_TRANSFORM, orientation);
         copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, s.alpha);
         copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
 
@@ -536,10 +544,11 @@ void LayerBuffer::BufferSource::onDraw(const Region& clip) const
         t.data = (GGLubyte*)(intptr_t(src.img.base) + src.img.offset);
         const Region dirty(Rect(t.width, t.height));
         mLayer.loadTexture(dirty, mTextureName, t, w, h);
-        mLayer.drawWithOpenGL(clip, mTextureName, t);
+        mLayer.drawWithOpenGL(clip, mTextureName, t, mBufferHeap.transform);
     }
 }
 
+
 // ---------------------------------------------------------------------------
 
 LayerBuffer::OverlaySource::OverlaySource(LayerBuffer& layer,
diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h
index 5532532f044f..2dc77f1501e9 100644
--- a/libs/surfaceflinger/LayerBuffer.h
+++ b/libs/surfaceflinger/LayerBuffer.h
@@ -46,7 +46,7 @@ class LayerBuffer : public LayerBaseClient
         virtual void onVisibilityResolved(const Transform& planeTransform);
         virtual void postBuffer(ssize_t offset);
         virtual void unregisterBuffers();
-        virtual void updateTransform(Transform* tr) const;
+        virtual bool transformed() const;
     protected:
         LayerBuffer& mLayer;
     };
@@ -68,7 +68,7 @@ public:
     virtual void onDraw(const Region& clip) const;
     virtual uint32_t doTransaction(uint32_t flags);
     virtual void unlockPageFlip(const Transform& planeTransform, Region& outDirtyRegion);
-    virtual Transform getDrawingStateTransform() const;
+    virtual bool transformed() const;
 
     status_t registerBuffers(const ISurface::BufferHeap& buffers);
     void postBuffer(ssize_t offset);
@@ -116,10 +116,10 @@ private:
         sp<Buffer> getBuffer() const;
         void setBuffer(const sp<Buffer>& buffer);
 
-        virtual void updateTransform(Transform* tr) const; 
         virtual void onDraw(const Region& clip) const;
         virtual void postBuffer(ssize_t offset);
         virtual void unregisterBuffers();
+        virtual bool transformed() const;
     private:
         mutable Mutex   mLock;
         sp<Buffer>      mBuffer;
diff --git a/libs/surfaceflinger/LayerOrientationAnim.cpp b/libs/surfaceflinger/LayerOrientationAnim.cpp
index 46b3b196c72e..2b72d7ce9487 100644
--- a/libs/surfaceflinger/LayerOrientationAnim.cpp
+++ b/libs/surfaceflinger/LayerOrientationAnim.cpp
@@ -84,7 +84,7 @@ Point LayerOrientationAnim::getPhysicalSize() const
 void LayerOrientationAnim::validateVisibility(const Transform&)
 {
     const Layer::State& s(drawingState());
-    const Transform tr(getDrawingStateTransform());
+    const Transform tr(s.transform);
     const Point size(getPhysicalSize());
     uint32_t w = size.x;
     uint32_t h = size.y;
diff --git a/libs/surfaceflinger/LayerScreenshot.cpp b/libs/surfaceflinger/LayerScreenshot.cpp
deleted file mode 100644
index 40c47b0b7d87..000000000000
--- a/libs/surfaceflinger/LayerScreenshot.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "SurfaceFlinger"
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/Log.h>
-
-#include <core/SkBitmap.h>
-
-#include <ui/EGLDisplaySurface.h>
-
-#include "LayerBase.h"
-#include "LayerScreenshot.h"
-#include "SurfaceFlinger.h"
-#include "DisplayHardware/DisplayHardware.h"
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-const uint32_t LayerScreenshot::typeInfo = LayerBase::typeInfo | 0x40;
-const char* const LayerScreenshot::typeID = "LayerScreenshot";
-
-// ---------------------------------------------------------------------------
-
-LayerScreenshot::LayerScreenshot(SurfaceFlinger* flinger, DisplayID display)
-    : LayerBase(flinger, display), mReply(0)
-{
-}
-
-LayerScreenshot::~LayerScreenshot()
-{
-}
-
-void LayerScreenshot::onDraw(const Region& clip) const
-{
-    const DisplayHardware& hw(graphicPlane(0).displayHardware());
-    copybit_image_t dst;
-    hw.getDisplaySurface(&dst);
-    if (dst.base != 0) {
-        uint8_t const* src = (uint8_t const*)(intptr_t(dst.base) + dst.offset); 
-        const int fbWidth = dst.w;
-        const int fbHeight = dst.h;
-        const int fbFormat = dst.format;
-
-        int x = mTransformedBounds.left;
-        int y = mTransformedBounds.top;
-        int w = mTransformedBounds.width();
-        int h = mTransformedBounds.height();
-        Parcel* const reply = mReply;
-        if (reply) {
-            const size_t Bpp = bytesPerPixel(fbFormat);
-            const size_t size = w * h * Bpp;
-            int32_t cfg = SkBitmap::kNo_Config;
-            switch (fbFormat) {
-                case PIXEL_FORMAT_RGBA_4444: cfg = SkBitmap::kARGB_4444_Config;
-                case PIXEL_FORMAT_RGBA_8888: cfg = SkBitmap::kARGB_8888_Config;
-                case PIXEL_FORMAT_RGB_565:   cfg = SkBitmap::kRGB_565_Config;
-                case PIXEL_FORMAT_A_8:       cfg = SkBitmap::kA8_Config;
-            }
-            reply->writeInt32(0);
-            reply->writeInt32(cfg);
-            reply->writeInt32(w);
-            reply->writeInt32(h);
-            reply->writeInt32(w * Bpp);
-            void* data = reply->writeInplace(size);
-            if (data) {
-                uint8_t* d = (uint8_t*)data;
-                uint8_t const* s = src + (x + y*fbWidth) * Bpp;
-                if (w == fbWidth) {
-                    memcpy(d, s, w*h*Bpp);   
-                } else {
-                    for (int y=0 ; y<h ; y++) {
-                        memcpy(d, s, w*Bpp);
-                        d += w*Bpp;
-                        s += fbWidth*Bpp;
-                    }
-                }
-            }
-        }
-    }
-    mCV.broadcast();
-}
-
-void LayerScreenshot::takeScreenshot(Mutex& lock, Parcel* reply)
-{
-    mReply = reply;
-    mCV.wait(lock);
-}
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
diff --git a/libs/surfaceflinger/LayerScreenshot.h b/libs/surfaceflinger/LayerScreenshot.h
deleted file mode 100644
index 2d9a8ec6d7af..000000000000
--- a/libs/surfaceflinger/LayerScreenshot.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_LAYER_SCREENSHOT_H
-#define ANDROID_LAYER_SCREENSHOT_H
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <utils/threads.h>
-#include <utils/Parcel.h>
-
-#include "LayerBase.h"
-
-namespace android {
-
-// ---------------------------------------------------------------------------
-
-class LayerScreenshot : public LayerBase
-{
-public:    
-    static const uint32_t typeInfo;
-    static const char* const typeID;
-    virtual char const* getTypeID() const { return typeID; }
-    virtual uint32_t getTypeInfo() const { return typeInfo; }
-    
-                LayerScreenshot(SurfaceFlinger* flinger, DisplayID display);
-        virtual ~LayerScreenshot();
-
-    virtual void onDraw(const Region& clip) const;
-    virtual bool needsBlending() const  { return true; }
-    virtual bool isSecure() const       { return false; }
-
-    void takeScreenshot(Mutex& lock, Parcel* reply);
-    
-private:
-    mutable Condition   mCV;
-    Parcel*             mReply;
-};
-
-// ---------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_LAYER_SCREENSHOT_H
diff --git a/libs/surfaceflinger/RFBServer.cpp b/libs/surfaceflinger/RFBServer.cpp
deleted file mode 100644
index c2c198941388..000000000000
--- a/libs/surfaceflinger/RFBServer.cpp
+++ /dev/null
@@ -1,722 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "RFBServer"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <errno.h>
-#include <fcntl.h>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-
-#include <netinet/in.h>
-
-#include <cutils/sockets.h>
-
-#include <utils/Log.h>
-#include <ui/Rect.h>
-
-#ifdef HAVE_ANDROID_OS
-#include <linux/input.h>
-#endif
-
-#include "RFBServer.h"
-#include "SurfaceFlinger.h"
-
-/* BUG=773511: this is a temporary hack required while developing the new
-   set of "clean kernel headers" for the Bionic C library. */
-#ifndef KEY_STAR
-#define KEY_STAR    227
-#endif
-#ifndef KEY_SHARP
-#define KEY_SHARP   228
-#endif
-#ifndef KEY_SOFT1
-#define KEY_SOFT1   229
-#endif
-#ifndef KEY_SOFT2
-#define KEY_SOFT2   230
-#endif
-#ifndef KEY_CENTER
-#define KEY_CENTER  232
-#endif
-
-// ----------------------------------------------------------------------------
-
-#define DEBUG_MSG   0
-
-// ----------------------------------------------------------------------------
-
-namespace android {
-
-const int VNC_PORT = 5900;
-
-RFBServer::RFBServer(uint32_t w, uint32_t h, android::PixelFormat format)
-    : Thread(false), mFD(-1), mStatus(NO_INIT), mIoVec(0)
-{
-    mFrameBuffer.version = sizeof(mFrameBuffer);
-    mFrameBuffer.width = w;
-    mFrameBuffer.height = h;
-    mFrameBuffer.stride = w;
-    mFrameBuffer.format = format;
-    mFrameBuffer.data = 0;
-}
-
-RFBServer::~RFBServer()
-{
-    if (mRobinThread != 0) {
-        // ask the thread to exit first
-        mRobinThread->exitAndWait();
-    }
-
-    free(mFrameBuffer.data);
-
-    delete [] mIoVec;
-}
-
-void RFBServer::onFirstRef()
-{
-    run("Batman");
-}
-
-status_t RFBServer::readyToRun()
-{
-    LOGI("RFB server ready to run");
-    return NO_ERROR;
-}
-
-bool RFBServer::threadLoop()
-{
-    struct sockaddr addr;
-    socklen_t alen;
-    int serverfd = -1;
-    int port = VNC_PORT;
-
-    do {
-        retry:
-        if (serverfd < 0) {
-            serverfd = socket_loopback_server(port, SOCK_STREAM);
-            if (serverfd < 0) {
-                if ((errno == EADDRINUSE) && (port < (VNC_PORT+10))) {
-                    LOGW("port %d already in use, trying %d", port, port+1);
-                    port++;
-                    goto retry;
-                }
-                LOGE("couldn't create socket, port=%d, error %d (%s)",
-                        port, errno, strerror(errno));
-                sleep(1);
-                break;
-            }
-            fcntl(serverfd, F_SETFD, FD_CLOEXEC);
-        }
-
-        alen = sizeof(addr);
-        mFD = accept(serverfd, &addr, &alen);
-
-        if (mFD < 0) {
-            LOGE("couldn't accept(), error %d (%s)", errno, strerror(errno));
-            // we could have run out of file descriptors, wait a bit and
-            // try again.
-            sleep(1);
-            goto retry;
-        }
-        fcntl(mFD, F_SETFD, FD_CLOEXEC);
-
-        // send protocol version and Authentication method
-        mStatus = NO_ERROR;
-        handshake(3, 3, Authentication::None);
-
-        if (alive()) {
-            // create the thread we use to send data to the client
-            mRobinThread = new ServerThread(this);
-        }
-
-        while( alive() ) {
-            // client message must be destroyed at each iteration
-            // (most of the time this is a no-op)
-            ClientMessage msg;
-            waitForClientMessage(msg);
-            if (alive()) {
-                handleClientMessage(msg);
-            }
-        }
-
-    } while( alive() );
-
-    // free-up some resources
-    if (mRobinThread != 0) {
-        mRobinThread->exitAndWait();
-        mRobinThread.clear();
-    }
-
-    free(mFrameBuffer.data);
-    mFrameBuffer.data = 0;
-
-    close(mFD);
-    close(serverfd);
-    mFD = -1;
-
-    // we'll try again
-    return true;
-}
-
-// ----------------------------------------------------------------------------
-
-RFBServer::ServerThread::ServerThread(const sp<RFBServer>& receiver)
-            : Thread(false), mReceiver(receiver)
-{
-    LOGD("RFB Server Thread created");
-}
-
-RFBServer::ServerThread::~ServerThread()
-{
-    LOGD("RFB Server Thread destroyed");
-}
-
-void RFBServer::ServerThread::onFirstRef()
-{
-    mUpdateBarrier.close();
-    run("Robin");
-}
-
-status_t RFBServer::ServerThread::readyToRun()
-{
-    return NO_ERROR;
-}
-
-void RFBServer::ServerThread::wake()
-{
-    mUpdateBarrier.open();
-}
-
-void RFBServer::ServerThread::exitAndWait()
-{
-    requestExit();
-    mUpdateBarrier.open();
-    requestExitAndWait();
-}
-
-bool RFBServer::ServerThread::threadLoop()
-{
-    sp<RFBServer> receiver(mReceiver.promote());
-    if (receiver == 0)
-        return false;
-
-    // wait for something to do
-    mUpdateBarrier.wait();
-
-    // we're asked to quit, abort everything
-    if (exitPending())
-        return false;
-
-    mUpdateBarrier.close();
-
-    // process updates
-    receiver->sendFrameBufferUpdates();
-    return !exitPending();
-}
-
-// ----------------------------------------------------------------------------
-
-void RFBServer::handshake(uint8_t major, uint8_t minor, uint32_t auth)
-{
-    ProtocolVersion protocolVersion(major, minor);
-    if( !write(protocolVersion) )
-        return;
-
-    if ( !read(protocolVersion) )
-        return;
-
-    int maj, min;
-    if ( protocolVersion.decode(maj, min) != NO_ERROR ) {
-        mStatus = -1;
-        return;
-    }
-
-#if DEBUG_MSG
-    LOGD("client protocol string: <%s>", (char*)protocolVersion.payload());
-    LOGD("client wants protocol version %d.%d\n", maj, min);
-#endif
-
-    Authentication authentication(auth);
-    if( !write(authentication) )
-        return;
-
-    ClientInitialization clientInit;
-    if ( !read(clientInit) )
-        return;
-
-#if DEBUG_MSG
-    LOGD("client initialization: sharedFlags = %d\n", clientInit.sharedFlags());
-#endif
-
-    ServerInitialization serverInit("Android RFB");
-    ServerInitialization::Payload& message(serverInit.message());
-        message.framebufferWidth = htons(mFrameBuffer.width);
-        message.framebufferHeight = htons(mFrameBuffer.height);
-        message.serverPixelFormat.bitsPerPixel = 16;
-        message.serverPixelFormat.depth = 16;
-        message.serverPixelFormat.bigEndianFlag = 0;
-        message.serverPixelFormat.trueColorFlag = 1;
-        message.serverPixelFormat.redMax   = htons((1<<5)-1);
-        message.serverPixelFormat.greenMax = htons((1<<6)-1);
-        message.serverPixelFormat.blueMax  = htons((1<<5)-1);
-        message.serverPixelFormat.redShift     = 11;
-        message.serverPixelFormat.greenShift   = 5;
-        message.serverPixelFormat.blueShift    = 0;
-
-    mIoVec = new iovec[mFrameBuffer.height];
-
-    write(serverInit);
-}
-
-void RFBServer::handleClientMessage(const ClientMessage& msg)
-{
-    switch(msg.type()) {
-    case SET_PIXEL_FORMAT:
-        handleSetPixelFormat(msg.messages().setPixelFormat);
-        break;
-    case SET_ENCODINGS:
-        handleSetEncodings(msg.messages().setEncodings);
-        break;
-    case FRAME_BUFFER_UPDATE_REQ:
-        handleFrameBufferUpdateReq(msg.messages().frameBufferUpdateRequest);
-        break;
-    case KEY_EVENT:
-        handleKeyEvent(msg.messages().keyEvent);
-        break;
-    }
-}
-
-void RFBServer::handleSetPixelFormat(const SetPixelFormat& msg)
-{
-    if (!validatePixelFormat(msg.pixelFormat)) {
-        LOGE("The builtin VNC server only supports the RGB 565 pixel format");
-        LOGD("requested pixel format:");
-        LOGD("bitsPerPixel:     %d", msg.pixelFormat.bitsPerPixel);
-        LOGD("depth:            %d", msg.pixelFormat.depth);
-        LOGD("bigEndianFlag:    %d", msg.pixelFormat.bigEndianFlag);
-        LOGD("trueColorFlag:    %d", msg.pixelFormat.trueColorFlag);
-        LOGD("redmax:           %d", ntohs(msg.pixelFormat.redMax));
-        LOGD("bluemax:          %d", ntohs(msg.pixelFormat.greenMax));
-        LOGD("greenmax:         %d", ntohs(msg.pixelFormat.blueMax));
-        LOGD("redshift:         %d", msg.pixelFormat.redShift);
-        LOGD("greenshift:       %d", msg.pixelFormat.greenShift);
-        LOGD("blueshift:        %d", msg.pixelFormat.blueShift);
-        mStatus = -1;
-    }
-}
-
-bool RFBServer::validatePixelFormat(const PixelFormat& pf)
-{
-    if ((pf.bitsPerPixel != 16) || (pf.depth != 16))
-        return false;
-
-    if (pf.bigEndianFlag || !pf.trueColorFlag)
-        return false;
-
-    if (ntohs(pf.redMax)!=0x1F ||
-        ntohs(pf.greenMax)!=0x3F ||
-        ntohs(pf.blueMax)!=0x1F) {
-        return false;
-    }
-
-    if (pf.redShift!=11 || pf.greenShift!=5 || pf.blueShift!=0)
-        return false;
-
-    return true;
-}
-
-void RFBServer::handleSetEncodings(const SetEncodings& msg)
-{
-    /* From the RFB specification:
-        Sets the encoding types in which pixel data can be sent by the server.
-        The order of the encoding types given in this message is a hint by the
-        client as to its preference (the first encoding specified being most
-        preferred). The server may or may not choose to make use of this hint.
-        Pixel data may always be sent in raw encoding even if not specified
-        explicitly here.
-    */
-
-    LOGW("SetEncodings received. Only RAW is supported.");
-}
-
-void RFBServer::handleFrameBufferUpdateReq(const FrameBufferUpdateRequest& msg)
-{
-#if DEBUG_MSG
-    LOGD("handle FrameBufferUpdateRequest");
-#endif
-
-    Rect r;
-    r.left = ntohs(msg.x);
-    r.top = ntohs(msg.y);
-    r.right = r.left + ntohs(msg.width);
-    r.bottom = r.top + ntohs(msg.height);
-
-    Mutex::Autolock _l(mRegionLock);
-    mClientRegionRequest.set(r);
-    if (!msg.incremental)
-        mDirtyRegion.orSelf(r);
-
-    mRobinThread->wake();
-}
-
-void RFBServer::handleKeyEvent(const KeyEvent& msg)
-{
-#ifdef HAVE_ANDROID_OS
-
-    int scancode = 0;
-    int code = ntohl(msg.key);
-
-    if (code>='0' && code<='9') {
-        scancode = (code & 0xF) - 1;
-        if (scancode<0) scancode += 10;
-        scancode += KEY_1;
-    } else if (code>=0xFF50 && code<=0xFF58) {
-        static const uint16_t map[] =
-             {  KEY_HOME, KEY_LEFT, KEY_UP, KEY_RIGHT, KEY_DOWN,
-                KEY_SOFT1, KEY_SOFT2, KEY_END, 0 };
-        scancode = map[code & 0xF];
-    } else if (code>=0xFFE1 && code<=0xFFEE) {
-        static const uint16_t map[] =
-             {  KEY_LEFTSHIFT, KEY_LEFTSHIFT,
-                KEY_COMPOSE, KEY_COMPOSE,
-                KEY_LEFTSHIFT, KEY_LEFTSHIFT,
-                0,0,
-                KEY_LEFTALT, KEY_RIGHTALT,
-                0, 0, 0, 0 };
-        scancode = map[code & 0xF];
-    } else if ((code>='A' && code<='Z') || (code>='a' && code<='z')) {
-        static const uint16_t map[] = {
-                KEY_A, KEY_B, KEY_C, KEY_D, KEY_E,
-                KEY_F, KEY_G, KEY_H, KEY_I, KEY_J,
-                KEY_K, KEY_L, KEY_M, KEY_N, KEY_O,
-                KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T,
-                KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z };
-        scancode = map[(code & 0x5F) - 'A'];
-    } else {
-        switch (code) {
-            case 0x0003:    scancode = KEY_CENTER;      break;
-            case 0x0020:    scancode = KEY_SPACE;       break;
-            case 0x0023:    scancode = KEY_SHARP;       break;
-            case 0x0033:    scancode = KEY_SHARP;       break;
-            case 0x002C:    scancode = KEY_COMMA;       break;
-            case 0x003C:    scancode = KEY_COMMA;       break;
-            case 0x002E:    scancode = KEY_DOT;         break;
-            case 0x003E:    scancode = KEY_DOT;         break;
-            case 0x002F:    scancode = KEY_SLASH;       break;
-            case 0x003F:    scancode = KEY_SLASH;       break;
-            case 0x0032:    scancode = KEY_EMAIL;       break;
-            case 0x0040:    scancode = KEY_EMAIL;       break;
-            case 0xFF08:    scancode = KEY_BACKSPACE;   break;
-            case 0xFF1B:    scancode = KEY_BACK;        break;
-            case 0xFF09:    scancode = KEY_TAB;         break;
-            case 0xFF0D:    scancode = KEY_ENTER;       break;
-            case 0x002A:    scancode = KEY_STAR;        break;
-            case 0xFFBE:    scancode = KEY_SEND;        break; // F1
-            case 0xFFBF:    scancode = KEY_END;         break; // F2
-            case 0xFFC0:    scancode = KEY_HOME;        break; // F3
-            case 0xFFC5:    scancode = KEY_POWER;       break; // F8
-        }
-    }
-
-#if DEBUG_MSG
-   LOGD("handle KeyEvent 0x%08x, %d, scancode=%d\n", code, msg.downFlag, scancode);
-#endif
-
-    if (scancode) {
-        mEventInjector.injectKey(uint16_t(scancode),
-             msg.downFlag ? EventInjector::DOWN : EventInjector::UP);
-    }
-#endif
-}
-
-void RFBServer::waitForClientMessage(ClientMessage& msg)
-{
-    if ( !read(msg.payload(), 1) )
-        return;
-
-    switch(msg.type()) {
-
-    case SET_PIXEL_FORMAT:
-        read(msg.payload(1), sizeof(SetPixelFormat)-1);
-        break;
-
-    case FIX_COLOUR_MAP_ENTRIES:
-        mStatus = UNKNOWN_ERROR;
-        return;
-
-    case SET_ENCODINGS:
-    {
-        if ( !read(msg.payload(1), sizeof(SetEncodings)-1) )
-            return;
-
-        size_t size = ntohs( msg.messages().setEncodings.numberOfEncodings ) * 4;
-        if (msg.resize(sizeof(SetEncodings) + size) != NO_ERROR) {
-            mStatus = NO_MEMORY;
-            return;
-        }
-
-        if ( !read(msg.payload(sizeof(SetEncodings)), size) )
-            return;
-
-        break;
-    }
-
-    case FRAME_BUFFER_UPDATE_REQ:
-        read(msg.payload(1), sizeof(FrameBufferUpdateRequest)-1);
-        break;
-
-    case KEY_EVENT:
-        read(msg.payload(1), sizeof(KeyEvent)-1);
-        break;
-
-    case POINTER_EVENT:
-        read(msg.payload(1), sizeof(PointerEvent)-1);
-        break;
-
-    case CLIENT_CUT_TEXT:
-    {
-        if ( !read(msg.payload(1), sizeof(ClientCutText)-1) )
-            return;
-
-        size_t size = ntohl( msg.messages().clientCutText.length );
-        if (msg.resize(sizeof(ClientCutText) + size) != NO_ERROR) {
-            mStatus = NO_MEMORY;
-            return;
-        }
-
-        if ( !read(msg.payload(sizeof(SetEncodings)), size) )
-            return;
-
-        break;
-    }
-
-    default:
-        LOGE("Unknown Message %d", msg.type());
-        mStatus = UNKNOWN_ERROR;
-        return;
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-bool RFBServer::write(const Message& msg)
-{
-    write(msg.payload(), msg.size());
-    return alive();
-}
-
-bool RFBServer::read(Message& msg)
-{
-    read(msg.payload(), msg.size());
-    return alive();
-}
-
-bool RFBServer::write(const void* buffer, int size)
-{
-    int wr = ::write(mFD, buffer, size);
-    if (wr != size) {
-        //LOGE("write(%d) error %d (%s)", size, wr, strerror(errno));
-        mStatus = (wr == -1) ? errno : -1;
-    }
-    return alive();
-}
-
-bool RFBServer::read(void* buffer, int size)
-{
-    int rd = ::read(mFD, buffer, size);
-    if (rd != size) {
-        //LOGE("read(%d) error %d (%s)", size, rd, strerror(errno));
-        mStatus = (rd == -1) ? errno : -1;
-    }
-    return alive();
-}
-
-bool RFBServer::alive() const
-{
-    return  mStatus == 0;
-}
-
-bool RFBServer::isConnected() const
-{
-    return alive();
-}
-
-// ----------------------------------------------------------------------------
-
-void RFBServer::frameBufferUpdated(const GGLSurface& front, const Region& reg)
-{
-    Mutex::Autolock _l(mRegionLock);
-
-    // update dirty region
-    mDirtyRegion.orSelf(reg);
-
-    // remember the front-buffer
-    mFrontBuffer = front;
-
-    // The client has not requested anything, don't do anything more
-    if (mClientRegionRequest.isEmpty())
-        return;
-
-    // wake the sending thread up
-    mRobinThread->wake();
-}
-
-void RFBServer::sendFrameBufferUpdates()
-{
-    Vector<Rect> rects;
-    size_t countRects;
-    GGLSurface fb;
-
-    { // Scope for the lock
-        Mutex::Autolock _l(mRegionLock);
-        if (mFrontBuffer.data == 0)
-            return;
-
-        const Region reg( mDirtyRegion.intersect(mClientRegionRequest) );
-        if (reg.isEmpty())
-            return;
-
-        mDirtyRegion.subtractSelf(reg);
-        countRects = reg.rects(rects);
-
-        // copy the frame-buffer so we can stay responsive
-        size_t bytesPerPix = bytesPerPixel(mFrameBuffer.format);
-        size_t bpr = mFrameBuffer.stride * bytesPerPix;
-        if (mFrameBuffer.data == 0) {
-            mFrameBuffer.data = (GGLubyte*)malloc(bpr * mFrameBuffer.height);
-            if (mFrameBuffer.data == 0)
-            	return;
-        }
-
-        memcpy(mFrameBuffer.data, mFrontBuffer.data, bpr*mFrameBuffer.height);
-        fb = mFrameBuffer;
-    }
-
-    FrameBufferUpdate msgHeader;
-    msgHeader.type = 0;
-    msgHeader.numberOfRectangles = htons(countRects);
-    write(&msgHeader, sizeof(msgHeader));
-
-    Rectangle rectangle;
-    for (size_t i=0 ; i<countRects ; i++) {
-        const Rect& r = rects[i];
-        rectangle.x = htons( r.left );
-        rectangle.y = htons( r.top );
-        rectangle.w = htons( r.width() );
-        rectangle.h = htons( r.height() );
-        rectangle.encoding = htons( SetEncodings::Raw );
-        write(&rectangle, sizeof(rectangle));
-        size_t h = r.height();
-        size_t w = r.width();
-        size_t bytesPerPix = bytesPerPixel(fb.format);
-        size_t bpr = fb.stride * bytesPerPix;
-        size_t bytes = w * bytesPerPix;
-        size_t offset = (r.top * bpr) + (r.left * bytesPerPix);
-        uint8_t* src = static_cast<uint8_t*>(fb.data) + offset;
-        iovec* iov = mIoVec;
-        while (h--) {
-            iov->iov_base = src;
-            iov->iov_len = bytes;
-            src += bpr;
-            iov++;
-        }
-        size_t iovcnt = iov - mIoVec;
-        int wr = ::writev(mFD, mIoVec, iovcnt);
-        if (wr < 0) {
-            //LOGE("write(%d) error %d (%s)", size, wr, strerror(errno));
-            mStatus =  errno;
-        }
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-RFBServer::Message::Message(size_t size)
-    : mSize(size), mAllocatedSize(size)
-{
-    mPayload = malloc(size);
-}
-
-RFBServer::Message::Message(void* payload, size_t size)
-    : mPayload(payload), mSize(size), mAllocatedSize(0)
-{
-}
-
-RFBServer::Message::~Message()
-{
-    if (mAllocatedSize)
-        free(mPayload);
-}
-
-status_t RFBServer::Message::resize(size_t size)
-{
-    if (size > mAllocatedSize) {
-        void* newp;
-        if (mAllocatedSize) {
-            newp = realloc(mPayload, size);
-            if (!newp) return NO_MEMORY;
-        } else {
-            newp = malloc(size);
-            if (!newp) return NO_MEMORY;
-            memcpy(newp, mPayload, mSize);
-            mAllocatedSize = size;
-        }
-        mPayload = newp;
-    }
-    mSize = size;
-    return NO_ERROR;
-}
-
-// ----------------------------------------------------------------------------
-
-RFBServer::EventInjector::EventInjector()
-    : mFD(-1)
-{
-}
-
-RFBServer::EventInjector::~EventInjector()
-{
-}
-
-void RFBServer::EventInjector::injectKey(uint16_t code, uint16_t value)
-{
-#ifdef HAVE_ANDROID_OS
-    // XXX: we need to open the right event device
-    int version;
-    mFD = open("/dev/input/event0", O_RDWR);
-    ioctl(mFD, EVIOCGVERSION, &version);
-
-    input_event ev;
-    memset(&ev, 0, sizeof(ev));
-    ev.type = EV_KEY;
-    ev.code = code;
-    ev.value = value;
-    ::write(mFD, &ev, sizeof(ev));
-
-    close(mFD);
-    mFD = -1;
-#endif
-}
-
-
-}; // namespace android
-
diff --git a/libs/surfaceflinger/RFBServer.h b/libs/surfaceflinger/RFBServer.h
deleted file mode 100644
index 420912ed724d..000000000000
--- a/libs/surfaceflinger/RFBServer.h
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_RFB_SERVER_H
-#define ANDROID_RFB_SERVER_H
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <unistd.h>
-#include <arpa/inet.h>
-
-#include <utils/Errors.h>
-#include <utils/threads.h>
-#include <ui/Region.h>
-#include <ui/PixelFormat.h>
-
-#include <pixelflinger/pixelflinger.h>
-
-#include "Barrier.h"
-
-namespace android {
-
-class SurfaceFlinger;
-
-class RFBServer : public Thread
-{
-public:
-                        RFBServer(uint32_t w, uint32_t h, android::PixelFormat format);
-    virtual             ~RFBServer();
-
-    void    frameBufferUpdated(const GGLSurface& front, const Region& reg);
-    bool    isConnected() const;
-
-private:
-            typedef uint8_t     card8;
-            typedef uint16_t    card16;
-            typedef uint32_t    card32;
-
-            struct Message {
-                                Message(size_t size);
-                virtual         ~Message();
-                void*           payload(int offset=0) {
-                    return static_cast<char*>(mPayload)+offset;
-                }
-                void const *    payload(int offset=0) const {
-                    return static_cast<char const *>(mPayload)+offset;
-                }
-                size_t          size() const { return mSize; }
-            protected:
-                                Message(void* payload, size_t size);
-                status_t        resize(size_t size);
-            private:
-                void*       mPayload;
-                size_t      mSize;
-                size_t      mAllocatedSize;
-            };
-
-            struct ProtocolVersion : public Message {
-                ProtocolVersion(uint8_t major, uint8_t minor)
-                    : Message(&messageData, 12) {
-                    char* p = static_cast<char*>(payload());
-                    snprintf(p, 13, "RFB %03u.%03u%c", major, minor, 0xA);
-                }
-                status_t decode(int& maj, int& min) {
-                    char* p = static_cast<char*>(payload());
-                    int n = sscanf(p, "RFB %03u.%03u", &maj, &min);
-                    return (n == 2) ? NO_ERROR : NOT_ENOUGH_DATA;
-                }
-            private:
-                char messageData[12+1];
-            };
-            
-            struct Authentication : public Message {
-                enum { Failed=0, None=1, Vnc=2 };
-                Authentication(int auth) : Message(&messageData, 4) {
-                    *static_cast<card32*>(payload()) = htonl(auth);
-                }
-            private:
-                card32 messageData;
-            };
-            
-            struct ClientInitialization : public Message {
-                ClientInitialization() : Message(&messageData, 1) { }
-                int sharedFlags() {
-                    return messageData;
-                }
-            private:
-                card8 messageData;
-            };
-
-            struct PixelFormat {
-                card8   bitsPerPixel;
-                card8   depth;
-                card8   bigEndianFlag;
-                card8   trueColorFlag;
-                card16  redMax;
-                card16  greenMax;
-                card16  blueMax;
-                card8   redShift;
-                card8   greenShift;
-                card8   blueShift;
-                uint8_t padding[3];
-            } __attribute__((packed));
-            
-            struct ServerInitialization : public Message {
-                ServerInitialization(char const * name)
-                    : Message(sizeof(Payload) + strlen(name))
-                {
-                    const size_t nameLength = size() - sizeof(Payload);
-                    message().nameLength = htonl(nameLength); 
-                    memcpy((char*)message().nameString, name,nameLength);
-                }
-                struct Payload {
-                    card16      framebufferWidth;
-                    card16      framebufferHeight;
-                    PixelFormat serverPixelFormat;
-                    card32      nameLength;
-                    card8       nameString[0];
-                } __attribute__((packed));
-                Payload& message() {
-                    return *static_cast<Payload*>(payload());
-                }
-            };
-
-            // client messages...
-            
-            struct SetPixelFormat {
-                card8           type;
-                uint8_t         padding[3];
-                PixelFormat     pixelFormat;
-            } __attribute__((packed));
-
-            struct SetEncodings {
-                enum { Raw=0, CoR=1, RRE=2, CoRRE=4, Hextile=5 };
-                card8           type;
-                uint8_t         padding;
-                card16          numberOfEncodings;
-                card32          encodings[0];
-            } __attribute__((packed));
-
-            struct FrameBufferUpdateRequest {
-                card8           type;
-                card8           incremental;
-                card16          x;
-                card16          y;
-                card16          width;
-                card16          height;
-            } __attribute__((packed));
-            
-            struct KeyEvent {
-                card8           type;
-                card8           downFlag;
-                uint8_t         padding[2];
-                card32          key;
-            } __attribute__((packed));
-
-            struct PointerEvent {
-                card8           type;
-                card8           buttonMask;
-                card16          x;
-                card16          y;
-            } __attribute__((packed));
-
-            struct ClientCutText {
-                card8           type;
-                uint8_t         padding[3];
-                card32          length;
-                card8           text[0];
-            } __attribute__((packed));
-            
-            union ClientMessages {
-                card8                       type;
-                SetPixelFormat              setPixelFormat;
-                SetEncodings                setEncodings;
-                FrameBufferUpdateRequest    frameBufferUpdateRequest;
-                KeyEvent                    keyEvent;
-                PointerEvent                pointerEvent;
-                ClientCutText               clientCutText;
-            };
-
-            struct Rectangle {
-                card16      x;
-                card16      y;
-                card16      w;
-                card16      h;
-                card32      encoding;
-            } __attribute__((packed));
-
-            struct FrameBufferUpdate {
-                card8       type;
-                uint8_t     padding;
-                card16      numberOfRectangles;
-                Rectangle   rectangles[0];            
-            } __attribute__((packed));
-
-            enum {
-                SET_PIXEL_FORMAT        = 0,
-                FIX_COLOUR_MAP_ENTRIES  = 1,
-                SET_ENCODINGS           = 2,
-                FRAME_BUFFER_UPDATE_REQ = 3,
-                KEY_EVENT               = 4,
-                POINTER_EVENT           = 5,
-                CLIENT_CUT_TEXT         = 6,
-            };
-
-            struct ClientMessage : public Message {
-                ClientMessage()
-                    : Message(&messageData, sizeof(messageData)) {
-                }
-                const ClientMessages& messages() const {
-                    return *static_cast<ClientMessages const *>(payload());
-                }
-                const int type() const {
-                    return messages().type;
-                }
-                status_t resize(size_t size) {
-                    return Message::resize(size);
-                }
-
-                ClientMessages messageData;
-            };
-
-            
-            class ServerThread : public Thread
-            {
-                friend class RFBServer;
-            public:
-                        ServerThread(const sp<RFBServer>& receiver);
-                virtual ~ServerThread();
-                void wake();
-                void exitAndWait();
-            private:
-                virtual bool threadLoop();
-                virtual status_t readyToRun();
-                virtual void onFirstRef();
-                wp<RFBServer> mReceiver;
-                bool (RFBServer::*mAction)();
-                Barrier mUpdateBarrier;
-            };
-            
-            class EventInjector {
-            public:
-                enum { UP=0, DOWN=1 };
-                EventInjector();
-                ~EventInjector();
-                void injectKey(uint16_t code, uint16_t value);
-            private:
-                struct input_event {
-                    struct timeval time;
-                    uint16_t type;
-                    uint16_t code;
-                    uint32_t value;
-                };
-                int mFD;
-            };
-            
-            void        handshake(uint8_t major, uint8_t minor, uint32_t auth);
-            void        waitForClientMessage(ClientMessage& msg);
-            void        handleClientMessage(const ClientMessage& msg);
-            void        handleSetPixelFormat(const SetPixelFormat& msg);
-            void        handleSetEncodings(const SetEncodings& msg);
-            void        handleFrameBufferUpdateReq(const FrameBufferUpdateRequest& msg);
-            void        handleKeyEvent(const KeyEvent& msg);
-            void        sendFrameBufferUpdates();
-
-            bool        validatePixelFormat(const PixelFormat& pf);
-            bool        alive() const;
-            bool        write(const Message& msg);
-            bool        read(Message& msg);
-
-            bool        write(const void* buffer, int size);
-            bool        read(void* buffer, int size);
-
-    virtual bool        threadLoop();
-    virtual status_t    readyToRun();
-    virtual void        onFirstRef();
-
-            sp<ServerThread>    mRobinThread;
-
-            int         mFD;
-            int         mStatus;
-            iovec*      mIoVec;
-    
-            EventInjector   mEventInjector;
-
-            Mutex       mRegionLock;
-            // This is the region requested by the client since the last
-            // time we updated it
-            Region      mClientRegionRequest;
-            // This is the region of the screen that needs to be sent to the
-            // client since the last time we updated it.
-            // Typically this is the dirty region, but not necessarily, for
-            // instance if the client asked for a non incremental update.
-            Region      mDirtyRegion;
-            
-            GGLSurface  mFrameBuffer;
-            GGLSurface  mFrontBuffer;
-};
-
-}; // namespace android
-
-#endif // ANDROID_RFB_SERVER_H
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 4e457c9c258f..900282a274d5 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -53,21 +53,14 @@
 #include "LayerDim.h"
 #include "LayerBitmap.h"
 #include "LayerOrientationAnim.h"
-#include "LayerScreenshot.h"
 #include "OrientationAnimation.h"
 #include "SurfaceFlinger.h"
-#include "RFBServer.h"
 #include "VRamHeap.h"
 
 #include "DisplayHardware/DisplayHardware.h"
 #include "GPUHardware/GPUHardware.h"
 
 
-// the VNC server even on local ports presents a significant
-// thread as it can allow an application to control and "see" other
-// applications, de-facto bypassing security permissions.
-#define ENABLE_VNC_SERVER   0
-
 #define DISPLAY_COUNT       1
 
 namespace android {
@@ -460,9 +453,6 @@ status_t SurfaceFlinger::readyToRun()
     if (mDebugNoBootAnimation == false)
         mBootAnimation = new BootAnimation(this);
 
-    if (ENABLE_VNC_SERVER)
-        mRFBServer = new RFBServer(w, h, f);
-
     return NO_ERROR;
 }
 
@@ -572,18 +562,6 @@ void SurfaceFlinger::postFramebuffer()
             debugShowFPS();
         }
 
-        if (UNLIKELY(ENABLE_VNC_SERVER &&
-                mRFBServer!=0 && mRFBServer->isConnected())) {
-            if (!mSecureFrameBuffer) {
-                GGLSurface fb;
-                // backbufer, is going to become the front buffer really soon
-                hw.getDisplaySurface(&fb);
-                if (LIKELY(fb.data != 0)) {
-                    mRFBServer->frameBufferUpdated(fb, mInvalidRegion);
-                }
-            }
-        }
-
         hw.flip(mInvalidRegion);
 
         mInvalidRegion.clear();
@@ -1571,55 +1549,17 @@ status_t SurfaceFlinger::onTransact(
 
     status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
     if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
-        if (code == 1012) {
-            // take screen-shot of the front buffer
-            if (UNLIKELY(checkCallingPermission(
-                    String16("android.permission.READ_FRAME_BUFFER")) == false))
-            { // not allowed
-                LOGE("Permission Denial: "
-                        "can't take screenshots from pid=%d, uid=%d\n",
-                        IPCThreadState::self()->getCallingPid(),
-                        IPCThreadState::self()->getCallingUid());
-                return PERMISSION_DENIED;
-            }
-
-            if (UNLIKELY(mSecureFrameBuffer)) {
-                LOGE("A secure window is on screen: "
-                        "can't take screenshots from pid=%d, uid=%d\n",
-                        IPCThreadState::self()->getCallingPid(),
-                        IPCThreadState::self()->getCallingUid());
-                return PERMISSION_DENIED;
-            }
-
-            LOGI("Taking a screenshot...");
-
-            LayerScreenshot* l = new LayerScreenshot(this, 0);
-
-            Mutex::Autolock _l(mStateLock);
-            const DisplayHardware& hw(graphicPlane(0).displayHardware());
-            l->initStates(hw.getWidth(), hw.getHeight(), 0);
-            l->setLayer(INT_MAX);
-
-            addLayer_l(l);
-            setTransactionFlags(eTransactionNeeded|eTraversalNeeded);
-
-            l->takeScreenshot(mStateLock, reply);
-
-            removeLayer_l(l);
-            setTransactionFlags(eTransactionNeeded);
-            return NO_ERROR;
-        } else {
-            // HARDWARE_TEST stuff...
-            if (UNLIKELY(checkCallingPermission(
-                    String16("android.permission.HARDWARE_TEST")) == false))
-            { // not allowed
-                LOGE("Permission Denial: pid=%d, uid=%d\n",
-                        IPCThreadState::self()->getCallingPid(),
-                        IPCThreadState::self()->getCallingUid());
-                return PERMISSION_DENIED;
-            }
-            int n;
-            switch (code) {
+        // HARDWARE_TEST stuff...
+        if (UNLIKELY(checkCallingPermission(
+                String16("android.permission.HARDWARE_TEST")) == false))
+        { // not allowed
+            LOGE("Permission Denial: pid=%d, uid=%d\n",
+                    IPCThreadState::self()->getCallingPid(),
+                    IPCThreadState::self()->getCallingUid());
+            return PERMISSION_DENIED;
+        }
+        int n;
+        switch (code) {
             case 1000: // SHOW_CPU
                 n = data.readInt32();
                 mDebugCpu = n ? 1 : 0;
@@ -1652,8 +1592,8 @@ status_t SurfaceFlinger::onTransact(
                 const DisplayHardware& hw(graphicPlane(0).displayHardware());
                 mDirtyRegion.set(hw.bounds()); // careful that's not thread-safe
                 signalEvent();
-                }
-                return NO_ERROR;
+            }
+            return NO_ERROR;
             case 1005: // ask GPU revoke
                 mGPU->friendlyRevoke();
                 return NO_ERROR;
@@ -1669,13 +1609,12 @@ status_t SurfaceFlinger::onTransact(
                 reply->writeInt32(mDebugRegion);
                 reply->writeInt32(mDebugBackground);
                 return NO_ERROR;
-            case 1013: { // screenshot
+            case 1013: {
                 Mutex::Autolock _l(mStateLock);
                 const DisplayHardware& hw(graphicPlane(0).displayHardware());
                 reply->writeInt32(hw.getPageFlipCount());
             }
             return NO_ERROR;
-            }
         }
     }
     return err;
@@ -1829,10 +1768,33 @@ void GraphicPlane::setTransform(const Transform& tr) {
     mGlobalTransform = mOrientationTransform * mTransform;
 }
 
-status_t GraphicPlane::setOrientation(int orientation)
-{
+status_t GraphicPlane::orientationToTransfrom(
+        int orientation, int w, int h, Transform* tr)
+{    
     float a, b, c, d, x, y;
+    switch (orientation) {
+    case ISurfaceComposer::eOrientationDefault:
+        a=1; b=0; c=0; d=1; x=0; y=0;
+        break;
+    case ISurfaceComposer::eOrientation90:
+        a=0; b=-1; c=1; d=0; x=w; y=0;
+        break;
+    case ISurfaceComposer::eOrientation180:
+        a=-1; b=0; c=0; d=-1; x=w; y=h;
+        break;
+    case ISurfaceComposer::eOrientation270:
+        a=0; b=1; c=-1; d=0; x=0; y=h;
+        break;
+    default:
+        return BAD_VALUE;
+    }
+    tr->set(a, b, c, d);
+    tr->set(x, y);
+    return NO_ERROR;
+}
 
+status_t GraphicPlane::setOrientation(int orientation)
+{
     const DisplayHardware& hw(displayHardware());
     const float w = hw.getWidth();
     const float h = hw.getHeight();
@@ -1846,30 +1808,21 @@ status_t GraphicPlane::setOrientation(int orientation)
 
     // If the rotation can be handled in hardware, this is where
     // the magic should happen.
-
-    switch (orientation) {
-    case ISurfaceComposer::eOrientation90:
-        a=0; b=-1; c=1; d=0; x=w; y=0;
-        break;
-    case ISurfaceComposer::eOrientation180:
-        a=-1; b=0; c=0; d=-1; x=w; y=h;
-        break;
-    case ISurfaceComposer::eOrientation270:
-        a=0; b=1; c=-1; d=0; x=0; y=h;
-        break;
-    case 42: {
+    if (UNLIKELY(orientation == 42)) {
+        float a, b, c, d, x, y;
         const float r = (3.14159265f / 180.0f) * 42.0f;
         const float si = sinf(r);
         const float co = cosf(r);
         a=co; b=-si; c=si; d=co;
         x = si*(h*0.5f) + (1-co)*(w*0.5f);
         y =-si*(w*0.5f) + (1-co)*(h*0.5f);
-    } break;
-    default:
-        return BAD_VALUE;
+        mOrientationTransform.set(a, b, c, d);
+        mOrientationTransform.set(x, y);
+    } else {
+        GraphicPlane::orientationToTransfrom(orientation, w, h,
+                &mOrientationTransform);
     }
-    mOrientationTransform.set(a, b, c, d);
-    mOrientationTransform.set(x, y);
+    
     mGlobalTransform = mOrientationTransform * mTransform;
     return NO_ERROR;
 }
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index 8e5fd885d5a5..f7d77640ae3c 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -58,7 +58,6 @@ class Layer;
 class LayerBuffer;
 class LayerOrientationAnim;
 class OrientationAnimation;
-class RFBServer;
 class SurfaceHeapManager;
 
 typedef int32_t ClientID;
@@ -112,6 +111,8 @@ private:
 class GraphicPlane
 {
 public:
+    static status_t orientationToTransfrom(int orientation, int w, int h,
+            Transform* tr);
 
                                 GraphicPlane();
                                 ~GraphicPlane();
@@ -344,7 +345,6 @@ private:
                 sp<GPUHardwareInterface>    mGPU;
                 GLuint                      mWormholeTexName;
                 sp<BootAnimation>           mBootAnimation;
-                sp<RFBServer>               mRFBServer;
                 nsecs_t                     mBootTime;
                 
                 // Can only accessed from the main thread, these members
diff --git a/libs/ui/ISurface.cpp b/libs/ui/ISurface.cpp
index abd3634b9a34..d5e9f812a40b 100644
--- a/libs/ui/ISurface.cpp
+++ b/libs/ui/ISurface.cpp
@@ -37,7 +37,7 @@ ISurface::BufferHeap::BufferHeap(uint32_t w, uint32_t h,
         int32_t hor_stride, int32_t ver_stride,
         PixelFormat format, const sp<IMemoryHeap>& heap)
     : w(w), h(h), hor_stride(hor_stride), ver_stride(ver_stride),
-      format(format), heap(heap) 
+      format(format), transform(0), flags(0), heap(heap) 
 {
 }
 
diff --git a/location/java/com/android/internal/location/INetworkLocationManager.java b/location/java/com/android/internal/location/INetworkLocationManager.java
index 83bbe1fdf526..6b632fde15f1 100644
--- a/location/java/com/android/internal/location/INetworkLocationManager.java
+++ b/location/java/com/android/internal/location/INetworkLocationManager.java
@@ -16,6 +16,8 @@
 
 package com.android.internal.location;
 
+import android.content.Context;
+
 /**
  * Used to register network location and collection services 
  * with the Location Manager Service.
@@ -23,6 +25,13 @@ package com.android.internal.location;
  * {@hide}
  */
 public interface INetworkLocationManager {
+
+    /* callback to allow installation to occur in Location Manager's thread */
+    public interface InstallCallback {
+        void installNetworkLocationProvider(Context context, INetworkLocationManager manager);
+    }
+    
+    void setInstallCallback(InstallCallback callback);
     void setNetworkLocationProvider(INetworkLocationProvider provider);
     void setLocationCollector(ILocationCollector collector);
 }
\ No newline at end of file
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 297877418a58..4d2e7250271c 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -135,7 +135,7 @@ public class AudioManager {
     public static final int STREAM_VOICE_CALL = AudioSystem.STREAM_VOICE_CALL;
     /** The audio stream for system sounds */
     public static final int STREAM_SYSTEM = AudioSystem.STREAM_SYSTEM;
-    /** The audio stream for the phone ring and message alerts */
+    /** The audio stream for the phone ring */
     public static final int STREAM_RING = AudioSystem.STREAM_RING;
     /** The audio stream for music playback */
     public static final int STREAM_MUSIC = AudioSystem.STREAM_MUSIC;
@@ -214,14 +214,13 @@ public class AudioManager {
     /**
      * Whether to include ringer modes as possible options when changing volume.
      * For example, if true and volume level is 0 and the volume is adjusted
-     * with {@link #ADJUST_LOWER}, then the ringer mode may switch the silent
-     * or vibrate mode.
+     * with {@link #ADJUST_LOWER}, then the ringer mode may switch the silent or
+     * vibrate mode.
      * <p>
-     * By default this is on for stream types that are affected by the ringer
-     * mode (for example, the ring stream type). If this flag is included, this
-     * behavior will be present regardless of the stream type being affected by
-     * the ringer mode.
-     *
+     * By default this is on for the ring stream. If this flag is included,
+     * this behavior will be present regardless of the stream type being
+     * affected by the ringer mode.
+     * 
      * @see #adjustVolume(int, int)
      * @see #adjustStreamVolume(int, int, int)
      */
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 1314ba14648b..fd990fe756cb 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -339,7 +339,11 @@ public class AudioRecord
      * Releases the native AudioRecord resources.
      */
     public void release() {
-        stop();
+        try {
+            stop();
+        } catch(IllegalStateException ise) { 
+            // don't raise an exception, we're releasing the resources.
+        }
         native_release();
         mState = STATE_UNINITIALIZED;
     }
@@ -427,6 +431,56 @@ public class AudioRecord
     public int getPositionNotificationPeriod() {
         return native_get_pos_update_period();
     }
+    
+    /**
+     * {@hide}
+     * Returns the minimum buffer size required for the successful creation of an AudioRecord
+     * object.
+     * @param sampleRateInHz the sample rate expressed in Hertz.
+     * @param channelConfig describes the configuration of the audio channels. 
+     *   See {@link AudioFormat#CHANNEL_CONFIGURATION_MONO} and
+     *   {@link AudioFormat#CHANNEL_CONFIGURATION_STEREO}
+     * @param audioFormat the format in which the audio data is represented. 
+     *   See {@link AudioFormat#ENCODING_PCM_16BIT}.
+     * @return {@link #ERROR_BAD_VALUE} if the recording parameters are not supported by the 
+     *  hardware, or an invalid parameter was passed,
+     *  or {@link #ERROR} if the implementation was unable to query the hardware for its 
+     *  output properties, 
+     *   or the minimum buffer size expressed in of bytes.
+     */
+    static public int getMinBufferSize(int sampleRateInHz, int channelConfig, int audioFormat) {
+        int channelCount = 0;
+        switch(channelConfig) {
+        case AudioFormat.CHANNEL_CONFIGURATION_DEFAULT:
+        case AudioFormat.CHANNEL_CONFIGURATION_MONO:
+            channelCount = 1;
+            break;
+        case AudioFormat.CHANNEL_CONFIGURATION_STEREO:
+            channelCount = 2;
+            break;
+        case AudioFormat.CHANNEL_CONFIGURATION_INVALID:
+        default:
+            loge("getMinBufferSize(): Invalid channel configuration.");
+            return AudioRecord.ERROR_BAD_VALUE;
+        }
+        
+        // PCM_8BIT is not supported at the moment
+        if (audioFormat != AudioFormat.ENCODING_PCM_16BIT) {
+            loge("getMinBufferSize(): Invalid audio format.");
+            return AudioRecord.ERROR_BAD_VALUE;
+        }
+        
+        int size = native_get_min_buff_size(sampleRateInHz, channelCount, audioFormat);
+        if (size == 0) {
+            return AudioRecord.ERROR_BAD_VALUE;
+        } 
+        else if (size == -1) {
+            return AudioRecord.ERROR;
+        }
+        else {
+            return size;
+        }
+    }
 
 
     //---------------------------------------------------------
@@ -699,6 +753,9 @@ public class AudioRecord
     
     private native final int native_set_pos_update_period(int updatePeriod);
     private native final int native_get_pos_update_period();
+    
+    static private native final int native_get_min_buff_size(
+            int sampleRateInHz, int channelCount, int audioFormat);
 
     
     //---------------------------------------------------------
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index f3d895703b98..bdabda7b29c2 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -349,9 +349,9 @@ public class AudioService extends IAudioService.Stub {
         // If either the client forces allowing ringer modes for this adjustment,
         // or the stream type is one that is affected by ringer modes
         if ((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0
-                || isStreamAffectedByRingerMode(streamType)) {
+                || streamType == AudioManager.STREAM_RING) {
             // Check if the ringer mode changes with this volume adjustment. If
-            // it does, it will handle adjusting the volome, so we won't below
+            // it does, it will handle adjusting the volume, so we won't below
             adjustVolume = checkForRingerModeChange(oldIndex, direction);
         }
 
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 9bb1df94080a..74ffc1a97a7d 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -395,7 +395,11 @@ public class AudioTrack
     public void release() {
         // even though native_release() stops the native AudioTrack, we need to stop
         // AudioTrack subclasses too.
-        stop();
+        try {
+            stop();
+        } catch(IllegalStateException ise) { 
+            // don't raise an exception, we're releasing the resources.
+        }
         native_release();
         mState = STATE_UNINITIALIZED;
     }
@@ -1007,4 +1011,4 @@ public class AudioTrack
         Log.e(TAG, "[ android.media.AudioTrack ] " + msg);
     }
 
-}
\ No newline at end of file
+}
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 4a301149da20..3609826b5500 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -19,6 +19,10 @@ package android.media;
 import android.view.Surface;
 import android.hardware.Camera;
 import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileDescriptor;
+import android.util.Log;
 
 /**
  * Used to record audio and video. The recording control is based on a
@@ -50,6 +54,7 @@ public class MediaRecorder
     static {
         System.loadLibrary("media_jni");
     }
+    private final static String TAG = "MediaRecorder";
     
     // The two fields below are accessed by native methods
     @SuppressWarnings("unused")
@@ -57,7 +62,10 @@ public class MediaRecorder
     
     @SuppressWarnings("unused")
     private Surface mSurface;
-    
+
+    private String mPath;
+    private FileDescriptor mFd;
+
     /**
      * Default constructor.
      */
@@ -71,8 +79,6 @@ public class MediaRecorder
      * the camera object. Must call before prepare().
      * 
      * @param c the Camera to use for recording
-     * FIXME: Temporarily hidden until API approval
-     * @hide
      */
     public native void setCamera(Camera c);
 
@@ -104,7 +110,6 @@ public class MediaRecorder
     /**
      * Defines the video source. These constants are used with 
      * {@link MediaRecorder#setVideoSource(int)}.
-     * @hide
      */
     public final class VideoSource {
       /* Do not change these values without updating their counterparts
@@ -152,7 +157,6 @@ public class MediaRecorder
     /**
      * Defines the video encoding. These constants are used with 
      * {@link MediaRecorder#setVideoEncoder(int)}.
-     * @hide
      */
     public final class VideoEncoder {
       /* Do not change these values without updating their counterparts
@@ -187,7 +191,6 @@ public class MediaRecorder
      * @param video_source the video source to use
      * @throws IllegalStateException if it is called after setOutputFormat()
      * @see android.media.MediaRecorder.VideoSource
-     * @hide
      */ 
     public native void setVideoSource(int video_source)
             throws IllegalStateException;
@@ -214,7 +217,6 @@ public class MediaRecorder
      * @param height the height of the video to be captured
      * @throws IllegalStateException if it is called after 
      * prepare() or before setOutputFormat()
-     * @hide
      */
     public native void setVideoSize(int width, int height)
             throws IllegalStateException;
@@ -227,7 +229,10 @@ public class MediaRecorder
      * @param rate the number of frames per second of video to capture
      * @throws IllegalStateException if it is called after 
      * prepare() or before setOutputFormat().
-     * @hide
+     *
+     * NOTE: On some devices that have auto-frame rate, this sets the
+     * maximum frame rate, not a constant frame rate. Actual frame rate
+     * will vary according to lighting conditions.
      */
     public native void setVideoFrameRate(int rate) throws IllegalStateException;
 
@@ -253,21 +258,43 @@ public class MediaRecorder
      * @throws IllegalStateException if it is called before
      * setOutputFormat() or after prepare()
      * @see android.media.MediaRecorder.VideoEncoder
-     * @hide
      */ 
     public native void setVideoEncoder(int video_encoder)
             throws IllegalStateException;
 
+    /**
+     * Pass in the file descriptor of the file to be written. Call this after
+     * setOutputFormat() but before prepare().
+     * 
+     * @param fd an open file descriptor to be written into.
+     * @throws IllegalStateException if it is called before
+     * setOutputFormat() or after prepare()
+     */ 
+    public void setOutputFile(FileDescriptor fd) throws IllegalStateException
+    {
+        mPath = null;
+        mFd = fd;
+    }
+  
     /**
      * Sets the path of the output file to be produced. Call this after
      * setOutputFormat() but before prepare().
      * 
-     * @param path The pathname to use()
+     * @param path The pathname to use.
      * @throws IllegalStateException if it is called before
      * setOutputFormat() or after prepare()
      */ 
-    public native void setOutputFile(String path) throws IllegalStateException;
+    public void setOutputFile(String path) throws IllegalStateException
+    {
+        mFd = null;
+        mPath = path;
+    }
   
+    // native implementation
+    private native void _setOutputFile(FileDescriptor fd, long offset, long length)
+        throws IllegalStateException, IOException;
+    private native void _prepare() throws IllegalStateException, IOException;
+
     /**
      * Prepares the recorder to begin capturing and encoding data. This method
      * must be called after setting up the desired audio and video sources,
@@ -277,7 +304,18 @@ public class MediaRecorder
      * start() or before setOutputFormat().
      * @throws IOException if prepare fails otherwise.
      */
-    public native void prepare() throws IllegalStateException, IOException;
+    public void prepare() throws IllegalStateException, IOException
+    {
+        if (mPath != null) {
+            FileOutputStream f = new FileOutputStream(mPath);
+            _setOutputFile(f.getFD(), 0, 0);
+        } else if (mFd != null) {
+            _setOutputFile(mFd, 0, 0);
+        } else {
+            throw new IOException("No valid output file");
+        }
+        _prepare();
+    }
 
     /**
      * Begins capturing and encoding data to the file specified with 
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 8eb638ec1920..095749b75e50 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -143,25 +143,17 @@ android_media_MediaRecorder_setAudioEncoder(JNIEnv *env, jobject thiz, jint ae)
 }
 
 static void
-android_media_MediaRecorder_setOutputFile(JNIEnv *env, jobject thiz, jstring path)
+android_media_MediaRecorder_setOutputFileFD(JNIEnv *env, jobject thiz, jobject fileDescriptor, jlong offset, jlong length)
 {
     LOGV("setOutputFile");
-    MediaRecorder *mr = (MediaRecorder *)env->GetIntField(thiz, fields.context);
-
-    if (path == NULL) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", "Path is a NULL pointer");
-        return;
-    }
-    const char *pathStr = env->GetStringUTFChars(path, NULL);
-    if (pathStr == NULL) {  // Out of memory
-        jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
+    if (fileDescriptor == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
         return;
     }
-    status_t opStatus = mr->setOutputFile(pathStr);
-
-    // Make sure that local ref is released before a potential exception
-    env->ReleaseStringUTFChars(path, pathStr);
-    process_media_recorder_call(env, opStatus, "java/lang/RuntimeException", "setOutputFile failed.");
+    int fd = getParcelFileDescriptorFD(env, fileDescriptor);
+    MediaRecorder *mr = (MediaRecorder *)env->GetIntField(thiz, fields.context);
+    status_t opStatus = mr->setOutputFile(fd, offset, length);
+    process_media_recorder_call(env, opStatus, "java/io/IOException", "setOutputFile failed.");
 }
 
 static void
@@ -273,23 +265,23 @@ android_media_MediaRecorder_native_finalize(JNIEnv *env, jobject thiz)
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gMethods[] = {
-    {"setCamera",            "(Landroid/hardware/Camera;)V",(void *)android_media_MediaRecorder_setCamera},
-    {"setVideoSource",       "(I)V",                    (void *)android_media_MediaRecorder_setVideoSource},
-    {"setAudioSource",       "(I)V",                    (void *)android_media_MediaRecorder_setAudioSource},
-    {"setOutputFormat",      "(I)V",                    (void *)android_media_MediaRecorder_setOutputFormat},
-    {"setVideoEncoder",      "(I)V",                    (void *)android_media_MediaRecorder_setVideoEncoder},
-    {"setAudioEncoder",      "(I)V",                    (void *)android_media_MediaRecorder_setAudioEncoder},
-    {"setOutputFile",        "(Ljava/lang/String;)V",   (void *)android_media_MediaRecorder_setOutputFile},
-    {"setVideoSize",         "(II)V",                   (void *)android_media_MediaRecorder_setVideoSize},
-    {"setVideoFrameRate",    "(I)V",                    (void *)android_media_MediaRecorder_setVideoFrameRate},
-    {"prepare",              "()V",                     (void *)android_media_MediaRecorder_prepare},
-    {"getMaxAmplitude",      "()I",                     (void *)android_media_MediaRecorder_native_getMaxAmplitude},
-    {"start",                "()V",                     (void *)android_media_MediaRecorder_start},
-    {"stop",                 "()V",                     (void *)android_media_MediaRecorder_stop},
-    {"reset",                "()V",                     (void *)android_media_MediaRecorder_reset},
-    {"release",              "()V",                     (void *)android_media_MediaRecorder_release},
-    {"native_setup",         "()V",                     (void *)android_media_MediaRecorder_native_setup},
-    {"native_finalize",      "()V",                     (void *)android_media_MediaRecorder_native_finalize},
+    {"setCamera",            "(Landroid/hardware/Camera;)V",    (void *)android_media_MediaRecorder_setCamera},
+    {"setVideoSource",       "(I)V",                            (void *)android_media_MediaRecorder_setVideoSource},
+    {"setAudioSource",       "(I)V",                            (void *)android_media_MediaRecorder_setAudioSource},
+    {"setOutputFormat",      "(I)V",                            (void *)android_media_MediaRecorder_setOutputFormat},
+    {"setVideoEncoder",      "(I)V",                            (void *)android_media_MediaRecorder_setVideoEncoder},
+    {"setAudioEncoder",      "(I)V",                            (void *)android_media_MediaRecorder_setAudioEncoder},
+    {"_setOutputFile",       "(Ljava/io/FileDescriptor;JJ)V",   (void *)android_media_MediaRecorder_setOutputFileFD},
+    {"setVideoSize",         "(II)V",                           (void *)android_media_MediaRecorder_setVideoSize},
+    {"setVideoFrameRate",    "(I)V",                            (void *)android_media_MediaRecorder_setVideoFrameRate},
+    {"_prepare",             "()V",                             (void *)android_media_MediaRecorder_prepare},
+    {"getMaxAmplitude",      "()I",                             (void *)android_media_MediaRecorder_native_getMaxAmplitude},
+    {"start",                "()V",                             (void *)android_media_MediaRecorder_start},
+    {"stop",                 "()V",                             (void *)android_media_MediaRecorder_stop},
+    {"reset",                "()V",                             (void *)android_media_MediaRecorder_reset},
+    {"release",              "()V",                             (void *)android_media_MediaRecorder_release},
+    {"native_setup",         "()V",                             (void *)android_media_MediaRecorder_native_setup},
+    {"native_finalize",      "()V",                             (void *)android_media_MediaRecorder_native_finalize},
 };
 
 static const char* const kClassPathName = "android/media/MediaRecorder";
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index 559f9d5ba3f0..02731825e087 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -491,10 +491,11 @@ void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftV
     // initialize track
     int afFrameCount;
     int afSampleRate;
-    if (AudioSystem::getOutputFrameCount(&afFrameCount) != NO_ERROR) {
+    int streamType = mSoundPool->streamType();
+    if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
         afFrameCount = kDefaultFrameCount;
     }
-    if (AudioSystem::getOutputSamplingRate(&afSampleRate) != NO_ERROR) {
+    if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
         afSampleRate = kDefaultSampleRate;
     }
     int numChannels = sample->numChannels();
@@ -522,10 +523,10 @@ void SoundChannel::play(const sp<Sample>& sample, int nextChannelID, float leftV
     void *userData = (void *)((unsigned long)this | toggle);
     
 #ifdef USE_SHARED_MEM_BUFFER
-    newTrack = new AudioTrack(mSoundPool->streamType(), sampleRate, sample->format(),
+    newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
             numChannels, sample->getIMemory(), 0, callback, userData);
 #else
-    newTrack = new AudioTrack(mSoundPool->streamType(), sampleRate, sample->format(),
+    newTrack = new AudioTrack(streamType, sampleRate, sample->format(),
             numChannels, frameCount, 0, callback, userData, bufferFrames);
 #endif
     if (newTrack->initCheck() != NO_ERROR) {
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index a987b9228d08..3d39181922f1 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -128,22 +128,8 @@ status_t AudioRecord::set(
         return BAD_VALUE;
     }
 
-    size_t inputBuffSizeInBytes = -1;
-    if (AudioSystem::getInputBufferSize(sampleRate, format, channelCount, &inputBuffSizeInBytes)
-        != NO_ERROR) {
-            LOGE("AudioSystem could not query the input buffer size.");
-            return NO_INIT;
-    }
-    if (inputBuffSizeInBytes == 0) {
-        LOGE("Recording parameters are not supported: sampleRate %d, channelCount %d, format %d",
-            sampleRate, channelCount, format);
-        return BAD_VALUE;
-    }
-    int frameSizeInBytes = channelCount * (format == AudioSystem::PCM_16_BIT ? 2 : 1);
-    
-    // We use 2* size of input buffer for ping pong use of record buffer.
-    int minFrameCount = 2 * inputBuffSizeInBytes / frameSizeInBytes;
-    LOGV("AudioRecord::set() minFrameCount = %d", minFrameCount);
+    // TODO: Get input frame count from hardware.
+    int minFrameCount = 1024*2;
 
     if (frameCount == 0) {
         frameCount = minFrameCount;
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index cf911058e411..63dfc3b368b3 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -20,7 +20,6 @@
 #include <utils/Log.h>
 #include <utils/IServiceManager.h>
 #include <media/AudioSystem.h>
-#include <media/AudioTrack.h>
 #include <math.h>
 
 namespace android {
@@ -31,9 +30,10 @@ sp<IAudioFlinger> AudioSystem::gAudioFlinger;
 sp<AudioSystem::AudioFlingerClient> AudioSystem::gAudioFlingerClient;
 audio_error_callback AudioSystem::gAudioErrorCallback = NULL;
 // Cached values
-int AudioSystem::gOutSamplingRate = 0;
-int AudioSystem::gOutFrameCount = 0;
-uint32_t AudioSystem::gOutLatency = 0;
+int AudioSystem::gOutSamplingRate[NUM_AUDIO_OUTPUT_TYPES];
+int AudioSystem::gOutFrameCount[NUM_AUDIO_OUTPUT_TYPES];
+uint32_t AudioSystem::gOutLatency[NUM_AUDIO_OUTPUT_TYPES];
+bool AudioSystem::gA2dpEnabled;
 // Cached values for recording queries
 uint32_t AudioSystem::gPrevInSamplingRate = 16000;
 int AudioSystem::gPrevInFormat = AudioSystem::PCM_16_BIT;
@@ -66,9 +66,12 @@ const sp<IAudioFlinger>& AudioSystem::get_audio_flinger()
         gAudioFlinger = interface_cast<IAudioFlinger>(binder);
         gAudioFlinger->registerClient(gAudioFlingerClient);
         // Cache frequently accessed parameters 
-        gOutFrameCount = (int)gAudioFlinger->frameCount();
-        gOutSamplingRate = (int)gAudioFlinger->sampleRate();
-        gOutLatency = gAudioFlinger->latency();
+        for (int output = 0; output < NUM_AUDIO_OUTPUT_TYPES; output++) {
+            gOutFrameCount[output] = (int)gAudioFlinger->frameCount(output);
+            gOutSamplingRate[output] = (int)gAudioFlinger->sampleRate(output);
+            gOutLatency[output] = gAudioFlinger->latency(output);
+        }
+        gA2dpEnabled = gAudioFlinger->isA2dpEnabled();
     }
     LOGE_IF(gAudioFlinger==0, "no AudioFlinger!?");
     return gAudioFlinger;
@@ -147,7 +150,7 @@ status_t AudioSystem::getMasterMute(bool* mute)
 
 status_t AudioSystem::setStreamVolume(int stream, float value)
 {
-    if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) return BAD_VALUE;
+    if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE;
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
     af->setStreamVolume(stream, value);
@@ -156,7 +159,7 @@ status_t AudioSystem::setStreamVolume(int stream, float value)
 
 status_t AudioSystem::setStreamMute(int stream, bool mute)
 {
-    if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) return BAD_VALUE;
+    if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE;
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
     af->setStreamMute(stream, mute);
@@ -165,7 +168,7 @@ status_t AudioSystem::setStreamMute(int stream, bool mute)
 
 status_t AudioSystem::getStreamVolume(int stream, float* volume)
 {
-    if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) return BAD_VALUE;
+    if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE;
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
     *volume = af->streamVolume(stream);
@@ -174,7 +177,7 @@ status_t AudioSystem::getStreamVolume(int stream, float* volume)
 
 status_t AudioSystem::getStreamMute(int stream, bool* mute)
 {
-    if (uint32_t(stream) >= AudioTrack::NUM_STREAM_TYPES) return BAD_VALUE;
+    if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE;
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
     *mute = af->streamMute(stream);
@@ -252,37 +255,48 @@ int AudioSystem::logToLinear(float volume)
     return volume ? 100 - int(dBConvertInverse * log(volume) + 0.5) : 0;
 }
 
-status_t AudioSystem::getOutputSamplingRate(int* samplingRate)
+status_t AudioSystem::getOutputSamplingRate(int* samplingRate, int streamType)
 {
-    if (gOutSamplingRate == 0) {
+    int output = getOutput(streamType);
+
+    if (gOutSamplingRate[output] == 0) {
         const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
         if (af == 0) return PERMISSION_DENIED;
         // gOutSamplingRate is updated by get_audio_flinger()
     }
-    *samplingRate = gOutSamplingRate;
+    LOGV("getOutputSamplingRate() streamType %d, output %d, sampling rate %d", streamType, output, gOutSamplingRate[output]);
+    *samplingRate = gOutSamplingRate[output];
     
     return NO_ERROR;
 }
 
-status_t AudioSystem::getOutputFrameCount(int* frameCount)
+status_t AudioSystem::getOutputFrameCount(int* frameCount, int streamType)
 {
-    if (gOutFrameCount == 0) {
+    int output = getOutput(streamType);
+
+    if (gOutFrameCount[output] == 0) {
         const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
         if (af == 0) return PERMISSION_DENIED;
         // gOutFrameCount is updated by get_audio_flinger()
     }
-    *frameCount = gOutFrameCount;
+    LOGV("getOutputFrameCount() streamType %d, output %d, frame count %d", streamType, output, gOutFrameCount[output]);
+
+    *frameCount = gOutFrameCount[output];
     return NO_ERROR;
 }
 
-status_t AudioSystem::getOutputLatency(uint32_t* latency)
+status_t AudioSystem::getOutputLatency(uint32_t* latency, int streamType)
 {
-    if (gOutLatency == 0) {
+    int output = getOutput(streamType);
+
+    if (gOutLatency[output] == 0) {
         const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
         if (af == 0) return PERMISSION_DENIED;
         // gOutLatency is updated by get_audio_flinger()
-    }    
-    *latency = gOutLatency;
+    }
+    LOGV("getOutputLatency() streamType %d, output %d, latency %d", streamType, output, gOutLatency[output]);
+
+    *latency = gOutLatency[output];
     
     return NO_ERROR;
 }
@@ -315,24 +329,23 @@ status_t AudioSystem::getInputBufferSize(uint32_t sampleRate, int format, int ch
 void AudioSystem::AudioFlingerClient::binderDied(const wp<IBinder>& who) {   
     Mutex::Autolock _l(AudioSystem::gLock);
     AudioSystem::gAudioFlinger.clear();
-    AudioSystem::gOutSamplingRate = 0;
-    AudioSystem::gOutFrameCount = 0;
-    AudioSystem::gOutLatency = 0;
+
+    for (int output = 0; output < NUM_AUDIO_OUTPUT_TYPES; output++) {
+        gOutFrameCount[output] = 0;
+        gOutSamplingRate[output] = 0;
+        gOutLatency[output] = 0;
+    }
     AudioSystem::gInBuffSize = 0;
-    
+
     if (gAudioErrorCallback) {
         gAudioErrorCallback(DEAD_OBJECT);
     }
     LOGW("AudioFlinger server died!");
 }
 
-void AudioSystem::AudioFlingerClient::audioOutputChanged(uint32_t frameCount, uint32_t samplingRate, uint32_t latency) {
-
-    AudioSystem::gOutFrameCount = frameCount;
-    AudioSystem::gOutSamplingRate = samplingRate;
-    AudioSystem::gOutLatency = latency;
-
-    LOGV("AudioFlinger output changed!");
+void AudioSystem::AudioFlingerClient::a2dpEnabledChanged(bool enabled) {
+    gA2dpEnabled = enabled;        
+    LOGV("AudioFlinger A2DP enabled status changed! %d", enabled);
 }
 
 void AudioSystem::setErrorCallback(audio_error_callback cb) {
@@ -340,5 +353,31 @@ void AudioSystem::setErrorCallback(audio_error_callback cb) {
     gAudioErrorCallback = cb;
 }
 
+int AudioSystem::getOutput(int streamType)
+{  
+    if (streamType == DEFAULT) {
+        streamType = MUSIC;
+    }
+    if (gA2dpEnabled && routedToA2dpOutput(streamType)) {
+        return AUDIO_OUTPUT_A2DP;
+    } else {
+        return AUDIO_OUTPUT_HARDWARE;
+    }
+}
+
+bool AudioSystem::routedToA2dpOutput(int streamType) {
+    switch(streamType) {
+    case MUSIC:
+    case VOICE_CALL:
+    case BLUETOOTH_SCO:
+    case SYSTEM:
+        return true;
+    default:
+        return false;
+    }
+}
+
+
+
 }; // namespace android
 
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 63b2012fed31..1ffad463710a 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -128,22 +128,21 @@ status_t AudioTrack::set(
        return NO_INIT;
     }
     int afSampleRate;
-    if (AudioSystem::getOutputSamplingRate(&afSampleRate) != NO_ERROR) {
+    if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
         return NO_INIT;
     }
     int afFrameCount;
-    if (AudioSystem::getOutputFrameCount(&afFrameCount) != NO_ERROR) {
+    if (AudioSystem::getOutputFrameCount(&afFrameCount, streamType) != NO_ERROR) {
         return NO_INIT;
     }
     uint32_t afLatency;
-    if (AudioSystem::getOutputLatency(&afLatency) != NO_ERROR) {
+    if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) {
         return NO_INIT;
     }
 
-
     // handle default values first.
-    if (streamType == DEFAULT) {
-        streamType = MUSIC;
+    if (streamType == AudioSystem::DEFAULT) {
+        streamType = AudioSystem::MUSIC;
     }
     if (sampleRate == 0) {
         sampleRate = afSampleRate;
@@ -260,7 +259,7 @@ status_t AudioTrack::set(
     mMarkerPosition = 0;
     mNewPosition = 0;
     mUpdatePeriod = 0;
-    
+
     return NO_ERROR;
 }
 
@@ -434,7 +433,7 @@ void AudioTrack::setSampleRate(int rate)
 {
     int afSamplingRate;
 
-    if (AudioSystem::getOutputSamplingRate(&afSamplingRate) != NO_ERROR) {
+    if (AudioSystem::getOutputSamplingRate(&afSamplingRate, mStreamType) != NO_ERROR) {
         return;
     }
     // Resampler implementation limits input sampling rate to 2 x output sampling rate.
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 4215820b0e0d..5cbb25ca1fc9 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -53,7 +53,8 @@ enum {
     SET_PARAMETER,
     REGISTER_CLIENT,
     GET_INPUTBUFFERSIZE,
-    WAKE_UP
+    WAKE_UP,
+    IS_A2DP_ENABLED
 };
 
 class BpAudioFlinger : public BpInterface<IAudioFlinger>
@@ -123,42 +124,47 @@ public:
         return interface_cast<IAudioRecord>(reply.readStrongBinder());
     }
 
-    virtual uint32_t sampleRate() const
+    virtual uint32_t sampleRate(int output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(output);
         remote()->transact(SAMPLE_RATE, data, &reply);
         return reply.readInt32();
     }
 
-    virtual int channelCount() const
+    virtual int channelCount(int output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(output);
         remote()->transact(CHANNEL_COUNT, data, &reply);
         return reply.readInt32();
     }
 
-    virtual int format() const
+    virtual int format(int output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(output);
         remote()->transact(FORMAT, data, &reply);
         return reply.readInt32();
     }
 
-    virtual size_t frameCount() const
+    virtual size_t frameCount(int output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(output);
         remote()->transact(FRAME_COUNT, data, &reply);
         return reply.readInt32();
     }
 
-    virtual uint32_t latency() const
+    virtual uint32_t latency(int output) const
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        data.writeInt32(output);
         remote()->transact(LATENCY, data, &reply);
         return reply.readInt32();
     }
@@ -333,6 +339,14 @@ public:
         remote()->transact(WAKE_UP, data, &reply);
         return;
     }
+
+    virtual bool isA2dpEnabled() const
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+        remote()->transact(IS_A2DP_ENABLED, data, &reply);
+        return (bool)reply.readInt32();
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AudioFlinger, "android.media.IAudioFlinger");
@@ -385,27 +399,32 @@ status_t BnAudioFlinger::onTransact(
         } break;
         case SAMPLE_RATE: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( sampleRate() );
+            int output = data.readInt32();
+            reply->writeInt32( sampleRate(output) );
             return NO_ERROR;
         } break;
         case CHANNEL_COUNT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( channelCount() );
+            int output = data.readInt32();
+            reply->writeInt32( channelCount(output) );
             return NO_ERROR;
         } break;
         case FORMAT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( format() );
+            int output = data.readInt32();
+            reply->writeInt32( format(output) );
             return NO_ERROR;
         } break;
         case FRAME_COUNT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( frameCount() );
+            int output = data.readInt32();
+            reply->writeInt32( frameCount(output) );
             return NO_ERROR;
         } break;
         case LATENCY: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( latency() );
+            int output = data.readInt32();
+            reply->writeInt32( latency(output) );
             return NO_ERROR;
         } break;
          case SET_MASTER_VOLUME: {
@@ -519,7 +538,11 @@ status_t BnAudioFlinger::onTransact(
             wakeUp();
             return NO_ERROR;
         } break;
-
+        case IS_A2DP_ENABLED: {
+            CHECK_INTERFACE(IAudioFlinger, data, reply);
+            reply->writeInt32( (int)isA2dpEnabled() );
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp
index d9562665d00a..5feb11fb10bb 100644
--- a/media/libmedia/IAudioFlingerClient.cpp
+++ b/media/libmedia/IAudioFlingerClient.cpp
@@ -38,13 +38,11 @@ public:
     {
     }
 
-    void audioOutputChanged(uint32_t frameCount, uint32_t samplingRate, uint32_t latency)
+    void a2dpEnabledChanged(bool enabled)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlingerClient::getInterfaceDescriptor());
-        data.writeInt32(frameCount);
-        data.writeInt32(samplingRate);
-        data.writeInt32(latency);
+        data.writeInt32((int)enabled);
         remote()->transact(AUDIO_OUTPUT_CHANGED, data, &reply);
     }
 };
@@ -65,10 +63,8 @@ status_t BnAudioFlingerClient::onTransact(
     switch(code) {
         case AUDIO_OUTPUT_CHANGED: {
             CHECK_INTERFACE(IAudioFlingerClient, data, reply);
-            uint32_t frameCount = data.readInt32();
-            uint32_t samplingRate = data.readInt32();
-            uint32_t latency = data.readInt32();
-            audioOutputChanged(frameCount, samplingRate, latency);
+            bool enabled = (bool)data.readInt32();
+            a2dpEnabledChanged(enabled);
             return NO_ERROR;
         } break;
         default:
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 1f6d59990abf..507d03ea0da6 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -39,7 +39,8 @@ enum {
     SET_OUTPUT_FORMAT,
     SET_VIDEO_ENCODER,
     SET_AUDIO_ENCODER,
-    SET_OUTPUT_FILE,
+    SET_OUTPUT_FILE_PATH,
+    SET_OUTPUT_FILE_FD,
     SET_VIDEO_SIZE,
     SET_VIDEO_FRAMERATE,
     SET_PREVIEW_SURFACE,
@@ -139,7 +140,18 @@ public:
         Parcel data, reply;
         data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
         data.writeCString(path);
-        remote()->transact(SET_OUTPUT_FILE, data, &reply);
+        remote()->transact(SET_OUTPUT_FILE_PATH, data, &reply);
+        return reply.readInt32();
+    }
+
+    status_t setOutputFile(int fd, int64_t offset, int64_t length) {
+        LOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length);
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeFileDescriptor(fd);
+        data.writeInt64(offset);
+        data.writeInt64(length);
+        remote()->transact(SET_OUTPUT_FILE_FD, data, &reply);
         return reply.readInt32();
     }
 
@@ -330,13 +342,22 @@ status_t BnMediaRecorder::onTransact(
             return NO_ERROR;
 
         } break;
-        case SET_OUTPUT_FILE: {
-            LOGV("SET_OUTPUT_FILE");
+        case SET_OUTPUT_FILE_PATH: {
+            LOGV("SET_OUTPUT_FILE_PATH");
             CHECK_INTERFACE(IMediaRecorder, data, reply);
             const char* path = data.readCString();
             reply->writeInt32(setOutputFile(path));
             return NO_ERROR;
         } break;
+        case SET_OUTPUT_FILE_FD: {
+            LOGV("SET_OUTPUT_FILE_FD");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            int fd = dup(data.readFileDescriptor());
+            int64_t offset = data.readInt64();
+            int64_t length = data.readInt64();
+            reply->writeInt32(setOutputFile(fd, offset, length));
+            return NO_ERROR;
+        } break;
         case SET_VIDEO_SIZE: {
             LOGV("SET_VIDEO_SIZE");
             CHECK_INTERFACE(IMediaRecorder, data, reply);
diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp
index ead24d497f23..9bd75c29ddf9 100644
--- a/media/libmedia/JetPlayer.cpp
+++ b/media/libmedia/JetPlayer.cpp
@@ -96,7 +96,7 @@ int JetPlayer::init()
 
     // create the output AudioTrack
     mAudioTrack = new AudioTrack();
-    mAudioTrack->set(AudioTrack::MUSIC,  //TODO parametrize this
+    mAudioTrack->set(AudioSystem::MUSIC,  //TODO parametrize this
             pLibConfig->sampleRate,
             1, // format = PCM 16bits per sample,
             pLibConfig->numChannels,
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index fa36460a77a0..7fafc562894e 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -93,7 +93,7 @@ ToneGenerator::ToneGenerator(int streamType, float volume) {
 
     mState = TONE_IDLE;
 
-    if (AudioSystem::getOutputSamplingRate(&mSamplingRate) != NO_ERROR) {
+    if (AudioSystem::getOutputSamplingRate(&mSamplingRate, streamType) != NO_ERROR) {
         LOGE("Unable to marshal AudioFlinger");
         return;
     }
@@ -182,7 +182,7 @@ bool ToneGenerator::startTone(int toneType) {
             mLock.lock();
             if (mState == TONE_STARTING) {
                 if (mWaitCbkCond.waitRelative(mLock, seconds(1)) != NO_ERROR) {
-                    LOGE("--- timed out");
+                    LOGE("--- Immediate start timed out");
                     mState = TONE_IDLE;
                 }
             }
@@ -200,7 +200,7 @@ bool ToneGenerator::startTone(int toneType) {
             }
             LOGV("cond received");
         } else {
-            LOGE("--- timed out");
+            LOGE("--- Delayed start timed out");
             mState = TONE_IDLE;
         }
     }
@@ -235,7 +235,7 @@ void ToneGenerator::stopTone() {
         if (lStatus == NO_ERROR) {
             LOGV("track stop complete, time %d", (unsigned int)(systemTime()/1000000));
         } else {
-            LOGE("--- timed out");
+            LOGE("--- Stop timed out");
             mState = TONE_IDLE;
             mpAudioTrack->stop();
         }
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 31ff50730d7e..bd8579ca8d84 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -82,7 +82,7 @@ MediaPlayer::MediaPlayer()
     mListener = NULL;
     mCookie = NULL;
     mDuration = -1;
-    mStreamType = AudioTrack::MUSIC;
+    mStreamType = AudioSystem::MUSIC;
     mCurrentPosition = -1;
     mSeekPosition = -1;
     mCurrentState = MEDIA_PLAYER_IDLE;
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 6ee4c0d45ef2..4ab26ac0c384 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -248,7 +248,33 @@ status_t MediaRecorder::setOutputFile(const char* path)
 
     status_t ret = mMediaRecorder->setOutputFile(path);
     if (OK != ret) {
-        LOGV("setAudioEncoder failed: %d", ret);
+        LOGV("setOutputFile failed: %d", ret);
+        mCurrentState = MEDIA_RECORDER_ERROR;
+        return UNKNOWN_ERROR;
+    }
+    mIsOutputFileSet = true;
+    return ret;
+}
+
+status_t MediaRecorder::setOutputFile(int fd, int64_t offset, int64_t length)
+{
+    LOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length);
+    if(mMediaRecorder == NULL) {
+        LOGE("media recorder is not initialized yet");
+        return INVALID_OPERATION;
+    }
+    if (mIsOutputFileSet) {
+        LOGE("output file has already been set");
+        return INVALID_OPERATION;
+    }
+    if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
+        LOGE("setOutputFile called in an invalid state(%d)", mCurrentState);
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mMediaRecorder->setOutputFile(fd, offset, length);
+    if (OK != ret) {
+        LOGV("setOutputFile failed: %d", ret);
         mCurrentState = MEDIA_RECORDER_ERROR;
         return UNKNOWN_ERROR;
     }
@@ -306,7 +332,7 @@ status_t MediaRecorder::prepare()
         return INVALID_OPERATION;
     }
     if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) {
-        LOGE("setVideoFrameRate called in an invalid state: %d", mCurrentState);
+        LOGE("prepare called in an invalid state: %d", mCurrentState);
         return INVALID_OPERATION;
     }
 
@@ -328,7 +354,7 @@ status_t MediaRecorder::getMaxAmplitude(int* max)
         return INVALID_OPERATION;
     }
     if (mCurrentState & MEDIA_RECORDER_ERROR) {
-        LOGE("setVideoFrameRate called in an invalid state: %d", mCurrentState);
+        LOGE("getMaxAmplitude called in an invalid state: %d", mCurrentState);
         return INVALID_OPERATION;
     }
 
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 9e366e2660aa..97e353653c64 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -818,7 +818,7 @@ Exit:
 MediaPlayerService::AudioOutput::AudioOutput()
 {
     mTrack = 0;
-    mStreamType = AudioTrack::MUSIC;
+    mStreamType = AudioSystem::MUSIC;
     mLeftVolume = 1.0;
     mRightVolume = 1.0;
     mLatency = 0;
@@ -900,15 +900,15 @@ status_t MediaPlayerService::AudioOutput::open(uint32_t sampleRate, int channelC
     int afFrameCount;
     int frameCount;
 
-    if (AudioSystem::getOutputFrameCount(&afFrameCount) != NO_ERROR) {
+    if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) {
         return NO_INIT;
     }
-    if (AudioSystem::getOutputSamplingRate(&afSampleRate) != NO_ERROR) {
+    if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) {
         return NO_INIT;
     }
 
-    frameCount = (sampleRate*afFrameCount)/afSampleRate;
-    AudioTrack *t = new AudioTrack(mStreamType, sampleRate, format, channelCount, frameCount*bufferCount);
+    frameCount = (sampleRate*afFrameCount*bufferCount)/afSampleRate;
+    AudioTrack *t = new AudioTrack(mStreamType, sampleRate, format, channelCount, frameCount);
     if ((t == 0) || (t->initCheck() != NO_ERROR)) {
         LOGE("Unable to create audio track");
         delete t;
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index f326a0e3af1c..e8ba17f86750 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -121,6 +121,17 @@ status_t MediaRecorderClient::setOutputFile(const char* path)
     return mRecorder->setOutputFile(path);
 }
 
+status_t MediaRecorderClient::setOutputFile(int fd, int64_t offset, int64_t length)
+{
+    LOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length);
+    Mutex::Autolock lock(mLock);
+    if (mRecorder == NULL) {
+        LOGE("recorder is not initialized");
+        return NO_INIT;
+    }
+    return mRecorder->setOutputFile(fd, offset, length);
+}
+
 status_t MediaRecorderClient::setVideoSize(int width, int height)
 {
     LOGV("setVideoSize(%dx%d)", width, height);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 3158017ba7fa..2b80c10056ff 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -36,6 +36,7 @@ public:
     virtual     status_t        setVideoEncoder(int ve);
     virtual     status_t        setAudioEncoder(int ae);
     virtual     status_t        setOutputFile(const char* path);
+    virtual     status_t        setOutputFile(int fd, int64_t offset, int64_t length);
     virtual     status_t        setVideoSize(int width, int height);
     virtual     status_t        setVideoFrameRate(int frames_per_second);
     virtual     status_t        prepare();
diff --git a/media/libmediaplayerservice/MidiFile.cpp b/media/libmediaplayerservice/MidiFile.cpp
index 7ce2fab041e0..d03caa5e5d9f 100644
--- a/media/libmediaplayerservice/MidiFile.cpp
+++ b/media/libmediaplayerservice/MidiFile.cpp
@@ -58,7 +58,7 @@ static const S_EAS_LIB_CONFIG* pLibConfig = NULL;
 MidiFile::MidiFile() :
     mEasData(NULL), mEasHandle(NULL), mAudioBuffer(NULL),
     mPlayTime(-1), mDuration(-1), mState(EAS_STATE_ERROR),
-    mStreamType(AudioTrack::MUSIC), mLoop(false), mExit(false),
+    mStreamType(AudioSystem::MUSIC), mLoop(false), mExit(false),
     mPaused(false), mRender(false), mTid(-1)
 {
     LOGV("constructor");
diff --git a/media/libmediaplayerservice/VorbisPlayer.cpp b/media/libmediaplayerservice/VorbisPlayer.cpp
index 009d6286a0f3..0ad335f84d10 100644
--- a/media/libmediaplayerservice/VorbisPlayer.cpp
+++ b/media/libmediaplayerservice/VorbisPlayer.cpp
@@ -55,7 +55,7 @@ static status_t STATE_OPEN = 2;
 
 VorbisPlayer::VorbisPlayer() :
     mAudioBuffer(NULL), mPlayTime(-1), mDuration(-1), mState(STATE_ERROR),
-    mStreamType(AudioTrack::MUSIC), mLoop(false), mAndroidLoop(false),
+    mStreamType(AudioSystem::MUSIC), mLoop(false), mAndroidLoop(false),
     mExit(false), mPaused(false), mRender(false), mRenderTid(-1)
 {
     LOGV("constructor\n");
diff --git a/preloaded-classes b/preloaded-classes
index 1ace628942e8..61390db126ba 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -340,7 +340,7 @@ android.view.TouchDelegate
 android.view.VelocityTracker
 android.view.View
 android.view.View$AttachInfo
-android.view.View$AttachInfo$SoundEffectPlayer
+android.view.View$AttachInfo$Callbacks
 android.view.View$BaseSavedState$1
 android.view.View$MeasureSpec
 android.view.View$ScrollabilityCache
diff --git a/services/java/com/android/server/GadgetService.java b/services/java/com/android/server/GadgetService.java
index 5ef0fb9f38a9..ddf3afef1786 100644
--- a/services/java/com/android/server/GadgetService.java
+++ b/services/java/com/android/server/GadgetService.java
@@ -31,9 +31,10 @@ import android.content.pm.PackageItemInfo;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.gadget.GadgetManager;
-import android.gadget.GadgetInfo;
+import android.gadget.GadgetProviderInfo;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.util.AttributeSet;
@@ -78,7 +79,7 @@ class GadgetService extends IGadgetService.Stub
 
     static class Provider {
         int uid;
-        GadgetInfo info;
+        GadgetProviderInfo info;
         ArrayList<GadgetId> instances = new ArrayList();
         PendingIntent broadcast;
         
@@ -106,7 +107,7 @@ class GadgetService extends IGadgetService.Stub
     PackageManager mPackageManager;
     AlarmManager mAlarmManager;
     ArrayList<Provider> mInstalledProviders = new ArrayList();
-    int mNextGadgetId = 1;
+    int mNextGadgetId = GadgetManager.INVALID_GADGET_ID + 1;
     ArrayList<GadgetId> mGadgetIds = new ArrayList();
     ArrayList<Host> mHosts = new ArrayList();
 
@@ -128,7 +129,6 @@ class GadgetService extends IGadgetService.Stub
         // update the provider list.
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_PACKAGE_ADDED);
-        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
         filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
         filter.addDataScheme("package");
         mContext.registerReceiver(mBroadcastReceiver, filter);
@@ -148,7 +148,7 @@ class GadgetService extends IGadgetService.Stub
             int N = mInstalledProviders.size();
             pw.println("Providers: (size=" + N + ")");
             for (int i=0; i<N; i++) {
-                GadgetInfo info = mInstalledProviders.get(i).info;
+                GadgetProviderInfo info = mInstalledProviders.get(i).info;
                 pw.println("  [" + i + "] provder=" + info.provider
                         + " min=(" + info.minWidth + "x" + info.minHeight + ")"
                         + " updatePeriodMillis=" + info.updatePeriodMillis
@@ -265,7 +265,7 @@ class GadgetService extends IGadgetService.Stub
         if (p != null) {
             p.instances.remove(id);
             // send the broacast saying that this gadgetId has been deleted
-            Intent intent = new Intent(GadgetManager.GADGET_DELETED_ACTION);
+            Intent intent = new Intent(GadgetManager.ACTION_GADGET_DELETED);
             intent.setComponent(p.info.provider);
             intent.putExtra(GadgetManager.EXTRA_GADGET_ID, id.gadgetId);
             mContext.sendBroadcast(intent);
@@ -274,7 +274,7 @@ class GadgetService extends IGadgetService.Stub
                 cancelBroadcasts(p);
 
                 // send the broacast saying that the provider is not in use any more
-                intent = new Intent(GadgetManager.GADGET_DISABLED_ACTION);
+                intent = new Intent(GadgetManager.ACTION_GADGET_DISABLED);
                 intent.setComponent(p.info.provider);
                 mContext.sendBroadcast(intent);
             }
@@ -331,7 +331,7 @@ class GadgetService extends IGadgetService.Stub
         }
     }
 
-    public GadgetInfo getGadgetInfo(int gadgetId) {
+    public GadgetProviderInfo getGadgetInfo(int gadgetId) {
         synchronized (mGadgetIds) {
             GadgetId id = lookupGadgetIdLocked(gadgetId);
             if (id != null) {
@@ -351,10 +351,10 @@ class GadgetService extends IGadgetService.Stub
         }
     }
 
-    public List<GadgetInfo> getInstalledProviders() {
+    public List<GadgetProviderInfo> getInstalledProviders() {
         synchronized (mGadgetIds) {
             final int N = mInstalledProviders.size();
-            ArrayList<GadgetInfo> result = new ArrayList(N);
+            ArrayList<GadgetProviderInfo> result = new ArrayList(N);
             for (int i=0; i<N; i++) {
                 result.add(mInstalledProviders.get(i).info);
             }
@@ -364,7 +364,7 @@ class GadgetService extends IGadgetService.Stub
 
     public void updateGadgetIds(int[] gadgetIds, RemoteViews views) {
         if (gadgetIds == null) {
-            throw new IllegalArgumentException("bad gadgetIds");
+            return;
         }
         if (gadgetIds.length == 0) {
             return;
@@ -408,7 +408,7 @@ class GadgetService extends IGadgetService.Stub
                     // the lock is held, but this is a oneway call
                     id.host.callbacks.updateGadget(id.gadgetId, views);
                 } catch (RemoteException e) {
-                    // It failed, remove the callback. No need to prune because
+                    // It failed; remove the callback. No need to prune because
                     // we know that this host is still referenced by this instance.
                     id.host.callbacks = null;
                 }
@@ -524,10 +524,7 @@ class GadgetService extends IGadgetService.Stub
     void getGadgetList() {
         PackageManager pm = mPackageManager;
 
-        // TODO: We have these as different actions.  I wonder if it makes more sense to
-        // have like a GADGET_ACTION, and then subcommands.  It's kind of arbitrary that
-        // we look for GADGET_UPDATE_ACTION and not any of the other gadget actions.
-        Intent intent = new Intent(GadgetManager.GADGET_UPDATE_ACTION);
+        Intent intent = new Intent(GadgetManager.ACTION_GADGET_UPDATE);
         List<ResolveInfo> broadcastReceivers = pm.queryBroadcastReceivers(intent,
                 PackageManager.GET_META_DATA);
 
@@ -538,11 +535,14 @@ class GadgetService extends IGadgetService.Stub
         }
     }
 
-    void addProviderLocked(ResolveInfo ri) {
-        Provider p = parseGadgetInfoXml(new ComponentName(ri.activityInfo.packageName,
+    boolean addProviderLocked(ResolveInfo ri) {
+        Provider p = parseProviderInfoXml(new ComponentName(ri.activityInfo.packageName,
                     ri.activityInfo.name), ri);
         if (p != null) {
             mInstalledProviders.add(p);
+            return true;
+        } else {
+            return false;
         }
     }
 
@@ -568,16 +568,18 @@ class GadgetService extends IGadgetService.Stub
     }
 
     void sendEnableIntentLocked(Provider p) {
-        Intent intent = new Intent(GadgetManager.GADGET_ENABLED_ACTION);
+        Intent intent = new Intent(GadgetManager.ACTION_GADGET_ENABLED);
         intent.setComponent(p.info.provider);
         mContext.sendBroadcast(intent);
     }
 
     void sendUpdateIntentLocked(Provider p, int[] gadgetIds) {
-        Intent intent = new Intent(GadgetManager.GADGET_UPDATE_ACTION);
-        intent.putExtra(GadgetManager.EXTRA_GADGET_IDS, gadgetIds);
-        intent.setComponent(p.info.provider);
-        mContext.sendBroadcast(intent);
+        if (gadgetIds != null && gadgetIds.length > 0) {
+            Intent intent = new Intent(GadgetManager.ACTION_GADGET_UPDATE);
+            intent.putExtra(GadgetManager.EXTRA_GADGET_IDS, gadgetIds);
+            intent.setComponent(p.info.provider);
+            mContext.sendBroadcast(intent);
+        }
     }
 
     void registerForBroadcastsLocked(Provider p, int[] gadgetIds) {
@@ -587,7 +589,7 @@ class GadgetService extends IGadgetService.Stub
             // PendingIntent.getBroadcast will update the extras.
             boolean alreadyRegistered = p.broadcast != null;
             int instancesSize = p.instances.size();
-            Intent intent = new Intent(GadgetManager.GADGET_UPDATE_ACTION);
+            Intent intent = new Intent(GadgetManager.ACTION_GADGET_UPDATE);
             intent.putExtra(GadgetManager.EXTRA_GADGET_IDS, gadgetIds);
             intent.setComponent(p.info.provider);
             long token = Binder.clearCallingIdentity();
@@ -614,16 +616,16 @@ class GadgetService extends IGadgetService.Stub
         return gadgetIds;
     }
 
-    private Provider parseGadgetInfoXml(ComponentName component, ResolveInfo ri) {
+    private Provider parseProviderInfoXml(ComponentName component, ResolveInfo ri) {
         Provider p = null;
 
         ActivityInfo activityInfo = ri.activityInfo;
         XmlResourceParser parser = null;
         try {
             parser = activityInfo.loadXmlMetaData(mPackageManager,
-                    GadgetManager.GADGET_PROVIDER_META_DATA);
+                    GadgetManager.META_DATA_GADGET_PROVIDER);
             if (parser == null) {
-                Log.w(TAG, "No " + GadgetManager.GADGET_PROVIDER_META_DATA + " meta-data for "
+                Log.w(TAG, "No " + GadgetManager.META_DATA_GADGET_PROVIDER + " meta-data for "
                         + "gadget provider '" + component + '\'');
                 return null;
             }
@@ -644,7 +646,7 @@ class GadgetService extends IGadgetService.Stub
             }
 
             p = new Provider();
-            GadgetInfo info = p.info = new GadgetInfo();
+            GadgetProviderInfo info = p.info = new GadgetProviderInfo();
 
             info.provider = component;
             p.uid = activityInfo.applicationInfo.uid;
@@ -672,6 +674,7 @@ class GadgetService extends IGadgetService.Stub
             // of what a client process passes to us should not be fatal for the
             // system process.
             Log.w(TAG, "XML parsing failed for gadget provider '" + component + '\'', e);
+            return null;
         } finally {
             if (parser != null) parser.close();
         }
@@ -979,20 +982,26 @@ class GadgetService extends IGadgetService.Stub
                 
                 if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
                     synchronized (mGadgetIds) {
-                        addProvidersForPackageLocked(pkgName);
-                        saveStateLocked();
-                    }
-                }
-                else if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
-                    synchronized (mGadgetIds) {
-                        updateProvidersForPackageLocked(pkgName);
+                        Bundle extras = intent.getExtras();
+                        if (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false)) {
+                            // The package was just upgraded
+                            updateProvidersForPackageLocked(pkgName);
+                        } else {
+                            // The package was just added
+                            addProvidersForPackageLocked(pkgName);
+                        }
                         saveStateLocked();
                     }
                 }
                 else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
-                    synchronized (mGadgetIds) {
-                        removeProvidersForPackageLocked(pkgName);
-                        saveStateLocked();
+                    Bundle extras = intent.getExtras();
+                    if (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false)) {
+                        // The package is being updated.  We'll receive a PACKAGE_ADDED shortly.
+                    } else {
+                        synchronized (mGadgetIds) {
+                            removeProvidersForPackageLocked(pkgName);
+                            saveStateLocked();
+                        }
                     }
                 }
             }
@@ -1002,7 +1011,7 @@ class GadgetService extends IGadgetService.Stub
     // TODO: If there's a better way of matching an intent filter against the
     // packages for a given package, use that.
     void addProvidersForPackageLocked(String pkgName) {
-        Intent intent = new Intent(GadgetManager.GADGET_UPDATE_ACTION);
+        Intent intent = new Intent(GadgetManager.ACTION_GADGET_UPDATE);
         List<ResolveInfo> broadcastReceivers = mPackageManager.queryBroadcastReceivers(intent,
                 PackageManager.GET_META_DATA);
 
@@ -1021,7 +1030,7 @@ class GadgetService extends IGadgetService.Stub
     // packages for a given package, use that.
     void updateProvidersForPackageLocked(String pkgName) {
         HashSet<String> keep = new HashSet();
-        Intent intent = new Intent(GadgetManager.GADGET_UPDATE_ACTION);
+        Intent intent = new Intent(GadgetManager.ACTION_GADGET_UPDATE);
         List<ResolveInfo> broadcastReceivers = mPackageManager.queryBroadcastReceivers(intent,
                 PackageManager.GET_META_DATA);
 
@@ -1031,17 +1040,53 @@ class GadgetService extends IGadgetService.Stub
             ResolveInfo ri = broadcastReceivers.get(i);
             ActivityInfo ai = ri.activityInfo;
             if (pkgName.equals(ai.packageName)) {
-                Provider p = lookupProviderLocked(new ComponentName(ai.packageName, ai.name));
+                ComponentName component = new ComponentName(ai.packageName, ai.name);
+                Provider p = lookupProviderLocked(component);
                 if (p == null) {
-                    addProviderLocked(ri);
+                    if (addProviderLocked(ri)) {
+                        keep.add(ai.name);
+                    }
+                } else {
+                    Provider parsed = parseProviderInfoXml(component, ri);
+                    if (parsed != null) {
+                        keep.add(ai.name);
+                        // Use the new GadgetProviderInfo.
+                        GadgetProviderInfo oldInfo = p.info;
+                        p.info = parsed.info;
+                        // If it's enabled
+                        final int M = p.instances.size();
+                        if (M > 0) {
+                            int[] gadgetIds = getGadgetIds(p);
+                            // Reschedule for the new updatePeriodMillis (don't worry about handling
+                            // it specially if updatePeriodMillis didn't change because we just sent
+                            // an update, and the next one will be updatePeriodMillis from now).
+                            cancelBroadcasts(p);
+                            registerForBroadcastsLocked(p, gadgetIds);
+                            // If it's currently showing, call back with the new GadgetProviderInfo.
+                            for (int j=0; j<M; j++) {
+                                GadgetId id = p.instances.get(j);
+                                if (id.host != null && id.host.callbacks != null) {
+                                    try {
+                                        id.host.callbacks.providerChanged(id.gadgetId, p.info);
+                                    } catch (RemoteException ex) {
+                                        // It failed; remove the callback. No need to prune because
+                                        // we know that this host is still referenced by this
+                                        // instance.
+                                        id.host.callbacks = null;
+                                    }
+                                }
+                            }
+                            // Now that we've told the host, push out an update.
+                            sendUpdateIntentLocked(p, gadgetIds);
+                        }
+                    }
                 }
-                keep.add(ai.name);
             }
         }
 
         // prune the ones we don't want to keep
         N = mInstalledProviders.size();
-        for (int i=0; i<N; i++) {
+        for (int i=N-1; i>=0; i--) {
             Provider p = mInstalledProviders.get(i);
             if (pkgName.equals(p.info.provider.getPackageName())
                     && !keep.contains(p.info.provider.getClassName())) {
@@ -1052,7 +1097,7 @@ class GadgetService extends IGadgetService.Stub
 
     void removeProvidersForPackageLocked(String pkgName) {
         int N = mInstalledProviders.size();
-        for (int i=0; i<N; i++) {
+        for (int i=N-1; i>=0; i--) {
             Provider p = mInstalledProviders.get(i);
             if (pkgName.equals(p.info.provider.getPackageName())) {
                 removeProviderLocked(i, p);
@@ -1064,7 +1109,7 @@ class GadgetService extends IGadgetService.Stub
         // By now, we have removed any gadgets that were in any hosts here,
         // so we don't need to worry about sending DISABLE broadcasts to them.
         N = mHosts.size();
-        for (int i=0; i<N; i++) {
+        for (int i=N-1; i>=0; i--) {
             Host host = mHosts.get(i);
             if (pkgName.equals(host.packageName)) {
                 deleteHostLocked(host);
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index ee49365324fa..758812920ee2 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -55,8 +55,10 @@ import android.os.Message;
 import android.os.Parcel;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemClock;
 import android.provider.Settings;
 import android.text.TextUtils;
+import android.util.EventLog;
 import android.util.Log;
 import android.util.PrintWriterPrinter;
 import android.util.Printer;
@@ -98,6 +100,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
     static final int MSG_UNBIND_METHOD = 3000;
     static final int MSG_BIND_METHOD = 3010;
     
+    static final long TIME_TO_RECONNECT = 10*1000;
+    
+    static final int LOG_IMF_FORCE_RECONNECT_IME = 32000;
+    
     final Context mContext;
     final Handler mHandler;
     final SettingsObserver mSettingsObserver;
@@ -247,6 +253,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
      */
     IInputMethod mCurMethod;
     
+    /**
+     * Time that we last initiated a bind to the input method, to determine
+     * if we should try to disconnect and reconnect to it.
+     */
+    long mLastBindTime;
+    
     /**
      * Have we called mCurMethod.bindInput()?
      */
@@ -486,7 +498,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
     }
 
     public void systemReady() {
-        
     }
     
     public List<InputMethodInfo> getInputMethodList() {
@@ -571,7 +582,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
         }
     }
     
-    private int getShowFlags() {
+    private int getImeShowFlags() {
         int flags = 0;
         if (mShowForced) {
             flags |= InputMethod.SHOW_FORCED
@@ -582,6 +593,16 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
         return flags;
     }
     
+    private int getAppShowFlags() {
+        int flags = 0;
+        if (mShowForced) {
+            flags |= InputMethodManager.SHOW_FORCED;
+        } else if (!mShowExplicitlyRequested) {
+            flags |= InputMethodManager.SHOW_IMPLICIT;
+        }
+        return flags;
+    }
+    
     InputBindResult attachNewInputLocked(boolean initial, boolean needResult) {
         if (!mBoundToMethod) {
             executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
@@ -598,7 +619,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
         }
         if (mShowRequested) {
             if (DEBUG) Log.v(TAG, "Attach new input asks to show input");
-            showCurrentInputLocked(getShowFlags());
+            showCurrentInputLocked(getAppShowFlags());
         }
         return needResult
                 ? new InputBindResult(session.session, mCurId, mCurSeq)
@@ -666,14 +687,31 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
                 return attachNewInputLocked(initial, needResult);
             }
             if (mHaveConnection) {
-                if (mCurMethod != null && !cs.sessionRequested) {
-                    cs.sessionRequested = true;
-                    if (DEBUG) Log.v(TAG, "Creating new session for client " + cs);
-                    executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
-                            MSG_CREATE_SESSION, mCurMethod,
-                            new MethodCallback(mCurMethod)));
+                if (mCurMethod != null) {
+                    if (!cs.sessionRequested) {
+                        cs.sessionRequested = true;
+                        if (DEBUG) Log.v(TAG, "Creating new session for client " + cs);
+                        executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
+                                MSG_CREATE_SESSION, mCurMethod,
+                                new MethodCallback(mCurMethod)));
+                    }
+                    // Return to client, and we will get back with it when
+                    // we have had a session made for it.
+                    return new InputBindResult(null, mCurId, mCurSeq);
+                } else if (SystemClock.uptimeMillis()
+                        < (mLastBindTime+TIME_TO_RECONNECT)) {
+                    // In this case we have connected to the service, but
+                    // don't yet have its interface.  If it hasn't been too
+                    // long since we did the connection, we'll return to
+                    // the client and wait to get the service interface so
+                    // we can report back.  If it has been too long, we want
+                    // to fall through so we can try a disconnect/reconnect
+                    // to see if we can get back in touch with the service.
+                    return new InputBindResult(null, mCurId, mCurSeq);
+                } else {
+                    EventLog.writeEvent(LOG_IMF_FORCE_RECONNECT_IME, mCurMethodId,
+                            SystemClock.uptimeMillis()-mLastBindTime, 0);
                 }
-                return new InputBindResult(null, mCurId, mCurSeq);
             }
         }
         
@@ -682,6 +720,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
             throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
         }
         
+        if (mHaveConnection) {
+            mContext.unbindService(this);
+            mHaveConnection = false;
+        }
+        
         if (mCurToken != null) {
             try {
                 if (DEBUG) Log.v(TAG, "Removing window token: " + mCurToken);
@@ -691,16 +734,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
             mCurToken = null;
         }
         
-        if (mHaveConnection) {
-            mContext.unbindService(this);
-            mHaveConnection = false;
-        }
-        
         clearCurMethod();
         
         mCurIntent = new Intent(InputMethod.SERVICE_INTERFACE);
         mCurIntent.setComponent(info.getComponent());
         if (mContext.bindService(mCurIntent, this, Context.BIND_AUTO_CREATE)) {
+            mLastBindTime = SystemClock.uptimeMillis();
             mHaveConnection = true;
             mCurId = info.getId();
             mCurToken = new Binder();
@@ -758,7 +797,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
 
     void onSessionCreated(IInputMethod method, IInputMethodSession session) {
         synchronized (mMethodMap) {
-            if (mCurMethod == method) {
+            if (mCurMethod != null && method != null
+                    && mCurMethod.asBinder() == method.asBinder()) {
                 if (mCurClient != null) {
                     mCurClient.curSession = new SessionState(mCurClient,
                             method, session);
@@ -781,6 +821,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
             }
             mCurMethod = null;
         }
+        mStatusBar.setIconVisibility(mInputMethodIcon, false);
     }
     
     public void onServiceDisconnected(ComponentName name) {
@@ -790,6 +831,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
             if (mCurMethod != null && mCurIntent != null
                     && name.equals(mCurIntent.getComponent())) {
                 clearCurMethod();
+                // We consider this to be a new bind attempt, since the system
+                // should now try to restart the service for us.
+                mLastBindTime = SystemClock.uptimeMillis();
                 mShowRequested = mInputShown;
                 mInputShown = false;
                 if (mCurClient != null) {
@@ -800,23 +844,28 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
         }
     }
 
-    public void updateStatusIcon(int iconId, String iconPackage) {
-        if (iconId == 0) {
-            Log.d(TAG, "hide the small icon for the input method");
-            mStatusBar.setIconVisibility(mInputMethodIcon, false);
-        } else {
-            Log.d(TAG, "show a small icon for the input method");
-
-            if (iconPackage != null
-                    && iconPackage
-                            .equals(InputMethodManager.BUILDIN_INPUTMETHOD_PACKAGE)) {
-                iconPackage = null;
+    public void updateStatusIcon(IBinder token, String packageName, int iconId) {
+        long ident = Binder.clearCallingIdentity();
+        try {
+            if (token == null || mCurToken != token) {
+                Log.w(TAG, "Ignoring setInputMethod of token: " + token);
+                return;
             }
-
-            mInputMethodData.iconId = iconId;
-            mInputMethodData.iconPackage = iconPackage;
-            mStatusBar.updateIcon(mInputMethodIcon, mInputMethodData, null);
-            mStatusBar.setIconVisibility(mInputMethodIcon, true);
+            
+            synchronized (mMethodMap) {
+                if (iconId == 0) {
+                    if (DEBUG) Log.d(TAG, "hide the small icon for the input method");
+                    mStatusBar.setIconVisibility(mInputMethodIcon, false);
+                } else if (packageName != null) {
+                    if (DEBUG) Log.d(TAG, "show a small icon for the input method");
+                    mInputMethodData.iconId = iconId;
+                    mInputMethodData.iconPackage = packageName;
+                    mStatusBar.updateIcon(mInputMethodIcon, mInputMethodData, null);
+                    mStatusBar.setIconVisibility(mInputMethodIcon, true);
+                }
+            }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
     }
 
@@ -860,23 +909,28 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
     }
     
     public void showSoftInput(IInputMethodClient client, int flags) {
-        synchronized (mMethodMap) {
-            if (mCurClient == null || client == null
-                    || mCurClient.client.asBinder() != client.asBinder()) {
-                try {
-                    // We need to check if this is the current client with
-                    // focus in the window manager, to allow this call to
-                    // be made before input is started in it.
-                    if (!mIWindowManager.inputMethodClientHasFocus(client)) {
-                        Log.w(TAG, "Ignoring showSoftInput of: " + client);
-                        return;
+        long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized (mMethodMap) {
+                if (mCurClient == null || client == null
+                        || mCurClient.client.asBinder() != client.asBinder()) {
+                    try {
+                        // We need to check if this is the current client with
+                        // focus in the window manager, to allow this call to
+                        // be made before input is started in it.
+                        if (!mIWindowManager.inputMethodClientHasFocus(client)) {
+                            Log.w(TAG, "Ignoring showSoftInput of: " + client);
+                            return;
+                        }
+                    } catch (RemoteException e) {
                     }
-                } catch (RemoteException e) {
                 }
+    
+                if (DEBUG) Log.v(TAG, "Client requesting input be shown");
+                showCurrentInputLocked(flags);
             }
-
-            if (DEBUG) Log.v(TAG, "Client requesting input be shown");
-            showCurrentInputLocked(flags);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
     }
     
@@ -891,29 +945,44 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
         }
         if (mCurMethod != null) {
             executeOrSendMessage(mCurMethod, mCaller.obtainMessageIO(
-                    MSG_SHOW_SOFT_INPUT, getShowFlags(), mCurMethod));
+                    MSG_SHOW_SOFT_INPUT, getImeShowFlags(), mCurMethod));
             mInputShown = true;
+        } else if (mHaveConnection && SystemClock.uptimeMillis()
+                < (mLastBindTime+TIME_TO_RECONNECT)) {
+            // The client has asked to have the input method shown, but
+            // we have been sitting here too long with a connection to the
+            // service and no interface received, so let's disconnect/connect
+            // to try to prod things along.
+            EventLog.writeEvent(LOG_IMF_FORCE_RECONNECT_IME, mCurMethodId,
+                    SystemClock.uptimeMillis()-mLastBindTime,1);
+            mContext.unbindService(this);
+            mContext.bindService(mCurIntent, this, Context.BIND_AUTO_CREATE);
         }
     }
     
     public void hideSoftInput(IInputMethodClient client, int flags) {
-        synchronized (mMethodMap) {
-            if (mCurClient == null || client == null
-                    || mCurClient.client.asBinder() != client.asBinder()) {
-                try {
-                    // We need to check if this is the current client with
-                    // focus in the window manager, to allow this call to
-                    // be made before input is started in it.
-                    if (!mIWindowManager.inputMethodClientHasFocus(client)) {
-                        Log.w(TAG, "Ignoring hideSoftInput of: " + client);
-                        return;
+        long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized (mMethodMap) {
+                if (mCurClient == null || client == null
+                        || mCurClient.client.asBinder() != client.asBinder()) {
+                    try {
+                        // We need to check if this is the current client with
+                        // focus in the window manager, to allow this call to
+                        // be made before input is started in it.
+                        if (!mIWindowManager.inputMethodClientHasFocus(client)) {
+                            Log.w(TAG, "Ignoring hideSoftInput of: " + client);
+                            return;
+                        }
+                    } catch (RemoteException e) {
                     }
-                } catch (RemoteException e) {
                 }
+    
+                if (DEBUG) Log.v(TAG, "Client requesting input be hidden");
+                hideCurrentInputLocked(flags);
             }
-
-            if (DEBUG) Log.v(TAG, "Client requesting input be hidden");
-            hideCurrentInputLocked(flags);
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
     }
     
@@ -942,70 +1011,75 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
     public void windowGainedFocus(IInputMethodClient client,
             boolean viewHasFocus, boolean isTextEditor, int softInputMode,
             boolean first, int windowFlags) {
-        synchronized (mMethodMap) {
-            if (DEBUG) Log.v(TAG, "windowGainedFocus: " + client.asBinder()
-                    + " viewHasFocus=" + viewHasFocus
-                    + " isTextEditor=" + isTextEditor
-                    + " softInputMode=#" + Integer.toHexString(softInputMode)
-                    + " first=" + first + " flags=#"
-                    + Integer.toHexString(windowFlags));
-            
-            if (mCurClient == null || client == null
-                    || mCurClient.client.asBinder() != client.asBinder()) {
-                try {
-                    // We need to check if this is the current client with
-                    // focus in the window manager, to allow this call to
-                    // be made before input is started in it.
-                    if (!mIWindowManager.inputMethodClientHasFocus(client)) {
-                        Log.w(TAG, "Ignoring focus gain of: " + client);
-                        return;
+        long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized (mMethodMap) {
+                if (DEBUG) Log.v(TAG, "windowGainedFocus: " + client.asBinder()
+                        + " viewHasFocus=" + viewHasFocus
+                        + " isTextEditor=" + isTextEditor
+                        + " softInputMode=#" + Integer.toHexString(softInputMode)
+                        + " first=" + first + " flags=#"
+                        + Integer.toHexString(windowFlags));
+                
+                if (mCurClient == null || client == null
+                        || mCurClient.client.asBinder() != client.asBinder()) {
+                    try {
+                        // We need to check if this is the current client with
+                        // focus in the window manager, to allow this call to
+                        // be made before input is started in it.
+                        if (!mIWindowManager.inputMethodClientHasFocus(client)) {
+                            Log.w(TAG, "Ignoring focus gain of: " + client);
+                            return;
+                        }
+                    } catch (RemoteException e) {
                     }
-                } catch (RemoteException e) {
                 }
-            }
-
-            switch (softInputMode&WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE) {
-                case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED:
-                    if (!isTextEditor || (softInputMode &
-                            WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
-                            != WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) {
-                        if (WindowManager.LayoutParams.mayUseInputMethod(windowFlags)) {
-                            // There is no focus view, and this window will
-                            // be behind any soft input window, so hide the
-                            // soft input window if it is shown.
-                            if (DEBUG) Log.v(TAG, "Unspecified window will hide input");
-                            hideCurrentInputLocked(InputMethodManager.HIDE_NOT_ALWAYS);
+    
+                switch (softInputMode&WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE) {
+                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED:
+                        if (!isTextEditor || (softInputMode &
+                                WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
+                                != WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) {
+                            if (WindowManager.LayoutParams.mayUseInputMethod(windowFlags)) {
+                                // There is no focus view, and this window will
+                                // be behind any soft input window, so hide the
+                                // soft input window if it is shown.
+                                if (DEBUG) Log.v(TAG, "Unspecified window will hide input");
+                                hideCurrentInputLocked(InputMethodManager.HIDE_NOT_ALWAYS);
+                            }
+                        } else if (isTextEditor && (softInputMode &
+                                WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
+                                == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
+                                && (softInputMode &
+                                        WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
+                            // There is a focus view, and we are navigating forward
+                            // into the window, so show the input window for the user.
+                            if (DEBUG) Log.v(TAG, "Unspecified window will show input");
+                            showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT);
                         }
-                    } else if (isTextEditor && (softInputMode &
-                            WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
-                            == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
-                            && (softInputMode &
-                                    WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
-                        // There is a focus view, and we are navigating forward
-                        // into the window, so show the input window for the user.
-                        if (DEBUG) Log.v(TAG, "Unspecified window will show input");
-                        showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT);
-                    }
-                    break;
-                case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED:
-                    // Do nothing.
-                    break;
-                case WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN:
-                    if (DEBUG) Log.v(TAG, "Window asks to hide input");
-                    hideCurrentInputLocked(0);
-                    break;
-                case WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE:
-                    if ((softInputMode &
-                            WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
-                        if (DEBUG) Log.v(TAG, "Window asks to show input going forward");
+                        break;
+                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED:
+                        // Do nothing.
+                        break;
+                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN:
+                        if (DEBUG) Log.v(TAG, "Window asks to hide input");
+                        hideCurrentInputLocked(0);
+                        break;
+                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE:
+                        if ((softInputMode &
+                                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
+                            if (DEBUG) Log.v(TAG, "Window asks to show input going forward");
+                            showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT);
+                        }
+                        break;
+                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
+                        if (DEBUG) Log.v(TAG, "Window asks to always show input");
                         showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT);
-                    }
-                    break;
-                case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
-                    if (DEBUG) Log.v(TAG, "Window asks to always show input");
-                    showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT);
-                    break;
+                        break;
+                }
             }
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
     }
     
@@ -1022,7 +1096,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
 
     public void setInputMethod(IBinder token, String id) {
         synchronized (mMethodMap) {
-            if (mCurToken == null) {
+            if (token == null) {
                 if (mContext.checkCallingOrSelfPermission(
                         android.Manifest.permission.WRITE_SECURE_SETTINGS)
                         != PackageManager.PERMISSION_GRANTED) {
@@ -1032,19 +1106,31 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
                 }
             } else if (mCurToken != token) {
                 Log.w(TAG, "Ignoring setInputMethod of token: " + token);
+                return;
             }
 
-            setInputMethodLocked(id);
+            long ident = Binder.clearCallingIdentity();
+            try {
+                setInputMethodLocked(id);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
         }
     }
 
     public void hideMySoftInput(IBinder token, int flags) {
         synchronized (mMethodMap) {
-            if (mCurToken == null || mCurToken != token) {
+            if (token == null || mCurToken != token) {
                 Log.w(TAG, "Ignoring hideInputMethod of token: " + token);
+                return;
             }
 
-            hideCurrentInputLocked(flags);
+            long ident = Binder.clearCallingIdentity();
+            try {
+                hideCurrentInputLocked(flags);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
         }
     }
 
@@ -1209,7 +1295,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
     
     // ----------------------------------------------------------------------
     
-    public void showInputMethodMenu() {
+    void showInputMethodMenu() {
         if (DEBUG) Log.v(TAG, "Show switching menu");
 
         hideInputMethodMenu();
@@ -1309,83 +1395,88 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
                         + android.Manifest.permission.WRITE_SECURE_SETTINGS);
             }
             
-            // Make sure this is a valid input method.
-            InputMethodInfo imm = mMethodMap.get(id);
-            if (imm == null) {
+            long ident = Binder.clearCallingIdentity();
+            try {
+                // Make sure this is a valid input method.
+                InputMethodInfo imm = mMethodMap.get(id);
                 if (imm == null) {
-                    throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
+                    if (imm == null) {
+                        throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
+                    }
                 }
-            }
-            
-            StringBuilder builder = new StringBuilder(256);
-            
-            boolean removed = false;
-            String firstId = null;
-            
-            // Look through the currently enabled input methods.
-            String enabledStr = Settings.Secure.getString(mContext.getContentResolver(),
-                    Settings.Secure.ENABLED_INPUT_METHODS);
-            if (enabledStr != null) {
-                final TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
-                splitter.setString(enabledStr);
-                while (splitter.hasNext()) {
-                    String curId = splitter.next();
-                    if (curId.equals(id)) {
-                        if (enabled) {
-                            // We are enabling this input method, but it is
-                            // already enabled.  Nothing to do.  The previous
-                            // state was enabled.
-                            return true;
+                
+                StringBuilder builder = new StringBuilder(256);
+                
+                boolean removed = false;
+                String firstId = null;
+                
+                // Look through the currently enabled input methods.
+                String enabledStr = Settings.Secure.getString(mContext.getContentResolver(),
+                        Settings.Secure.ENABLED_INPUT_METHODS);
+                if (enabledStr != null) {
+                    final TextUtils.SimpleStringSplitter splitter = mStringColonSplitter;
+                    splitter.setString(enabledStr);
+                    while (splitter.hasNext()) {
+                        String curId = splitter.next();
+                        if (curId.equals(id)) {
+                            if (enabled) {
+                                // We are enabling this input method, but it is
+                                // already enabled.  Nothing to do.  The previous
+                                // state was enabled.
+                                return true;
+                            }
+                            // We are disabling this input method, and it is
+                            // currently enabled.  Skip it to remove from the
+                            // new list.
+                            removed = true;
+                        } else if (!enabled) {
+                            // We are building a new list of input methods that
+                            // doesn't contain the given one.
+                            if (firstId == null) firstId = curId;
+                            if (builder.length() > 0) builder.append(':');
+                            builder.append(curId);
                         }
-                        // We are disabling this input method, and it is
-                        // currently enabled.  Skip it to remove from the
-                        // new list.
-                        removed = true;
-                    } else if (!enabled) {
-                        // We are building a new list of input methods that
-                        // doesn't contain the given one.
-                        if (firstId == null) firstId = curId;
-                        if (builder.length() > 0) builder.append(':');
-                        builder.append(curId);
                     }
                 }
-            }
-            
-            if (!enabled) {
-                if (!removed) {
-                    // We are disabling the input method but it is already
-                    // disabled.  Nothing to do.  The previous state was
-                    // disabled.
-                    return false;
-                }
-                // Update the setting with the new list of input methods.
-                Settings.Secure.putString(mContext.getContentResolver(),
-                        Settings.Secure.ENABLED_INPUT_METHODS, builder.toString());
-                // We the disabled input method is currently selected, switch
-                // to another one.
-                String selId = Settings.Secure.getString(mContext.getContentResolver(),
-                        Settings.Secure.DEFAULT_INPUT_METHOD);
-                if (id.equals(selId)) {
+                
+                if (!enabled) {
+                    if (!removed) {
+                        // We are disabling the input method but it is already
+                        // disabled.  Nothing to do.  The previous state was
+                        // disabled.
+                        return false;
+                    }
+                    // Update the setting with the new list of input methods.
                     Settings.Secure.putString(mContext.getContentResolver(),
-                            Settings.Secure.DEFAULT_INPUT_METHOD,
-                            firstId != null ? firstId : "");
+                            Settings.Secure.ENABLED_INPUT_METHODS, builder.toString());
+                    // We the disabled input method is currently selected, switch
+                    // to another one.
+                    String selId = Settings.Secure.getString(mContext.getContentResolver(),
+                            Settings.Secure.DEFAULT_INPUT_METHOD);
+                    if (id.equals(selId)) {
+                        Settings.Secure.putString(mContext.getContentResolver(),
+                                Settings.Secure.DEFAULT_INPUT_METHOD,
+                                firstId != null ? firstId : "");
+                    }
+                    // Previous state was enabled.
+                    return true;
                 }
-                // Previous state was enabled.
-                return true;
-            }
-            
-            // Add in the newly enabled input method.
-            if (enabledStr == null || enabledStr.length() == 0) {
-                enabledStr = id;
-            } else {
-                enabledStr = enabledStr + ':' + id;
+                
+                // Add in the newly enabled input method.
+                if (enabledStr == null || enabledStr.length() == 0) {
+                    enabledStr = id;
+                } else {
+                    enabledStr = enabledStr + ':' + id;
+                }
+                
+                Settings.Secure.putString(mContext.getContentResolver(),
+                        Settings.Secure.ENABLED_INPUT_METHODS, enabledStr);
+                
+                // Previous state was disabled.
+                return false;
+            } finally {
+                Binder.restoreCallingIdentity(ident);
             }
-            
-            Settings.Secure.putString(mContext.getContentResolver(),
-                    Settings.Secure.ENABLED_INPUT_METHODS, enabledStr);
-            
-            // Previous state was disabled.
-            return false;
         }
     }
     
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index bc6fd71850d7..db4daa561c1c 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -132,7 +132,7 @@ public class LocationManagerService extends ILocationManager.Stub
     private static final int MESSAGE_HEARTBEAT = 1;
     private static final int MESSAGE_ACQUIRE_WAKE_LOCK = 2;
     private static final int MESSAGE_RELEASE_WAKE_LOCK = 3;
-    private static final int MESSAGE_SET_NETWORK_LOCATION_PROVIDER = 4;
+    private static final int MESSAGE_INSTALL_NETWORK_LOCATION_PROVIDER = 4;
 
     // Alarm manager and wakelock variables
     private final static String ALARM_INTENT = "com.android.location.ALARM_INTENT";
@@ -565,13 +565,21 @@ public class LocationManagerService extends ILocationManager.Stub
         }
     }
 
-    public void setNetworkLocationProvider(INetworkLocationProvider provider) {
-        mLocationHandler.removeMessages(MESSAGE_SET_NETWORK_LOCATION_PROVIDER);
+    public void setInstallCallback(InstallCallback callback) {
+        mLocationHandler.removeMessages(MESSAGE_INSTALL_NETWORK_LOCATION_PROVIDER);
         Message m = Message.obtain(mLocationHandler, 
-                MESSAGE_SET_NETWORK_LOCATION_PROVIDER, provider);
+                MESSAGE_INSTALL_NETWORK_LOCATION_PROVIDER, callback);
         mLocationHandler.sendMessageAtFrontOfQueue(m);
     }
 
+    public void setNetworkLocationProvider(INetworkLocationProvider provider) {
+        mNetworkLocationInterface = provider;
+        provider.addListener(getPackageNames());
+        mNetworkLocationProvider = (LocationProviderImpl)provider;
+        LocationProviderImpl.addProvider(mNetworkLocationProvider);
+        updateProviders();
+    }
+
     public void setLocationCollector(ILocationCollector collector) {
         mCollector = collector;
         if (mGpsLocationProvider != null) {
@@ -1598,16 +1606,12 @@ public class LocationManagerService extends ILocationManager.Stub
                     // Update wakelock status so the next alarm is set before releasing wakelock
                     updateWakelockStatus(mScreenOn);
                     releaseWakeLock();
-                } else if (msg.what == MESSAGE_SET_NETWORK_LOCATION_PROVIDER) {
+                } else if (msg.what == MESSAGE_INSTALL_NETWORK_LOCATION_PROVIDER) {
                     synchronized (LocationManagerService.class) {
-                        Log.d(TAG, "adding network location provider");
-                        mNetworkLocationInterface = 
-                                (INetworkLocationProvider)msg.obj;
-                        mNetworkLocationInterface.addListener(getPackageNames());
-                        mNetworkLocationProvider = 
-                                (LocationProviderImpl)mNetworkLocationInterface;
-                        LocationProviderImpl.addProvider(mNetworkLocationProvider);
-                        updateProviders();
+                        Log.d(TAG, "installing network location provider");
+                        INetworkLocationManager.InstallCallback callback =
+                                (INetworkLocationManager.InstallCallback)msg.obj;
+                        callback.installNetworkLocationProvider(mContext, LocationManagerService.this);
                     }
                 }
             } catch (Exception e) {
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 221ba46de6e4..c490e42e3e93 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -3219,12 +3219,15 @@ class PackageManagerService extends IPackageManager.Stub {
                         Log.i(TAG, "Observer no longer exists.");
                     }
                 }
-                // There appears to be a subtle deadlock condition if the sendPackageBroadcast call appears
-                // in the synchronized block above.
+                // There appears to be a subtle deadlock condition if the sendPackageBroadcast
+                // call appears in the synchronized block above.
                 if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
                     res.removedInfo.sendBroadcast(false, true);
                     Bundle extras = new Bundle(1);
                     extras.putInt(Intent.EXTRA_UID, res.uid);
+                    if (res.removedInfo.removedPackage != null) {
+                        extras.putBoolean(Intent.EXTRA_REPLACING, true);
+                    }
                     sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
                                          res.pkg.applicationInfo.packageName,
                                          extras);
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 7c111d3d8c8b..6974b5ef5792 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -1001,11 +1001,9 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage
                 }
             }
             else {
-                synchronized (mLocks) {
-                    EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 4,
-                            mBroadcastWakeLock.mCount);
-                    mBroadcastWakeLock.release();
-                }
+                // If we're in this case, then this handler is running for a previous
+                // paired transaction.  mBroadcastWakeLock will already have been released
+                // in sendNotificationLocked.
             }
         }
     };
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index c009fac18d69..eece581fca49 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -87,10 +87,13 @@ public class WifiService extends IWifiManager.Stub {
 
     private final LockList mLocks = new LockList();
     /**
-     * See {@link Settings.System#WIFI_IDLE_MS}. This is the default value if a
-     * Settings.System value is not present.
+     * See {@link Settings.Gservices#WIFI_IDLE_MS}. This is the default value if a
+     * Settings.Gservices value is not present. This timeout value is chosen as
+     * the approximate point at which the battery drain caused by Wi-Fi
+     * being enabled but not active exceeds the battery drain caused by
+     * re-establishing a connection to the mobile data network.
      */
-    private static final long DEFAULT_IDLE_MILLIS = 2 * 60 * 1000; /* 2 minutes */
+    private static final long DEFAULT_IDLE_MILLIS = 15 * 60 * 1000; /* 15 minutes */
 
     private static final String WAKELOCK_TAG = "WifiService";
 
@@ -101,7 +104,7 @@ public class WifiService extends IWifiManager.Stub {
      * provides a bit of extra margin.
      * <p>
      * See {@link android.provider.Settings.Secure#WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS}.
-     * This is the default value if a Settings.System value is not present.
+     * This is the default value if a Settings.Secure value is not present.
      */
     private static final int DEFAULT_WAKELOCK_TIMEOUT = 8000;
 
@@ -1364,7 +1367,7 @@ public class WifiService extends IWifiManager.Stub {
      * in the current regulatory domain. This method should be used only
      * if the correct number of channels cannot be determined automatically
      * for some reason. If the operation is successful, the new value is
-     * persisted as a System setting.
+     * persisted as a Secure setting.
      * @param numChannels the number of allowed channels. Must be greater than 0
      * and less than or equal to 16.
      * @return {@code true} if the operation succeeds, {@code false} otherwise, e.g.,
@@ -1446,8 +1449,8 @@ public class WifiService extends IWifiManager.Stub {
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
 
-            long idleMillis = Settings.System.getLong(mContext.getContentResolver(),
-                                                  Settings.System.WIFI_IDLE_MS, DEFAULT_IDLE_MILLIS);
+            long idleMillis = Settings.Gservices.getLong(mContext.getContentResolver(),
+                                                  Settings.Gservices.WIFI_IDLE_MS, DEFAULT_IDLE_MILLIS);
             int stayAwakeConditions =
                     Settings.System.getInt(mContext.getContentResolver(),
                                            Settings.System.STAY_ON_WHILE_PLUGGED_IN, 0);
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 09f5d8f1ecaa..fed6d1281899 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -768,27 +768,55 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
         if (willMove && w != null) {
             final WindowState curTarget = mInputMethodTarget;
             if (curTarget != null && curTarget.mAppToken != null) {
-                int curIndex = -1;
-                if (DEBUG_INPUT_METHOD) Log.v(TAG, "mNextAppTransition=" 
-                        + mNextAppTransition + " curTarget animating="
-                        + curTarget.isAnimating()
-                        + " layer=" + curTarget.mAnimLayer
-                        + " new layer=" + w.mAnimLayer);
-                if (mNextAppTransition != WindowManagerPolicy.TRANSIT_NONE) {
-                    // If we are currently setting up for an animation,
-                    // hold everything until we can find out what will happen.
-                    mInputMethodTargetWaitingAnim = true;
-                    curIndex = localmWindows.indexOf(curTarget);
-                } else if (curTarget.isAnimating() &&
-                        curTarget.mAnimLayer > w.mAnimLayer) {
-                    // If the window we are currently targeting is involved
-                    // with an animation, and it is on top of the next target
-                    // we will be over, then hold off on moving until
-                    // that is done.
-                    curIndex = localmWindows.indexOf(curTarget);
-                }
-                if (curIndex >= 0) {
-                    return curIndex + 1;
+                
+                // Now some fun for dealing with window animations that
+                // modify the Z order.  We need to look at all windows below
+                // the current target that are in this app, finding the highest
+                // visible one in layering.
+                AppWindowToken token = curTarget.mAppToken;
+                WindowState highestTarget = null;
+                int highestPos = 0;
+                if (token.animating || token.animation != null) {
+                    int pos = 0;
+                    pos = localmWindows.indexOf(curTarget);
+                    while (pos >= 0) {
+                        WindowState win = (WindowState)localmWindows.get(pos);
+                        if (win.mAppToken != token) {
+                            break;
+                        }
+                        if (!win.mRemoved) {
+                            if (highestTarget == null || win.mAnimLayer >
+                                    highestTarget.mAnimLayer) {
+                                highestTarget = win;
+                                highestPos = pos;
+                            }
+                        }
+                        pos--;
+                    }
+                }
+                
+                if (highestTarget != null) {
+                    if (DEBUG_INPUT_METHOD) Log.v(TAG, "mNextAppTransition=" 
+                            + mNextAppTransition + " " + highestTarget
+                            + " animating=" + highestTarget.isAnimating()
+                            + " layer=" + highestTarget.mAnimLayer
+                            + " new layer=" + w.mAnimLayer);
+                    
+                    if (mNextAppTransition != WindowManagerPolicy.TRANSIT_NONE) {
+                        // If we are currently setting up for an animation,
+                        // hold everything until we can find out what will happen.
+                        mInputMethodTargetWaitingAnim = true;
+                        mInputMethodTarget = highestTarget;
+                        return highestPos + 1;
+                    } else if (highestTarget.isAnimating() &&
+                            highestTarget.mAnimLayer > w.mAnimLayer) {
+                        // If the window we are currently targeting is involved
+                        // with an animation, and it is on top of the next target
+                        // we will be over, then hold off on moving until
+                        // that is done.
+                        mInputMethodTarget = highestTarget;
+                        return highestPos + 1;
+                    }
                 }
             }
         }
@@ -891,12 +919,27 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
         }
     }
     
+    void logWindowList(String prefix) {
+        int N = mWindows.size();
+        while (N > 0) {
+            N--;
+            Log.v(TAG, prefix + "#" + N + ": " + mWindows.get(N));
+        }
+    }
+    
     void moveInputMethodDialogsLocked(int pos) {
         ArrayList<WindowState> dialogs = mInputMethodDialogs;
+        
         final int N = dialogs.size();
+        if (DEBUG_INPUT_METHOD) Log.v(TAG, "Removing " + N + " dialogs w/pos=" + pos);
         for (int i=0; i<N; i++) {
             pos = tmpRemoveWindowLocked(pos, dialogs.get(i));
         }
+        if (DEBUG_INPUT_METHOD) {
+            Log.v(TAG, "Window list w/pos=" + pos);
+            logWindowList("  ");
+        }
+        
         if (pos >= 0) {
             final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken;
             if (pos < mWindows.size()) {
@@ -905,17 +948,26 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
                     pos++;
                 }
             }
+            if (DEBUG_INPUT_METHOD) Log.v(TAG, "Adding " + N + " dialogs at pos=" + pos);
             for (int i=0; i<N; i++) {
                 WindowState win = dialogs.get(i);
                 win.mTargetAppToken = targetAppToken;
                 pos = reAddWindowLocked(pos, win);
             }
+            if (DEBUG_INPUT_METHOD) {
+                Log.v(TAG, "Final window list:");
+                logWindowList("  ");
+            }
             return;
         }
         for (int i=0; i<N; i++) {
             WindowState win = dialogs.get(i);
             win.mTargetAppToken = null;
             reAddWindowToListInOrderLocked(win);
+            if (DEBUG_INPUT_METHOD) {
+                Log.v(TAG, "No IM target, final list:");
+                logWindowList("  ");
+            }
         }
     }
     
@@ -971,9 +1023,21 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
             }
             
             if (imWin != null) {
+                if (DEBUG_INPUT_METHOD) {
+                    Log.v(TAG, "Moving IM from " + imPos);
+                    logWindowList("  ");
+                }
                 imPos = tmpRemoveWindowLocked(imPos, imWin);
+                if (DEBUG_INPUT_METHOD) {
+                    Log.v(TAG, "List after moving with new pos " + imPos + ":");
+                    logWindowList("  ");
+                }
                 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
                 reAddWindowLocked(imPos, imWin);
+                if (DEBUG_INPUT_METHOD) {
+                    Log.v(TAG, "List after moving IM to " + imPos + ":");
+                    logWindowList("  ");
+                }
                 if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
             } else {
                 moveInputMethodDialogsLocked(imPos);
@@ -984,9 +1048,14 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
             // because they aren't currently associated with a focus window.
             
             if (imWin != null) {
+                if (DEBUG_INPUT_METHOD) Log.v(TAG, "Moving IM from " + imPos);
                 tmpRemoveWindowLocked(0, imWin);
                 imWin.mTargetAppToken = null;
                 reAddWindowToListInOrderLocked(imWin);
+                if (DEBUG_INPUT_METHOD) {
+                    Log.v(TAG, "List with no IM target:");
+                    logWindowList("  ");
+                }
                 if (DN > 0) moveInputMethodDialogsLocked(-1);;
             } else {
                 moveInputMethodDialogsLocked(-1);;
@@ -1233,7 +1302,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
         if (win.mSurface != null && !mDisplayFrozen) {
             // If we are not currently running the exit animation, we
             // need to see about starting one.
-            if (wasVisible=win.isVisibleLw()) {
+            if (wasVisible=win.isWinVisibleLw()) {
                 
                 int transit = WindowManagerPolicy.TRANSIT_EXIT;
                 if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
@@ -1277,6 +1346,12 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
         mKeyWaiter.releasePendingPointerLocked(win.mSession);
         mKeyWaiter.releasePendingTrackballLocked(win.mSession);
         
+        win.mRemoved = true;
+        
+        if (mInputMethodTarget == win) {
+            moveInputMethodWindowsIfNeededLocked(false);
+        }
+        
         mPolicy.removeWindowLw(win);
         win.removeLocked();
 
@@ -1501,7 +1576,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
                         if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
                             transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
                         }
-                        if (win.isVisibleLw() &&
+                        if (win.isWinVisibleLw() &&
                               applyAnimationLocked(win, transit, false)) {
                             win.mExiting = true;
                             mKeyWaiter.finishedKey(session, client, true,
@@ -1511,13 +1586,13 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
                             // an exit.
                             win.mExiting = true;
                         } else {
+                            if (mInputMethodWindow == win) {
+                                mInputMethodWindow = null;
+                            }
                             win.destroySurfaceLocked();
                         }
                     }
                 }
-                if (mInputMethodWindow == win) {
-                    mInputMethodWindow = null;
-                }
                 outSurface.clear();
             }
 
@@ -1620,7 +1695,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
 
     private boolean applyAnimationLocked(WindowState win,
             int transit, boolean isEntrance) {
-        if (win.mAnimating && win.mAnimationIsEntrance == isEntrance) {
+        if (win.mLocalAnimating && win.mAnimationIsEntrance == isEntrance) {
             // If we are trying to apply an animation, but already running
             // an animation of the same type, then just leave that one alone.
             return true;
@@ -1666,6 +1741,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
                     Log.v(TAG, "Loaded animation " + a + " for " + win, e);
                 }
                 win.setAnimation(a);
+                win.mAnimationIsEntrance = isEntrance;
             }
         } else {
             win.clearAnimation();
@@ -2724,7 +2800,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
         boolean added = false;
         for (int j=0; j<NCW; j++) {
             WindowState cwin = (WindowState)win.mChildWindows.get(j);
-            if (cwin.mSubLayer >= 0) {
+            if (!added && cwin.mSubLayer >= 0) {
                 mWindows.add(index, win);
                 index++;
                 added = true;
@@ -4645,8 +4721,8 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
         KeyQ() {
             super(mContext);
             PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
-            mHoldingScreen = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK
-                    | PowerManager.ON_AFTER_RELEASE, "KEEP_SCREEN_ON_FLAG");
+            mHoldingScreen = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
+                    "KEEP_SCREEN_ON_FLAG");
             mHoldingScreen.setReferenceCounted(false);
         }
 
@@ -4769,8 +4845,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
                 if (holding) {
                     mHoldingScreen.acquire();
                 } else {
-                    long curTime = SystemClock.uptimeMillis();
-                    mPowerManager.userActivity(curTime, false, LocalPowerManager.OTHER_EVENT);
+                    mPolicy.screenOnStopped();
                     mHoldingScreen.release();
                 }
             }
@@ -5095,6 +5170,19 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
             }
         }
 
+        public boolean performHapticFeedback(IWindow window, int effectId,
+                boolean always) {
+            synchronized(mWindowMap) {
+                long ident = Binder.clearCallingIdentity();
+                try {
+                    return mPolicy.performHapticFeedback(
+                            windowForClientLocked(this, window), effectId, always);
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
+                }
+            }
+        }
+        
         void windowAddedLocked() {
             if (mSurfaceSession == null) {
                 if (localLOGV) Log.v(
@@ -5255,9 +5343,11 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
 
         // Currently running animation.
         boolean mAnimating;
+        boolean mLocalAnimating;
         Animation mAnimation;
         boolean mAnimationIsEntrance;
         boolean mHasTransformation;
+        boolean mHasLocalTransformation;
         final Transformation mTransformation = new Transformation();
 
         // This is set after IWindowSession.relayout() has been called at
@@ -5297,6 +5387,9 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
         // been updated for the new orientation.
         boolean mOrientationChanging;
         
+        // Is this window now (or just being) removed?
+        boolean mRemoved;
+        
         WindowState(Session s, IWindow c, WindowToken token,
                WindowState attachedWindow, WindowManager.LayoutParams a,
                int viewVisibility) {
@@ -5516,6 +5609,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
             if (localLOGV) Log.v(
                 TAG, "Setting animation in " + this + ": " + anim);
             mAnimating = false;
+            mLocalAnimating = false;
             mAnimation = anim;
             mAnimation.restrictDuration(MAX_ANIMATION_DURATION);
             mAnimation.scaleCurrentDuration(mWindowAnimationScale);
@@ -5524,6 +5618,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
         public void clearAnimation() {
             if (mAnimation != null) {
                 mAnimating = true;
+                mLocalAnimating = false;
                 mAnimation = null;
             }
         }
@@ -5752,13 +5847,15 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
                 
                 if (!mDrawPending && !mCommitDrawPending && mAnimation != null) {
                     mHasTransformation = true;
-                    if (!mAnimating) {
+                    mHasLocalTransformation = true;
+                    if (!mLocalAnimating) {
                         if (DEBUG_ANIM) Log.v(
                             TAG, "Starting animation in " + this +
                             " @ " + currentTime + ": ww=" + mFrame.width() + " wh=" + mFrame.height() +
                             " dw=" + dw + " dh=" + dh + " scale=" + mWindowAnimationScale);
                         mAnimation.initialize(mFrame.width(), mFrame.height(), dw, dh);
                         mAnimation.setStartTime(currentTime);
+                        mLocalAnimating = true;
                         mAnimating = true;
                     }
                     mTransformation.clear();
@@ -5767,9 +5864,6 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
                     if (DEBUG_ANIM) Log.v(
                         TAG, "Stepped animation in " + this +
                         ": more=" + more + ", xform=" + mTransformation);
-                    if (mAppToken != null && mAppToken.hasTransformation) {
-                        mTransformation.compose(mAppToken.transformation);
-                    }
                     if (more) {
                         // we're not done!
                         return true;
@@ -5780,10 +5874,19 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
                     mAnimation = null;
                     //WindowManagerService.this.dump();
                 }
-                if (mAppToken != null && mAppToken.hasTransformation) {
+                mHasLocalTransformation = false;
+                if ((!mLocalAnimating || mAnimationIsEntrance) && mAppToken != null
+                        && mAppToken.hasTransformation) {
+                    // When our app token is animating, we kind-of pretend like
+                    // we are as well.  Note the mLocalAnimating mAnimationIsEntrance
+                    // part of this check means that we will only do this if
+                    // our window is not currently exiting, or it is not
+                    // locally animating itself.  The idea being that one that
+                    // is exiting and doing a local animation should be removed
+                    // once that animation is done.
                     mAnimating = true;
                     mHasTransformation = true;
-                    mTransformation.set(mAppToken.transformation);
+                    mTransformation.clear();
                     return false;
                 } else if (mHasTransformation) {
                     // Little trick to get through the path below to act like
@@ -5796,10 +5899,11 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
                 // If the display is frozen, and there is a pending animation,
                 // clear it and make sure we run the cleanup code.
                 mAnimating = true;
+                mLocalAnimating = true;
                 mAnimation = null;
             }
             
-            if (!mAnimating) {
+            if (!mAnimating && !mLocalAnimating) {
                 return false;
             }
 
@@ -5809,6 +5913,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
                 + (mAppToken != null ? mAppToken.reportedVisible : false));
             
             mAnimating = false;
+            mLocalAnimating = false;
             mAnimation = null;
             mAnimLayer = mLayer;
             if (mIsImWindow) {
@@ -5817,6 +5922,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
             if (DEBUG_LAYERS) Log.v(TAG, "Stepping win " + this
                     + " anim layer: " + mAnimLayer);
             mHasTransformation = false;
+            mHasLocalTransformation = false;
             mPolicyVisibility = mPolicyVisibilityAfterAnim;
             mTransformation.clear();
             if (mHasDrawn
@@ -5891,10 +5997,15 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
         }
         
         void computeShownFrameLocked() {
-            final boolean selfTransformation = mHasTransformation;
-            final boolean attachedTransformation = (mAttachedWindow != null
-                    && mAttachedWindow.mHasTransformation);
-            if (selfTransformation || attachedTransformation) {
+            final boolean selfTransformation = mHasLocalTransformation;
+            Transformation attachedTransformation =
+                    (mAttachedWindow != null && mAttachedWindow.mHasLocalTransformation)
+                    ? mAttachedWindow.mTransformation : null;
+            Transformation appTransformation =
+                    (mAppToken != null && mAppToken.hasTransformation)
+                    ? mAppToken.transformation : null;
+            if (selfTransformation || attachedTransformation != null
+                    || appTransformation != null) {
                 // cache often used attributes locally  
                 final Rect frame = mFrame;
                 final float tmpFloats[] = mTmpFloats;
@@ -5905,8 +6016,11 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
                 if (selfTransformation) {
                     tmpMatrix.preConcat(mTransformation.getMatrix());
                 }
-                if (attachedTransformation) {
-                    tmpMatrix.preConcat(mAttachedWindow.mTransformation.getMatrix());
+                if (attachedTransformation != null) {
+                    tmpMatrix.preConcat(attachedTransformation.getMatrix());
+                }
+                if (appTransformation != null) {
+                    tmpMatrix.preConcat(appTransformation.getMatrix());
                 }
 
                 // "convert" it into SurfaceFlinger's format
@@ -5940,8 +6054,11 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
                     if (selfTransformation) {
                         mShownAlpha *= mTransformation.getAlpha();
                     }
-                    if (attachedTransformation) {
-                        mShownAlpha *= mAttachedWindow.mTransformation.getAlpha();
+                    if (attachedTransformation != null) {
+                        mShownAlpha *= attachedTransformation.getAlpha();
+                    }
+                    if (appTransformation != null) {
+                        mShownAlpha *= appTransformation.getAlpha();
                     }
                 } else {
                     //Log.i(TAG, "Not applying alpha transform");
@@ -5965,7 +6082,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
         /**
          * Is this window visible?  It is not visible if there is no
          * surface, or we are in the process of running an exit animation
-         * that will remove the surface.
+         * that will remove the surface, or its app token has been hidden.
          */
         public boolean isVisibleLw() {
             final AppWindowToken atoken = mAppToken;
@@ -5974,6 +6091,18 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
                     && !mExiting && !mDestroying;
         }
 
+        /**
+         * Is this window visible, ignoring its app token?  It is not visible
+         * if there is no surface, or we are in the process of running an exit animation
+         * that will remove the surface.
+         */
+        public boolean isWinVisibleLw() {
+            final AppWindowToken atoken = mAppToken;
+            return mSurface != null && mPolicyVisibility && !mAttachedHidden
+                    && (atoken == null || !atoken.hiddenRequested || atoken.animating)
+                    && !mExiting && !mDestroying;
+        }
+
         /**
          * The same as isVisible(), but follows the current hidden state of
          * the associated app token, not the pending requested hidden state.
@@ -6203,6 +6332,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
             pw.println(prefix + "mShownAlpha=" + mShownAlpha
                   + " mAlpha=" + mAlpha + " mLastAlpha=" + mLastAlpha);
             pw.println(prefix + "mAnimating=" + mAnimating
+                    + " mLocalAnimating=" + mLocalAnimating
                     + " mAnimationIsEntrance=" + mAnimationIsEntrance
                     + " mAnimation=" + mAnimation);
             pw.println(prefix + "XForm: has=" + mHasTransformation
@@ -6213,7 +6343,8 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
                   + " mHasDrawn=" + mHasDrawn);
             pw.println(prefix + "mExiting=" + mExiting
                     + " mRemoveOnExit=" + mRemoveOnExit
-                    + " mDestroying=" + mDestroying);
+                    + " mDestroying=" + mDestroying
+                    + " mRemoved=" + mRemoved);
             pw.println(prefix + "mOrientationChanging=" + mOrientationChanging
                     + " mAppFreezing=" + mAppFreezing);
         }
@@ -7959,6 +8090,9 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo
                 i--;
                 WindowState win = mDestroySurface.get(i);
                 win.mDestroying = false;
+                if (mInputMethodWindow == win) {
+                    mInputMethodWindow = null;
+                }
                 win.destroySurfaceLocked();
             } while (i > 0);
             mDestroySurface.clear();
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index f5efe4b591fe..e391da337983 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -159,7 +159,12 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
     static final int LOG_AM_BROADCAST_DISCARD_APP = 30025;
     static final int LOG_AM_CREATE_SERVICE = 30030;
     static final int LOG_AM_DESTROY_SERVICE = 30031;
-
+    static final int LOG_AM_PROCESS_CRASHED_TOO_MUCH = 30032;
+    static final int LOG_AM_DROP_PROCESS = 30033;
+    static final int LOG_AM_SERVICE_CRASHED_TOO_MUCH = 30034;
+    static final int LOG_AM_SCHEDULE_SERVICE_RESTART = 30035;
+    static final int LOG_AM_PROVIDER_LOST_PROCESS = 30036;
+    
     static final int LOG_BOOT_PROGRESS_AMS_READY = 3040;
     static final int LOG_BOOT_PROGRESS_ENABLE_SCREEN = 3050;
 
@@ -1787,7 +1792,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
         }
     }
 
-    private final void startPausingLocked(boolean userLeaving) {
+    private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
         if (mPausingActivity != null) {
             RuntimeException e = new RuntimeException();
             Log.e(TAG, "Trying to pause when pause is already pending for "
@@ -1840,9 +1845,15 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
 
         if (mPausingActivity != null) {
             // Have the window manager pause its key dispatching until the new
-            // activity has started...
-            prev.pauseKeyDispatchingLocked();
-            
+            // activity has started.  If we're pausing the activity just because
+            // the screen is being turned off and the UI is sleeping, don't interrupt
+            // key dispatch; the same activity will pick it up again on wakeup.
+            if (!uiSleeping) {
+                prev.pauseKeyDispatchingLocked();
+            } else {
+                if (DEBUG_PAUSE) Log.v(TAG, "Key dispatch not paused for screen off");
+            }
+
             // Schedule a pause timeout in case the app doesn't respond.
             // We don't give it much time because this directly impacts the
             // responsiveness seen by the user.
@@ -2188,7 +2199,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
         // can be resumed...
         if (mResumedActivity != null) {
             if (DEBUG_SWITCH) Log.v(TAG, "Skip resume: need to start pausing");
-            startPausingLocked(userLeaving);
+            startPausingLocked(userLeaving, false);
             return true;
         }
 
@@ -2605,8 +2616,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                 r.app.thread.scheduleNewIntent(ar, r);
                 sent = true;
             } catch (Exception e) {
-                Log.w(TAG,
-                      "Exception thrown sending new intent to " + r, e);
+                Log.w(TAG, "Exception thrown sending new intent to " + r, e);
             }
         }
         if (!sent) {
@@ -3456,7 +3466,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
             if (mPausingActivity == null) {
                 if (DEBUG_PAUSE) Log.v(TAG, "Finish needs to pause: " + r);
                 if (DEBUG_USER_LEAVING) Log.v(TAG, "finish() => pause with userLeaving=false");
-                startPausingLocked(false);
+                startPausingLocked(false, false);
             }
 
         } else if (r.state != ActivityState.PAUSING) {
@@ -3590,9 +3600,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                 r.app.thread.scheduleSendResult(r, list);
                 return;
             } catch (Exception e) {
-                Log.w(TAG,
-                      "Exception thrown sending result to " + r,
-                      e);
+                Log.w(TAG, "Exception thrown sending result to " + r, e);
             }
         }
 
@@ -3778,8 +3786,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
         r.configChangeFlags = 0;
         
         if (!mLRUActivities.remove(r)) {
-            Log.w(TAG, "Activity " + r
-                  + " being finished, but not in LRU list");
+            Log.w(TAG, "Activity " + r + " being finished, but not in LRU list");
         }
         
         return removedFromHistory;
@@ -4217,7 +4224,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                 } catch (RemoteException e) {
                 }
                 if (pkgUid == -1) {
-                    Log.w(TAG, "Invalid packageName:"+packageName);
+                    Log.w(TAG, "Invalid packageName:" + packageName);
                     return false;
                 }
                 if (uid == pkgUid || checkComponentPermission(
@@ -4270,7 +4277,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                 } catch (RemoteException e) {
                 }
                 if (pkgUid == -1) {
-                    Log.w(TAG, "Invalid packageName:"+packageName);
+                    Log.w(TAG, "Invalid packageName: " + packageName);
                     return;
                 }
                 restartPackageLocked(packageName, pkgUid);
@@ -4423,6 +4430,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
         if (app == null) {
             Log.w(TAG, "No pending application record for pid " + pid
                     + " (IApplicationThread " + thread + "); dropping process");
+            EventLog.writeEvent(LOG_AM_DROP_PROCESS, pid);
             if (pid > 0 && pid != MY_PID) {
                 Process.killProcess(pid);
             } else {
@@ -6579,10 +6587,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
             if (caller != null) {
                 r = getRecordForAppLocked(caller);
                 if (r == null) {
-                throw new SecurityException(
-                        "Unable to find app for caller " + caller
-                      + " (pid=" + Binder.getCallingPid()
-                      + ") when getting content provider " + name);
+                    throw new SecurityException(
+                            "Unable to find app for caller " + caller
+                          + " (pid=" + Binder.getCallingPid()
+                          + ") when getting content provider " + name);
                 }
             }
 
@@ -6739,6 +6747,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                             + cpi.applicationInfo.packageName + "/"
                             + cpi.applicationInfo.uid + " for provider "
                             + name + ": launching app became null");
+                    EventLog.writeEvent(LOG_AM_PROVIDER_LOST_PROCESS,
+                            cpi.applicationInfo.packageName,
+                            cpi.applicationInfo.uid, name);
+                    return null;
                 }
                 try {
                     cpr.wait();
@@ -6844,9 +6856,6 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                 ContentProviderRecord dst =
                     (ContentProviderRecord)r.pubProviders.get(src.info.name);
                 if (dst != null) {
-                    dst.provider = src.provider;
-                    dst.app = r;
-
                     mProvidersByClass.put(dst.info.name, dst);
                     String names[] = dst.info.authority.split(";");
                     for (int j = 0; j < names.length; j++) {
@@ -6863,6 +6872,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                         }
                     }
                     synchronized (dst) {
+                        dst.provider = src.provider;
+                        dst.app = r;
                         dst.notifyAll();
                     }
                     updateOomAdjLocked(r);
@@ -6993,7 +7004,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
             if (mPausingActivity == null) {
                 if (DEBUG_PAUSE) Log.v(TAG, "Sleep needs to pause...");
                 if (DEBUG_USER_LEAVING) Log.v(TAG, "Sleep => pause with userLeaving=false");
-                startPausingLocked(false);
+                startPausingLocked(false, true);
             }
         }
     }
@@ -7499,6 +7510,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
             // This process loses!
             Log.w(TAG, "Process " + app.info.processName
                     + " has crashed too many times: killing!");
+            EventLog.writeEvent(LOG_AM_PROCESS_CRASHED_TOO_MUCH,
+                    app.info.processName, app.info.uid);
             killServicesLocked(app, false);
             for (int i=mHistory.size()-1; i>=0; i--) {
                 HistoryRecord r = (HistoryRecord)mHistory.get(i);
@@ -8429,6 +8442,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                 if (sr.crashCount >= 2) {
                     Log.w(TAG, "Service crashed " + sr.crashCount
                             + " times, stopping: " + sr);
+                    EventLog.writeEvent(LOG_AM_SERVICE_CRASHED_TOO_MUCH,
+                            sr.crashCount, sr.shortName, app.pid);
                     bringDownServiceLocked(sr, true);
                 } else if (!allowRestart) {
                     bringDownServiceLocked(sr, true);
@@ -8447,7 +8462,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
 
     private final void removeDyingProviderLocked(ProcessRecord proc,
             ContentProviderRecord cpr) {
-        cpr.launchingApp = null;
+        synchronized (cpr) {
+            cpr.launchingApp = null;
+            cpr.notifyAll();
+        }
         
         mProvidersByClass.remove(cpr.info.name);
         String names[] = cpr.info.authority.split(";");
@@ -8529,6 +8547,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
                             break;
                         }
                     }
+                } else {
+                    i = NL;
                 }
 
                 if (i >= NL) {
@@ -8602,7 +8622,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
         mProcessesOnHold.remove(app);
 
         if (restart) {
-            // We have component that still need to be running in the
+            // We have components that still need to be running in the
             // process, so re-launch it.
             mProcessNames.put(app.processName, app.info.uid, app);
             startProcessLocked(app, "restart", app.processName);
@@ -8952,6 +8972,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
         r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
         Log.w(TAG, "Scheduling restart of crashed service "
                 + r.shortName + " in " + r.restartDelay + "ms");
+        EventLog.writeEvent(LOG_AM_SCHEDULE_SERVICE_RESTART,
+                r.shortName, r.restartDelay);
 
         Message msg = Message.obtain();
         msg.what = SERVICE_ERROR_MSG;
@@ -11660,7 +11682,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
 
                 // We can finish this one if we have its icicle saved and
                 // it is not persistent.
-                if ((r.haveState || !r.stateNotNeeded)
+                if ((r.haveState || !r.stateNotNeeded) && !r.visible
                         && r.stopped && !r.persistent && !r.finishing) {
                     final int origSize = mLRUActivities.size();
                     destroyActivityLocked(r, true);
diff --git a/services/java/com/android/server/am/UsageStatsService.java b/services/java/com/android/server/am/UsageStatsService.java
index 001987fd0ff3..3922f39f52ba 100755
--- a/services/java/com/android/server/am/UsageStatsService.java
+++ b/services/java/com/android/server/am/UsageStatsService.java
@@ -22,13 +22,24 @@ import android.content.Context;
 import android.os.Binder;
 import android.os.IBinder;
 import com.android.internal.os.PkgUsageStats;
+import android.os.Parcel;
 import android.os.Process;
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.util.Log;
+import java.io.File;
 import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
 import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -44,35 +55,257 @@ public final class UsageStatsService extends IUsageStats.Stub {
     private static final String TAG = "UsageStats";
     static IUsageStats sService;
     private Context mContext;
-    private String mFileName;
+    // structure used to maintain statistics since the last checkin.
     final private Map<String, PkgUsageStatsExtended> mStats;
+    // Lock to update package stats. Methods suffixed by SLOCK should invoked with
+    // this lock held
+    final Object mStatsLock;
+    // Lock to write to file. Methods suffixed by FLOCK should invoked with
+    // this lock held.
+    final Object mFileLock;
+    // Order of locks is mFileLock followed by mStatsLock to avoid deadlocks
     private String mResumedPkg;
+    private File mFile;
+    //private File mBackupFile;
+    private long mLastWriteRealTime;
+    private int _FILE_WRITE_INTERVAL = 30*60*1000; //ms
+    private static final String _PREFIX_DELIMIT=".";
+    private String mFilePrefix;
+    private Calendar mCal;
+    private static final int  _MAX_NUM_FILES = 10;
+    private long mLastTime;
     
     private class PkgUsageStatsExtended {
         int mLaunchCount;
         long mUsageTime;
-        long mChgTime;
+        long mPausedTime;
+        long mResumedTime;
+        
         PkgUsageStatsExtended() {
             mLaunchCount = 0;
             mUsageTime = 0;
-            mChgTime =  SystemClock.elapsedRealtime();
         }
         void updateResume() {
             mLaunchCount ++;
-            mChgTime = SystemClock.elapsedRealtime();
+            mResumedTime = SystemClock.elapsedRealtime();
         }
         void updatePause() {
-            long currTime = SystemClock.elapsedRealtime();
-            mUsageTime += (currTime - mChgTime);
-            mChgTime = currTime;
+            mPausedTime =  SystemClock.elapsedRealtime();
+            mUsageTime += (mPausedTime - mResumedTime);
+        }
+        void clear() {
+            mLaunchCount = 0;
+            mUsageTime = 0;
         }
     }
     
-    UsageStatsService(String filename) {
-        mFileName = filename;
+    UsageStatsService(String fileName) {
         mStats = new HashMap<String, PkgUsageStatsExtended>();
+        mStatsLock = new Object();
+        mFileLock = new Object();
+        mFilePrefix = fileName;
+        mCal = Calendar.getInstance();
+        // Update current stats which are binned by date
+        String uFileName = getCurrentDateStr(mFilePrefix);
+        mFile = new File(uFileName);
+        readStatsFromFile();
+        mLastWriteRealTime = SystemClock.elapsedRealtime();
+        mLastTime = new Date().getTime();
+    }
+
+    /*
+     * Utility method to convert date into string.
+     */
+    private String getCurrentDateStr(String prefix) {
+        mCal.setTime(new Date());
+        StringBuilder sb = new StringBuilder();
+        if (prefix != null) {
+            sb.append(prefix);
+            sb.append(".");
+        }
+        int mm = mCal.get(Calendar.MONTH) - Calendar.JANUARY +1;
+        if (mm < 10) {
+            sb.append("0");
+        }
+        sb.append(mm);
+        int dd = mCal.get(Calendar.DAY_OF_MONTH);
+        if (dd < 10) {
+            sb.append("0");
+        }
+        sb.append(dd);
+        sb.append(mCal.get(Calendar.YEAR));
+        return sb.toString();
+    }
+    
+    private Parcel getParcelForFile(File file) throws IOException {
+        FileInputStream stream = new FileInputStream(file);
+        byte[] raw = readFully(stream);
+        Parcel in = Parcel.obtain();
+        in.unmarshall(raw, 0, raw.length);
+        in.setDataPosition(0);
+        stream.close();
+        return in;
+    }
+    
+    private void readStatsFromFile() {
+        File newFile = mFile;
+        synchronized (mFileLock) {
+            try {
+                if (newFile.exists()) {
+                    readStatsFLOCK(newFile);
+                } else {
+                    // Check for file limit before creating a new file
+                    checkFileLimitFLOCK();
+                    newFile.createNewFile();
+                }
+            } catch (IOException e) {
+                Log.w(TAG,"Error : " + e + " reading data from file:" + newFile);
+            }
+        }
+    }
+    
+    private void readStatsFLOCK(File file) throws IOException {
+        Parcel in = getParcelForFile(file);
+        while (in.dataAvail() > 0) {
+            String pkgName = in.readString();
+            PkgUsageStatsExtended pus = new PkgUsageStatsExtended();
+            pus.mLaunchCount = in.readInt();
+            pus.mUsageTime = in.readLong();
+            synchronized (mStatsLock) {
+                mStats.put(pkgName, pus);
+            }
+        }
+    }
+
+    private ArrayList<String> getUsageStatsFileListFLOCK() {
+        File dir = getUsageFilesDir();
+        if (dir == null) {
+            Log.w(TAG, "Couldnt find writable directory for usage stats file");
+            return null;
+        }
+        // Check if there are too many files in the system and delete older files
+        String fList[] = dir.list();
+        if (fList == null) {
+            return null;
+        }
+        File pre = new File(mFilePrefix);
+        String filePrefix = pre.getName();
+        // file name followed by dot
+        int prefixLen = filePrefix.length()+1;
+        ArrayList<String> fileList = new ArrayList<String>();
+        for (String file : fList) {
+            int index = file.indexOf(filePrefix);
+            if (index == -1) {
+                continue;
+            }
+            if (file.endsWith(".bak")) {
+                continue;
+            }
+            fileList.add(file);
+        }
+        return fileList;
+    }
+    
+    private File getUsageFilesDir() {
+        if (mFilePrefix == null) {
+            return null;
+        }
+        File pre = new File(mFilePrefix);
+        return new File(pre.getParent());
     }
     
+    private void checkFileLimitFLOCK() {
+        File dir = getUsageFilesDir();
+        if (dir == null) {
+            Log.w(TAG, "Couldnt find writable directory for usage stats file");
+            return;
+        }
+        // Get all usage stats output files
+        ArrayList<String> fileList = getUsageStatsFileListFLOCK();
+        if (fileList == null) {
+            // Strange but we dont have to delete any thing
+            return;
+        }
+        int count = fileList.size();
+        if (count <= _MAX_NUM_FILES) {
+            return;
+        }
+        // Sort files
+        Collections.sort(fileList);
+        count -= _MAX_NUM_FILES;
+        // Delete older files
+        for (int i = 0; i < count; i++) {
+            String fileName = fileList.get(i);
+            File file = new File(dir, fileName);
+            Log.i(TAG, "Deleting file : "+fileName);
+            file.delete();
+        }
+    }
+    
+    private void writeStatsToFile() {
+        synchronized (mFileLock) {
+            long currTime = new Date().getTime();
+            boolean dayChanged =  ((currTime - mLastTime) >= (24*60*60*1000));
+            long currRealTime = SystemClock.elapsedRealtime();
+            if (((currRealTime-mLastWriteRealTime) < _FILE_WRITE_INTERVAL) &&
+                    (!dayChanged)) {
+                // wait till the next update
+                return;
+            }
+            // Get the most recent file
+            String todayStr = getCurrentDateStr(mFilePrefix);
+            // Copy current file to back up
+            File backupFile =  new File(mFile.getPath() + ".bak");
+            mFile.renameTo(backupFile);
+            try {
+                checkFileLimitFLOCK();
+                mFile.createNewFile();
+                // Write mStats to file
+                writeStatsFLOCK();
+                mLastWriteRealTime = currRealTime;
+                mLastTime = currTime;
+                if (dayChanged) {
+                    // clear stats
+                    synchronized (mStats) {
+                        mStats.clear();
+                    }
+                    mFile = new File(todayStr);
+                }
+                // Delete the backup file
+                if (backupFile != null) {
+                    backupFile.delete();
+                }
+            } catch (IOException e) {
+                Log.w(TAG, "Failed writing stats to file:" + mFile);
+                if (backupFile != null) {
+                    backupFile.renameTo(mFile);
+                }
+            }
+        }
+    }
+
+    private void writeStatsFLOCK() throws IOException {
+        FileOutputStream stream = new FileOutputStream(mFile);
+        Parcel out = Parcel.obtain();
+        writeStatsToParcelFLOCK(out);
+        stream.write(out.marshall());
+        out.recycle();
+        stream.flush();
+        stream.close();
+    }
+
+    private void writeStatsToParcelFLOCK(Parcel out) {
+        synchronized (mStatsLock) {
+            Set<String> keys = mStats.keySet();
+            for (String key : keys) {
+                PkgUsageStatsExtended pus = mStats.get(key);
+                out.writeString(key);
+                out.writeInt(pus.mLaunchCount);
+                out.writeLong(pus.mUsageTime);
+            }
+        }
+    }
+
     public void publish(Context context) {
         mContext = context;
         ServiceManager.addService(SERVICE_NAME, asBinder());
@@ -99,12 +332,14 @@ public final class UsageStatsService extends IUsageStats.Stub {
             return;
         } 
         if (localLOGV) Log.i(TAG, "started component:"+pkgName);
-        PkgUsageStatsExtended pus = mStats.get(pkgName);
-        if (pus == null) {
-            pus = new PkgUsageStatsExtended();
-            mStats.put(pkgName, pus);
+        synchronized (mStatsLock) {
+            PkgUsageStatsExtended pus = mStats.get(pkgName);
+            if (pus == null) {
+                pus = new PkgUsageStatsExtended();
+                mStats.put(pkgName, pus);
+            }
+            pus.updateResume();
         }
-        pus.updateResume();
         mResumedPkg = pkgName;
     }
 
@@ -120,13 +355,17 @@ public final class UsageStatsService extends IUsageStats.Stub {
             return;
         }
         if (localLOGV) Log.i(TAG, "paused component:"+pkgName);
-        PkgUsageStatsExtended pus = mStats.get(pkgName);
-        if (pus == null) {
-            // Weird some error here
-            Log.w(TAG, "No package stats for pkg:"+pkgName);
-            return;
+        synchronized (mStatsLock) {
+            PkgUsageStatsExtended pus = mStats.get(pkgName);
+            if (pus == null) {
+                // Weird some error here
+                Log.w(TAG, "No package stats for pkg:"+pkgName);
+                return;
+            }
+            pus.updatePause();
         }
-        pus.updatePause();
+        // Persist data to file
+        writeStatsToFile();
     }
     
     public void enforceCallingPermission() {
@@ -145,17 +384,19 @@ public final class UsageStatsService extends IUsageStats.Stub {
                 ((pkgName = componentName.getPackageName()) == null)) {
             return null;
         }
-        PkgUsageStatsExtended pus = mStats.get(pkgName);
-        if (pus == null) {
-            return null;
+        synchronized (mStatsLock) {
+            PkgUsageStatsExtended pus = mStats.get(pkgName);
+            if (pus == null) {
+               return null;
+            }
+            return new PkgUsageStats(pkgName, pus.mLaunchCount, pus.mUsageTime);
         }
-        return new PkgUsageStats(pkgName, pus.mLaunchCount, pus.mUsageTime);
     }
     
     public PkgUsageStats[] getAllPkgUsageStats() {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.PACKAGE_USAGE_STATS, null);
-        synchronized (mStats) {
+        synchronized (mStatsLock) {
             Set<String> keys = mStats.keySet();
             int size = keys.size();
             if (size <= 0) {
@@ -172,21 +413,120 @@ public final class UsageStatsService extends IUsageStats.Stub {
         }
     }
     
-    @Override
-    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+    static byte[] readFully(FileInputStream stream) throws java.io.IOException {
+        int pos = 0;
+        int avail = stream.available();
+        byte[] data = new byte[avail];
+        while (true) {
+            int amt = stream.read(data, pos, data.length-pos);
+            if (amt <= 0) {
+                return data;
+            }
+            pos += amt;
+            avail = stream.available();
+            if (avail > data.length-pos) {
+                byte[] newData = new byte[pos+avail];
+                System.arraycopy(data, 0, newData, 0, pos);
+                data = newData;
+            }
+        }
+    }
+    
+    private void collectDumpInfoFLOCK(PrintWriter pw, String[] args) {
+        List<String> fileList = getUsageStatsFileListFLOCK();
+        if (fileList == null) {
+            return;
+        }
+        final boolean isCheckinRequest = scanArgs(args, "-c");
+        Collections.sort(fileList);
+        File usageFile = new File(mFilePrefix);
+        String dirName = usageFile.getParent();
+        File dir = new File(dirName);
+        String filePrefix = usageFile.getName();
+        // file name followed by dot
+        int prefixLen = filePrefix.length()+1;
+        String todayStr = getCurrentDateStr(null);
+        for (String file : fileList) {
+            File dFile = new File(dir, file);
+            String dateStr = file.substring(prefixLen);
+            try {
+                Parcel in = getParcelForFile(dFile);
+                collectDumpInfoFromParcelFLOCK(in, pw, dateStr, isCheckinRequest);
+                if (isCheckinRequest && !todayStr.equalsIgnoreCase(dateStr)) {
+                    // Delete old file after collecting info only for checkin requests
+                    dFile.delete();
+                }
+            } catch (FileNotFoundException e) {
+                Log.w(TAG, "Failed with "+e+" when collecting dump info from file : " + file);
+                return;
+            } catch (IOException e) {
+                Log.w(TAG, "Failed with "+e+" when collecting dump info from file : "+file);
+            }      
+        }
+    }
+    
+    private void collectDumpInfoFromParcelFLOCK(Parcel in, PrintWriter pw,
+            String date, boolean isCheckinRequest) {
         StringBuilder sb = new StringBuilder();
-        synchronized (mStats) {
-            Set<String> keys = mStats.keySet();
-            for (String key: keys) {
-                PkgUsageStatsExtended ps = mStats.get(key);
-                sb.append("pkg="); 
-                sb.append(key);
+        sb.append("Date:");
+        sb.append(date);
+        boolean first = true;
+        while (in.dataAvail() > 0) {
+            String pkgName = in.readString();
+            int launchCount = in.readInt();
+            long usageTime = in.readLong();
+            if (isCheckinRequest) {
+                if (!first) {
+                    sb.append(",");
+                }
+                sb.append(pkgName);
+                sb.append(",");
+                sb.append(launchCount);
+                sb.append(",");
+                sb.append(usageTime);
+                sb.append("ms");
+            } else {
+                if (first) {
+                    sb.append("\n");
+                }
+                sb.append("pkg=");
+                sb.append(pkgName);
                 sb.append(", launchCount=");
-                sb.append(ps.mLaunchCount);
+                sb.append(launchCount);
                 sb.append(", usageTime=");
-                sb.append(ps.mUsageTime+" ms\n");
+                sb.append(usageTime);
+                sb.append(" ms\n");
             }
+            first = false;
         }
         pw.write(sb.toString());
     }
+    
+    /**
+     * Searches array of arguments for the specified string
+     * @param args array of argument strings
+     * @param value value to search for
+     * @return true if the value is contained in the array
+     */
+    private static boolean scanArgs(String[] args, String value) {
+        if (args != null) {
+            for (String arg : args) {
+                if (value.equals(arg)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+    
+    @Override
+    /*
+     * The data persisted to file is parsed and the stats are computed. 
+     */
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        synchronized (mFileLock) {
+            collectDumpInfoFLOCK(pw, args);
+        }
+    }
+
 }
diff --git a/tests/AndroidTests/AndroidManifest.xml b/tests/AndroidTests/AndroidManifest.xml
index 230456a8dd66..36f7b9be52df 100644
--- a/tests/AndroidTests/AndroidManifest.xml
+++ b/tests/AndroidTests/AndroidManifest.xml
@@ -44,6 +44,7 @@
     <uses-permission android:name="android.permission.CLEAR_APP_CACHE" />
     <uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" />
     <uses-permission android:name="android.permission.GET_PACKAGE_SIZE" />
+    <uses-permission android:name="android.permission.BLUETOOTH" />
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
     <uses-permission android:name="android.permission.INTERNET" />
diff --git a/tests/AndroidTests/src/com/android/unit_tests/MenuTest.java b/tests/AndroidTests/src/com/android/unit_tests/MenuTest.java
index d184543dfb25..c436726a0fc8 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/MenuTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/MenuTest.java
@@ -131,20 +131,7 @@ public class MenuTest extends AndroidTestCase {
                                               makeKeyEvent(KeyEvent.KEYCODE_A,
                                                            KeyEvent.META_SYM_ON)));
     }
-
-    @LargeTest
-    public void testIsNotShortcutWithMultipleMetas() throws Exception {
-        mMenu.setQwertyMode(true);
-        mMenu.add(0, 0, 0, "test").setShortcut('2', 'a');
-        Assert.assertFalse(mMenu.isShortcutKey(
-                'a',
-                makeKeyEvent(KeyEvent.KEYCODE_A, KeyEvent.META_SYM_ON & KeyEvent.META_ALT_ON)));
-        Assert.assertFalse(mMenu.isShortcutKey(
-                'a', makeKeyEvent(KeyEvent.KEYCODE_A, KeyEvent.META_SYM_ON)));
-        Assert.assertFalse(mMenu.isShortcutKey(
-                'a', makeKeyEvent(KeyEvent.KEYCODE_A, KeyEvent.META_SHIFT_ON)));
-    }
-
+    
     @SmallTest
     public void testIsShortcutWithUpperCaseAlpha() throws Exception {
         mMenu.setQwertyMode(true);
diff --git a/tests/AndroidTests/src/com/android/unit_tests/TextUtilsTest.java b/tests/AndroidTests/src/com/android/unit_tests/TextUtilsTest.java
index 8c1c91f4cd31..51e841cb8d3a 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/TextUtilsTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/TextUtilsTest.java
@@ -262,7 +262,7 @@ public class TextUtilsTest extends TestCase {
         Map<String, String> fixes = Maps.newHashMap();
         fixes.put("a", "<a@gmail.com>");
         fixes.put("a b", "<ab@gmail.com>");
-        fixes.put("a@b", "<a@gmail.com>");
+        fixes.put("a@b", "<a@b>");
         
         for (Map.Entry<String, String> e : fixes.entrySet()) {
             assertEquals(e.getValue(), validator.fixText(e.getKey()).toString());
diff --git a/tests/DumpRenderTree/compare_layout_results.py b/tests/DumpRenderTree/compare_layout_results.py
index 4383dbbd2d11..c4285f1e7d78 100644
--- a/tests/DumpRenderTree/compare_layout_results.py
+++ b/tests/DumpRenderTree/compare_layout_results.py
@@ -6,6 +6,7 @@ results to a file.
 
 import optparse
 import os
+import sys
 
 def DiffResults(marker, new_results, old_results, diff_results, strip_reason):
    """ Given two result files, generate diff and
@@ -45,7 +46,7 @@ def DiffResults(marker, new_results, old_results, diff_results, strip_reason):
        diff_file.writelines("- " + line)
        missing_count += 1
 
-   print marker + "  >>> New = " + str(new_count) + " , Missing = " + str(missing_count) 
+   print marker + "  >>> added " + str(new_count) + " tests, removed " + str(missing_count) + " tests" 
 
    diff_file.writelines("\n\n")
 
@@ -55,24 +56,32 @@ def DiffResults(marker, new_results, old_results, diff_results, strip_reason):
    return
 
 def main(options, args):
-  results_dir = options.results_directory
+  results_dir = os.path.abspath(options.results_directory)
   ref_dir = options.ref_directory
-  if os.path.exists(results_dir + "/layout_tests_diff.txt"):
-    os.remove(results_dir + "/layout_tests_diff.txt")
 
-  files=["passed", "nontext", "crashed"]
-  for f in files:
-    DiffResults(f, results_dir + "layout_tests_" + f + ".txt",
-              ref_dir + "layout_tests_" + f + ".txt", results_dir + "layout_tests_diff.txt", False)
+  # if ref_dir is null, cannonify ref_dir to the script dir.
+  if not ref_dir:
+    script_self = sys.argv[0]
+    script_dir = os.path.dirname(script_self)
+    ref_dir = os.path.join(script_dir, "results")
+
+  ref_dir = os.path.abspath(ref_dir)
 
-  for f in ["failed"]:
-    DiffResults(f, results_dir + "layout_tests_" + f + ".txt",
-              ref_dir + "layout_tests_" + f + ".txt", results_dir + "layout_tests_diff.txt", True)
+  diff_result = os.path.join(results_dir, "layout_tests_diff.txt") 
+  if os.path.exists(diff_result):
+    os.remove(diff_result)
+
+  files=["passed", "failed", "nontext", "crashed"]
+  for f in files:
+    result_file_name = "layout_tests_" + f + ".txt"
+    DiffResults(f, os.path.join(results_dir, result_file_name),
+                os.path.join(ref_dir, result_file_name), diff_result,
+                f == "failed")
 
 if '__main__' == __name__:
   option_parser = optparse.OptionParser()
   option_parser.add_option("", "--ref-directory",
-                           default="results/",
+                           default=None,
                            dest="ref_directory",
                            help="directory name under which results are stored.")
 
diff --git a/tests/DumpRenderTree/run_layout_tests.py b/tests/DumpRenderTree/run_layout_tests.py
index b4eb685068b6..433271e38104 100755
--- a/tests/DumpRenderTree/run_layout_tests.py
+++ b/tests/DumpRenderTree/run_layout_tests.py
@@ -48,6 +48,86 @@ def CountLineNumber(filename):
   fp.close()
   return lines
 
+def DumpRenderTreeFinished(adb_cmd):
+  """ Check if DumpRenderTree finished running tests
+  
+  Args:
+    output: adb_cmd string
+  """
+  
+  # pull /sdcard/running_test.txt, if the content is "#DONE", it's done
+  shell_cmd_str = adb_cmd + " shell cat /sdcard/running_test.txt"
+  adb_output = subprocess.Popen(shell_cmd_str, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
+  return adb_output.strip() == "#DONE"
+
+def DiffResults(marker, new_results, old_results, diff_results, strip_reason):
+   """ Given two result files, generate diff and
+       write to diff_results file. All arguments are absolute paths
+       to files.
+   """
+   old_file = open(old_results, "r")
+   new_file = open(new_results, "r")
+   diff_file = open(diff_results, "a") 
+
+   # Read lines from each file
+   ndict = new_file.readlines()
+   cdict = old_file.readlines()
+
+   # Write marker to diff file
+   diff_file.writelines(marker + "\n")
+   diff_file.writelines("###############\n")
+
+   # Strip reason from result lines
+   if strip_reason is True:
+     for i in range(0, len(ndict)):
+       ndict[i] = ndict[i].split(' ')[0] + "\n"
+     for i in range(0, len(cdict)):
+       cdict[i] = cdict[i].split(' ')[0] + "\n"
+
+   # Find results in new_results missing in old_results
+   new_count=0
+   for line in ndict:
+     if line not in cdict:
+       diff_file.writelines("+ " + line)
+       new_count += 1
+
+   # Find results in old_results missing in new_results
+   missing_count=0
+   for line in cdict:
+     if line not in ndict:
+       diff_file.writelines("- " + line)
+       missing_count += 1
+
+   logging.info(marker + "  >>> " + str(new_count) + " new, " + str(missing_count) + " misses")
+
+   diff_file.writelines("\n\n")
+
+   old_file.close()
+   new_file.close()
+   diff_file.close()
+   return
+
+def CompareResults(ref_dir, results_dir):
+  """Compare results in two directories
+
+  Args:
+    ref_dir: the reference directory having layout results as references
+    results_dir: the results directory
+  """
+  logging.info("Comparing results to " + ref_dir)
+
+  diff_result = os.path.join(results_dir, "layout_tests_diff.txt") 
+  if os.path.exists(diff_result):
+    os.remove(diff_result)
+
+  files=["passed", "failed", "nontext", "crashed"]
+  for f in files:
+    result_file_name = "layout_tests_" + f + ".txt"
+    DiffResults(f, os.path.join(results_dir, result_file_name),
+                os.path.join(ref_dir, result_file_name), diff_result,
+                f == "failed")
+  logging.info("Detailed diffs are in " + diff_result)
+
 def main(options, args):
   """Run the tests. Will call sys.exit when complete.
   
@@ -84,7 +164,7 @@ def main(options, args):
        sys.exit(1)
 
 
-  logging.info("Starting tests")
+  logging.info("Running tests")
 
   # Count crashed tests.
   crashed_tests = []
@@ -98,7 +178,7 @@ def main(options, args):
   # Call LayoutTestsAutoTest::startLayoutTests.
   shell_cmd_str = adb_cmd + " shell am instrument -e class com.android.dumprendertree.LayoutTestsAutoTest#startLayoutTests -e path \"" + path + "\" -e timeout " + timeout_ms + " -w com.android.dumprendertree/.LayoutTestsAutoRunner"
   adb_output = subprocess.Popen(shell_cmd_str, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
-  while adb_output.find('Process crashed') != -1:
+  while not DumpRenderTreeFinished(adb_cmd):
     # Get the running_test.txt
     logging.error("DumpRenderTree crashed, output:\n" + adb_output)
 
@@ -118,8 +198,8 @@ def main(options, args):
     logging.error("Error happened : " + adb_output)
     sys.exit(1)
 
-  logging.info("Done");
   logging.debug(adb_output);
+  logging.info("Done\n");
 
   # Pull results from /sdcard
   results_dir = options.results_directory
@@ -152,8 +232,21 @@ def main(options, args):
   nontext_tests = CountLineNumber(results_dir + "/layout_tests_nontext.txt")
   logging.info(str(nontext_tests) + " no dumpAsText")
 
-  logging.info("Results are stored under: " + results_dir)
+  logging.info("Results are stored under: " + results_dir + "\n")
+
+  # Comparing results to references to find new fixes and regressions.
+  results_dir = os.path.abspath(options.results_directory)
+  ref_dir = options.ref_directory
 
+  # if ref_dir is null, cannonify ref_dir to the script dir.
+  if not ref_dir:
+    script_self = sys.argv[0]
+    script_dir = os.path.dirname(script_self)
+    ref_dir = os.path.join(script_dir, "results")
+
+  ref_dir = os.path.abspath(ref_dir)
+
+  CompareResults(ref_dir, results_dir)
 
 if '__main__' == __name__:
   option_parser = optparse.OptionParser()
@@ -171,6 +264,11 @@ if '__main__' == __name__:
                            help="pass options to adb, such as -d -e, etc");
   option_parser.add_option("", "--results-directory",
                            default="layout-test-results",
-                           help="directory name under which results are stored.")
+                           help="directory which results are stored.")
+  option_parser.add_option("", "--ref-directory",
+                           default=None,
+                           dest="ref_directory",
+                           help="directory where reference results are stored.")
+
   options, args = option_parser.parse_args();
   main(options, args)
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostActivity.java
index c77d98ae55c9..86bfad7cb8bd 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/HTMLHostActivity.java
@@ -68,9 +68,12 @@ class TestRecorder {
       }
     }
 
-    public void nontext(String layout_file) {
+    public void nontext(String layout_file, boolean has_results) {
       try {
           mBufferedOutputNontextStream.write(layout_file.getBytes());
+          if (has_results) {
+              mBufferedOutputNontextStream.write(" : has expected results".getBytes());
+          }
           mBufferedOutputNontextStream.write('\n');
           mBufferedOutputNontextStream.flush();
       } catch(Exception e) {
@@ -299,6 +302,9 @@ public class HTMLHostActivity extends Activity
         resetTestStatus();
 
         if (testIndex == mTestList.size()) {
+            if (!mSingleTestMode) {
+                updateTestStatus("#DONE");
+            }
             finished();
             return;
         }
@@ -385,9 +391,9 @@ public class HTMLHostActivity extends Activity
         }
     }
 
-    public void nontextCase(String file) {
+    public void nontextCase(String file, boolean has_expected_results) {
         Log.v("Layout test:", file + " nontext");
-        mResultRecorder.nontext(file);
+        mResultRecorder.nontext(file, has_expected_results);
     }
  
     public void setCallback(HTMLHostCallbackInterface callback) {
@@ -447,8 +453,11 @@ public class HTMLHostActivity extends Activity
         }
         
         File nontext_result = new File(short_file + "-android-results.txt");
-        if (nontext_result.exists())
-            mResultRecorder.nontext(test_path);
+        if (nontext_result.exists()) {
+            // Check if the test has expected results.
+            File expected = new File(short_file + "-expected.txt");
+            nontextCase(test_path, expected.exists());
+        }
     }
     
     public void finished() {
diff --git a/tests/ImfTest/AndroidManifest.xml b/tests/ImfTest/AndroidManifest.xml
index 627ee6dc3dcb..55e5d386a235 100755
--- a/tests/ImfTest/AndroidManifest.xml
+++ b/tests/ImfTest/AndroidManifest.xml
@@ -19,7 +19,7 @@
             </intent-filter>
         </activity>
         
-        <activity android:name=".samples.AppAdjustmentBigEditTextNonScrollablePanScan" android:label="Big ET !Scroll Pan/Scan">
+        <activity android:name=".samples.BigEditTextActivityNonScrollablePanScan" android:label="Big ET !Scroll Pan/Scan">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.LAUNCHER" />
@@ -35,7 +35,7 @@
             </intent-filter>
         </activity>
         
-        <activity android:name=".samples.AppAdjustmentBigEditTextNonScrollableResize" android:label="Big ET !Scroll Resize">
+        <activity android:name=".samples.BigEditTextActivityNonScrollableResize" android:label="Big ET !Scroll Resize">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.LAUNCHER" />
@@ -43,7 +43,7 @@
             </intent-filter>
         </activity>
         
-        <activity android:name=".samples.AppAdjustmentBigEditTextScrollablePanScan" android:label="Big ET Scroll Pan/Scan">
+        <activity android:name=".samples.BigEditTextActivityScrollablePanScan" android:label="Big ET Scroll Pan/Scan">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.LAUNCHER" />
@@ -51,7 +51,7 @@
             </intent-filter>
         </activity>
         
-        <activity android:name=".samples.AppAdjustmentBigEditTextScrollableResize" android:label="Big ET Scroll Resize">
+        <activity android:name=".samples.BigEditTextActivityScrollableResize" android:label="Big ET Scroll Resize">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.LAUNCHER" />
@@ -59,7 +59,7 @@
             </intent-filter>
         </activity>
 
-        <activity android:name=".samples.AppAdjustmentEditTextDialog" android:label="ET Dialog">
+        <activity android:name=".samples.EditTextActivityDialog" android:label="ET Dialog">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.LAUNCHER" />
@@ -130,14 +130,6 @@
                 <category android:name="android.intent.category.IMF_TEST" />
             </intent-filter>
         </activity>   
-          
-        <activity android:name=".samples.OneEditTextActivityLandscape" android:label="OneEditTextActivityLandscape" android:screenOrientation="landscape">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN"/>
-                <category android:name="android.intent.category.LAUNCHER" />
-                <category android:name="android.intent.category.IMF_TEST" />
-            </intent-filter>
-        </activity>  
         
         <activity android:name=".samples.DialogActivity" android:label="DialogActivity" android:screenOrientation="portrait">
             <intent-filter>
diff --git a/tests/ImfTest/res/values/config.xml b/tests/ImfTest/res/values/config.xml
new file mode 100644
index 000000000000..5ae40a381523
--- /dev/null
+++ b/tests/ImfTest/res/values/config.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); 
+ * you may not use this file except in compliance with the License. 
+ * You may obtain a copy of the License at 
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0 
+ *
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+-->
+<resources>
+    <bool name="def_expect_ime_autopop">false</bool>
+</resources>
diff --git a/tests/ImfTest/src/com/android/imftest/samples/AppAdjustmentBigEditTextNonScrollablePanScan.java b/tests/ImfTest/src/com/android/imftest/samples/AppAdjustmentBigEditTextNonScrollablePanScan.java
deleted file mode 100644
index 15a29c800928..000000000000
--- a/tests/ImfTest/src/com/android/imftest/samples/AppAdjustmentBigEditTextNonScrollablePanScan.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.android.imftest.samples;
-
-import com.android.imftest.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.widget.EditText;
-import android.widget.LinearLayout;
-
-public class AppAdjustmentBigEditTextNonScrollablePanScan extends Activity {
-    
-    private LinearLayout mLayout;
-    
-    @Override
-    protected void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-        
-        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
-        
-        mLayout = new LinearLayout(this);
-        mLayout.setOrientation(LinearLayout.VERTICAL);
-        mLayout.setLayoutParams(new ViewGroup.LayoutParams(
-                ViewGroup.LayoutParams.FILL_PARENT,
-                ViewGroup.LayoutParams.FILL_PARENT));
-        
-        EditText editText = (EditText) getLayoutInflater().inflate(R.layout.full_screen_edit_text, mLayout, false);
-        
-        mLayout.addView(editText);
-        
-        setContentView(mLayout);
-    }
-
-}
diff --git a/tests/ImfTest/src/com/android/imftest/samples/AppAdjustmentBigEditTextNonScrollableResize.java b/tests/ImfTest/src/com/android/imftest/samples/AppAdjustmentBigEditTextNonScrollableResize.java
deleted file mode 100644
index 07268235670f..000000000000
--- a/tests/ImfTest/src/com/android/imftest/samples/AppAdjustmentBigEditTextNonScrollableResize.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.android.imftest.samples;
-
-import com.android.imftest.R;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.widget.EditText;
-import android.widget.LinearLayout;
-
-public class AppAdjustmentBigEditTextNonScrollableResize extends Activity {
-    
-    private LinearLayout mLayout;
-    
-    @Override
-    protected void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-        
-        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
-        
-        mLayout = new LinearLayout(this);
-        mLayout.setOrientation(LinearLayout.VERTICAL);
-        mLayout.setLayoutParams(new ViewGroup.LayoutParams(
-                ViewGroup.LayoutParams.FILL_PARENT,
-                ViewGroup.LayoutParams.FILL_PARENT));
-        
-        EditText editText = (EditText) getLayoutInflater().inflate(R.layout.full_screen_edit_text, mLayout, false);
-        
-        mLayout.addView(editText);
-        
-        setContentView(mLayout);
-    }
-
-}
diff --git a/tests/ImfTest/src/com/android/imftest/samples/BigEditTextActivityNonScrollablePanScan.java b/tests/ImfTest/src/com/android/imftest/samples/BigEditTextActivityNonScrollablePanScan.java
new file mode 100644
index 000000000000..9754381e2ce3
--- /dev/null
+++ b/tests/ImfTest/src/com/android/imftest/samples/BigEditTextActivityNonScrollablePanScan.java
@@ -0,0 +1,49 @@
+package com.android.imftest.samples;
+
+import com.android.imftest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+
+public class BigEditTextActivityNonScrollablePanScan extends Activity {
+    
+    private View mRootView;
+    private View mDefaultFocusedView;
+    
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        
+        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
+        
+        mRootView = new LinearLayout(this);
+        ((LinearLayout) mRootView).setOrientation(LinearLayout.VERTICAL);
+        mRootView.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                ViewGroup.LayoutParams.FILL_PARENT));
+        
+        View view = getLayoutInflater().inflate(
+                R.layout.full_screen_edit_text, ((LinearLayout) mRootView), false);
+        
+        ((LinearLayout) mRootView).addView(view);
+        
+        mDefaultFocusedView = view.findViewById(R.id.data);
+        
+        setContentView(mRootView);
+    }
+
+    public View getRootView() {
+        return mRootView;
+    }
+    
+    public View getDefaultFocusedView() {
+        return mDefaultFocusedView;
+    }
+
+}
diff --git a/tests/ImfTest/src/com/android/imftest/samples/BigEditTextActivityNonScrollableResize.java b/tests/ImfTest/src/com/android/imftest/samples/BigEditTextActivityNonScrollableResize.java
new file mode 100644
index 000000000000..701795fe4a7b
--- /dev/null
+++ b/tests/ImfTest/src/com/android/imftest/samples/BigEditTextActivityNonScrollableResize.java
@@ -0,0 +1,49 @@
+package com.android.imftest.samples;
+
+import com.android.imftest.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+
+public class BigEditTextActivityNonScrollableResize extends Activity {
+    
+    private View mRootView;
+    private View mDefaultFocusedView;
+    
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        
+        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
+        
+        mRootView = new LinearLayout(this);
+        ((LinearLayout) mRootView).setOrientation(LinearLayout.VERTICAL);
+        mRootView.setLayoutParams(new ViewGroup.LayoutParams(
+                ViewGroup.LayoutParams.FILL_PARENT,
+                ViewGroup.LayoutParams.FILL_PARENT));
+        
+        View view = getLayoutInflater().inflate(
+                R.layout.full_screen_edit_text, ((LinearLayout) mRootView), false);
+        
+        ((LinearLayout) mRootView).addView(view);
+        
+        mDefaultFocusedView = view.findViewById(R.id.data);
+        
+        setContentView(mRootView);
+    }
+
+    public View getRootView() {
+        return mRootView;
+    }
+    
+    public View getDefaultFocusedView() {
+        return mDefaultFocusedView;
+    }
+
+}
diff --git a/tests/ImfTest/src/com/android/imftest/samples/AppAdjustmentBigEditTextScrollablePanScan.java b/tests/ImfTest/src/com/android/imftest/samples/BigEditTextActivityScrollablePanScan.java
similarity index 54%
rename from tests/ImfTest/src/com/android/imftest/samples/AppAdjustmentBigEditTextScrollablePanScan.java
rename to tests/ImfTest/src/com/android/imftest/samples/BigEditTextActivityScrollablePanScan.java
index 50a980b325c6..bb3f7671a860 100644
--- a/tests/ImfTest/src/com/android/imftest/samples/AppAdjustmentBigEditTextScrollablePanScan.java
+++ b/tests/ImfTest/src/com/android/imftest/samples/BigEditTextActivityScrollablePanScan.java
@@ -4,15 +4,17 @@ import com.android.imftest.R;
 
 import android.app.Activity;
 import android.os.Bundle;
+import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.widget.EditText;
 import android.widget.LinearLayout;
 import android.widget.ScrollView;
 
-public class AppAdjustmentBigEditTextScrollablePanScan extends Activity {
+public class BigEditTextActivityScrollablePanScan extends Activity {
     
-    private ScrollView mScrollView;
+    private View mRootView;
+    private View mDefaultFocusedView;
     private LinearLayout mLayout;
     
     @Override
@@ -21,9 +23,9 @@ public class AppAdjustmentBigEditTextScrollablePanScan extends Activity {
         
         getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
         
-        mScrollView = new ScrollView(this);
-        mScrollView.setFillViewport(true);
-        mScrollView.setLayoutParams(new ViewGroup.LayoutParams(
+        mRootView = new ScrollView(this);
+        ((ScrollView) mRootView).setFillViewport(true);
+        mRootView.setLayoutParams(new ViewGroup.LayoutParams(
                 ViewGroup.LayoutParams.FILL_PARENT,
                 ViewGroup.LayoutParams.FILL_PARENT));
         
@@ -33,12 +35,23 @@ public class AppAdjustmentBigEditTextScrollablePanScan extends Activity {
                 ViewGroup.LayoutParams.FILL_PARENT,
                 ViewGroup.LayoutParams.FILL_PARENT));
         
-        EditText editText = (EditText) getLayoutInflater().inflate(R.layout.full_screen_edit_text, mScrollView, false);
+        View view = getLayoutInflater().inflate(
+                R.layout.full_screen_edit_text, ((ScrollView) mRootView), false);
         
-        mLayout.addView(editText);
-        mScrollView.addView(mLayout);
+        mLayout.addView(view);
         
-        setContentView(mScrollView);
+        ((ScrollView) mRootView).addView(mLayout);
+        mDefaultFocusedView = view.findViewById(R.id.data);
+        
+        setContentView(mRootView);
+    }
+
+    public View getRootView() {
+        return mRootView;
+    }
+    
+    public View getDefaultFocusedView() {
+        return mDefaultFocusedView;
     }
 
 }
diff --git a/tests/ImfTest/src/com/android/imftest/samples/AppAdjustmentBigEditTextScrollableResize.java b/tests/ImfTest/src/com/android/imftest/samples/BigEditTextActivityScrollableResize.java
similarity index 54%
rename from tests/ImfTest/src/com/android/imftest/samples/AppAdjustmentBigEditTextScrollableResize.java
rename to tests/ImfTest/src/com/android/imftest/samples/BigEditTextActivityScrollableResize.java
index a256878c5573..f2cae1cdfca7 100644
--- a/tests/ImfTest/src/com/android/imftest/samples/AppAdjustmentBigEditTextScrollableResize.java
+++ b/tests/ImfTest/src/com/android/imftest/samples/BigEditTextActivityScrollableResize.java
@@ -4,15 +4,17 @@ import com.android.imftest.R;
 
 import android.app.Activity;
 import android.os.Bundle;
+import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.widget.EditText;
 import android.widget.LinearLayout;
 import android.widget.ScrollView;
 
-public class AppAdjustmentBigEditTextScrollableResize extends Activity {
+public class BigEditTextActivityScrollableResize extends Activity {
     
-    private ScrollView mScrollView;
+    private View mRootView;
+    private View mDefaultFocusedView;
     private LinearLayout mLayout;
     
     @Override
@@ -21,9 +23,9 @@ public class AppAdjustmentBigEditTextScrollableResize extends Activity {
         
         getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
         
-        mScrollView = new ScrollView(this);
-        mScrollView.setFillViewport(true);
-        mScrollView.setLayoutParams(new ViewGroup.LayoutParams(
+        mRootView = new ScrollView(this);
+        ((ScrollView) mRootView).setFillViewport(true);
+        mRootView.setLayoutParams(new ViewGroup.LayoutParams(
                 ViewGroup.LayoutParams.FILL_PARENT,
                 ViewGroup.LayoutParams.FILL_PARENT));
         
@@ -33,12 +35,23 @@ public class AppAdjustmentBigEditTextScrollableResize extends Activity {
                 ViewGroup.LayoutParams.FILL_PARENT,
                 ViewGroup.LayoutParams.FILL_PARENT));
         
-        EditText editText = (EditText) getLayoutInflater().inflate(R.layout.full_screen_edit_text, mScrollView, false);
+        View view = getLayoutInflater().inflate(
+                R.layout.full_screen_edit_text, ((ScrollView) mRootView), false);
         
-        mLayout.addView(editText);
-        mScrollView.addView(mLayout);
+        mLayout.addView(view);
         
-        setContentView(mScrollView);
+        ((ScrollView) mRootView).addView(mLayout);
+        mDefaultFocusedView = view.findViewById(R.id.data);
+        
+        setContentView(mRootView);
+    }
+
+    public View getRootView() {
+        return mRootView;
+    }
+    
+    public View getDefaultFocusedView() {
+        return mDefaultFocusedView;
     }
 
 }
diff --git a/tests/ImfTest/src/com/android/imftest/samples/BottomEditTextActivityPanScan.java b/tests/ImfTest/src/com/android/imftest/samples/BottomEditTextActivityPanScan.java
index d74b9dd9d9eb..51f5045ea202 100644
--- a/tests/ImfTest/src/com/android/imftest/samples/BottomEditTextActivityPanScan.java
+++ b/tests/ImfTest/src/com/android/imftest/samples/BottomEditTextActivityPanScan.java
@@ -17,21 +17,30 @@ import com.android.imftest.R;
  */
 public class BottomEditTextActivityPanScan extends Activity 
 {
-    private LayoutInflater mInflater;
+    private View mRootView;
+    private View mDefaultFocusedView;
+    
     @Override
     public void onCreate(Bundle savedInstanceState) 
     {
         super.onCreate(savedInstanceState);
         
-        LinearLayout layout = new LinearLayout(this);
-        layout.setOrientation(LinearLayout.VERTICAL);
+        mRootView = new LinearLayout(this);
+        ((LinearLayout) mRootView).setOrientation(LinearLayout.VERTICAL);
         
-        mInflater = getLayoutInflater();
-        
-        View view = mInflater.inflate(R.layout.one_edit_text_activity, layout, false);
-        layout.addView(view);
+        View view = getLayoutInflater().inflate(R.layout.one_edit_text_activity, ((LinearLayout) mRootView), false);
+        mDefaultFocusedView = view.findViewById(R.id.dialog_edit_text);
+        ((LinearLayout) mRootView).addView(view);
        
-        setContentView(layout);
+        setContentView(mRootView);
         this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
     }  
+
+    public View getRootView() {
+        return mRootView;
+    }
+    
+    public View getDefaultFocusedView() {
+        return mDefaultFocusedView;
+    }
 }
\ No newline at end of file
diff --git a/tests/ImfTest/src/com/android/imftest/samples/BottomEditTextActivityResize.java b/tests/ImfTest/src/com/android/imftest/samples/BottomEditTextActivityResize.java
index 82da29a3af38..eb94b4f2ee38 100644
--- a/tests/ImfTest/src/com/android/imftest/samples/BottomEditTextActivityResize.java
+++ b/tests/ImfTest/src/com/android/imftest/samples/BottomEditTextActivityResize.java
@@ -17,21 +17,30 @@ import com.android.imftest.R;
  */
 public class BottomEditTextActivityResize extends Activity 
 {
-    private LayoutInflater mInflater;
+    private View mRootView;
+    private View mDefaultFocusedView;
+    
     @Override
     public void onCreate(Bundle savedInstanceState) 
     {
         super.onCreate(savedInstanceState);
         
-        LinearLayout layout = new LinearLayout(this);
-        layout.setOrientation(LinearLayout.VERTICAL);
+        mRootView = new LinearLayout(this);
+        ((LinearLayout) mRootView).setOrientation(LinearLayout.VERTICAL);
         
-        mInflater = getLayoutInflater();
-        
-        View view = mInflater.inflate(R.layout.one_edit_text_activity, layout, false);
-        layout.addView(view);
+        View view = getLayoutInflater().inflate(R.layout.one_edit_text_activity, ((LinearLayout) mRootView), false);
+        mDefaultFocusedView = view.findViewById(R.id.dialog_edit_text);
+        ((LinearLayout) mRootView).addView(view);
        
-        setContentView(layout);
+        setContentView(mRootView);
         this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
     }  
+
+    public View getRootView() {
+        return mRootView;
+    }
+    
+    public View getDefaultFocusedView() {
+        return mDefaultFocusedView;
+    }
 }
\ No newline at end of file
diff --git a/tests/ImfTest/src/com/android/imftest/samples/ButtonActivity.java b/tests/ImfTest/src/com/android/imftest/samples/ButtonActivity.java
index 4233811a60ed..1191f198198a 100644
--- a/tests/ImfTest/src/com/android/imftest/samples/ButtonActivity.java
+++ b/tests/ImfTest/src/com/android/imftest/samples/ButtonActivity.java
@@ -13,6 +13,8 @@ import android.widget.TextView;
 public class ButtonActivity extends Activity 
 {
     static boolean mKeyboardIsActive = false;
+    public static final int BUTTON_ID = 0;
+    private View mRootView;
     
     @Override
     public void onCreate(Bundle savedInstanceState) 
@@ -23,6 +25,8 @@ public class ButtonActivity extends Activity
         final Button myButton = new Button(this);
         myButton.setClickable(true);
         myButton.setText("Keyboard UP!");
+        myButton.setId(BUTTON_ID);
+        myButton.setFocusableInTouchMode(true);
         myButton.setOnClickListener(new View.OnClickListener()
         {
             public void onClick (View v)
@@ -36,7 +40,8 @@ public class ButtonActivity extends Activity
                 }
                 else
                 {
-                    imm.showSoftInput(null, 0);
+                    myButton.requestFocusFromTouch();
+                    imm.showSoftInput(v, 0);
                     myButton.setText("Keyboard DOWN!");
                 }
                
@@ -48,5 +53,10 @@ public class ButtonActivity extends Activity
        layout.setOrientation(LinearLayout.VERTICAL);
        layout.addView(myButton);
        setContentView(layout);
+       mRootView = layout;
+    }
+    
+    public View getRootView() {
+        return mRootView;
     }
 }
diff --git a/tests/ImfTest/src/com/android/imftest/samples/AppAdjustmentEditTextDialog.java b/tests/ImfTest/src/com/android/imftest/samples/EditTextActivityDialog.java
similarity index 88%
rename from tests/ImfTest/src/com/android/imftest/samples/AppAdjustmentEditTextDialog.java
rename to tests/ImfTest/src/com/android/imftest/samples/EditTextActivityDialog.java
index e82f1d50238c..bd1e934364f6 100644
--- a/tests/ImfTest/src/com/android/imftest/samples/AppAdjustmentEditTextDialog.java
+++ b/tests/ImfTest/src/com/android/imftest/samples/EditTextActivityDialog.java
@@ -14,7 +14,7 @@ import android.widget.EditText;
 import android.widget.LinearLayout;
 import android.widget.ScrollView;
 
-public class AppAdjustmentEditTextDialog extends Activity {
+public class EditTextActivityDialog extends Activity {
     
     private static final int SCROLLABLE_DIALOG_ID = 0;
     private static final int NONSCROLLABLE_DIALOG_ID = 1;
@@ -75,18 +75,18 @@ public class AppAdjustmentEditTextDialog extends Activity {
         EditText editText;
         
         if (scrollable) {
-            layout = new ScrollView(AppAdjustmentEditTextDialog.this);
+            layout = new ScrollView(EditTextActivityDialog.this);
             ((ScrollView) layout).setMinimumHeight(mLayout.getHeight());
             
             ((ScrollView) layout).addView((
-                    LinearLayout) View.inflate(AppAdjustmentEditTextDialog.this, 
+                    LinearLayout) View.inflate(EditTextActivityDialog.this, 
                     R.layout.dialog_edit_text_no_scroll, null));
         } else {
-            layout = View.inflate(AppAdjustmentEditTextDialog.this, 
+            layout = View.inflate(EditTextActivityDialog.this, 
                     R.layout.dialog_edit_text_no_scroll, null);
         }
         
-        Dialog d = new Dialog(AppAdjustmentEditTextDialog.this);
+        Dialog d = new Dialog(EditTextActivityDialog.this);
         d.setTitle(getString(R.string.test_dialog));
         d.setCancelable(true);
         d.setContentView(layout);
diff --git a/tests/ImfTest/src/com/android/imftest/samples/EditTextActivityNoScrollPanScan.java b/tests/ImfTest/src/com/android/imftest/samples/EditTextActivityNoScrollPanScan.java
deleted file mode 100644
index b59602310856..000000000000
--- a/tests/ImfTest/src/com/android/imftest/samples/EditTextActivityNoScrollPanScan.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.android.imftest.samples;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.widget.LinearLayout;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.EditText;
-import android.widget.Button;
-import android.widget.TextView;
-import android.widget.ScrollView;
-
-import com.android.internal.R;
-
-public class EditTextActivityNoScrollPanScan extends Activity 
-{
-   @Override
-   public void onCreate(Bundle savedInstanceState) 
-   {
-       super.onCreate(savedInstanceState);
-                
-       LinearLayout layout = new LinearLayout(this);
-       layout.setOrientation(LinearLayout.VERTICAL);
-       
-       String string = new String();
-       for (int i=0; i<9; i++) 
-       {
-           final EditText editText = new EditText(this);
-           editText.setText(string.valueOf(i));
-           layout.addView(editText);
-       }
-       setContentView(layout);
-       this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
-    }  
-}
diff --git a/tests/ImfTest/src/com/android/imftest/samples/ManyEditTextActivityNoScrollPanScan.java b/tests/ImfTest/src/com/android/imftest/samples/ManyEditTextActivityNoScrollPanScan.java
index 4cb3af6ab81c..54ab57a498bb 100644
--- a/tests/ImfTest/src/com/android/imftest/samples/ManyEditTextActivityNoScrollPanScan.java
+++ b/tests/ImfTest/src/com/android/imftest/samples/ManyEditTextActivityNoScrollPanScan.java
@@ -20,22 +20,31 @@ import com.android.internal.R;
  */
 public class ManyEditTextActivityNoScrollPanScan extends Activity 
 {
-   @Override
-   public void onCreate(Bundle savedInstanceState) 
-   {
-       super.onCreate(savedInstanceState);
-                
-       LinearLayout layout = new LinearLayout(this);
-       layout.setOrientation(LinearLayout.VERTICAL);
-       
-       String string = new String();
-       for (int i=0; i<9; i++) 
-       {
-           final EditText editText = new EditText(this);
-           editText.setText(string.valueOf(i));
-           layout.addView(editText);
-       }
-       setContentView(layout);
-       this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
+    public static final int NUM_EDIT_TEXTS = 9;
+
+    private View mRootView;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) 
+    {
+        super.onCreate(savedInstanceState);
+
+        mRootView = new LinearLayout(this);
+        ((LinearLayout) mRootView).setOrientation(LinearLayout.VERTICAL);
+
+        for (int i=0; i<NUM_EDIT_TEXTS; i++) 
+        {
+            final EditText editText = new EditText(this);
+            editText.setText(String.valueOf(i));
+            editText.setId(i);
+            ((LinearLayout) mRootView).addView(editText);
+        }
+        setContentView(mRootView);
+        this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
     }  
+
+    public View getRootView() {
+        return mRootView;
+    }
+
 }
diff --git a/tests/ImfTest/src/com/android/imftest/samples/ManyEditTextActivityScrollPanScan.java b/tests/ImfTest/src/com/android/imftest/samples/ManyEditTextActivityScrollPanScan.java
index bd32828a1d08..b228d342ff93 100644
--- a/tests/ImfTest/src/com/android/imftest/samples/ManyEditTextActivityScrollPanScan.java
+++ b/tests/ImfTest/src/com/android/imftest/samples/ManyEditTextActivityScrollPanScan.java
@@ -20,26 +20,33 @@ import com.android.internal.R;
  */
 public class ManyEditTextActivityScrollPanScan extends Activity 
 {
-   private ScrollView mScrollView;
-   @Override
-   public void onCreate(Bundle savedInstanceState) 
-   {
-       super.onCreate(savedInstanceState);
-       mScrollView = new ScrollView(this);
-       
-       LinearLayout layout = new LinearLayout(this);
-       layout.setOrientation(LinearLayout.VERTICAL);
-       
-       String string = new String();
-       for (int i=0; i<12; i++) 
-       {
-           final EditText editText = new EditText(this);
-           editText.setText(string.valueOf(i));
-           layout.addView(editText);
-       }
-
-       mScrollView.addView(layout);
-       setContentView(mScrollView);
-       this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
-    }  
+    public static final int NUM_EDIT_TEXTS = 12;
+
+    private View mRootView;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) 
+    {
+        super.onCreate(savedInstanceState);
+        mRootView = new ScrollView(this);
+
+        LinearLayout layout = new LinearLayout(this);
+        layout.setOrientation(LinearLayout.VERTICAL);
+
+        for (int i=0; i<NUM_EDIT_TEXTS; i++) 
+        {
+            final EditText editText = new EditText(this);
+            editText.setText(String.valueOf(i));
+            editText.setId(i);
+            layout.addView(editText);
+        }
+
+        ((ScrollView) mRootView).addView(layout);
+        setContentView(mRootView);
+        this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
+    }   
+
+    public View getRootView() {
+        return mRootView;
+    }
 }
\ No newline at end of file
diff --git a/tests/ImfTest/src/com/android/imftest/samples/ManyEditTextActivityScrollResize.java b/tests/ImfTest/src/com/android/imftest/samples/ManyEditTextActivityScrollResize.java
index eaaa98bf05c7..777fbaef6673 100644
--- a/tests/ImfTest/src/com/android/imftest/samples/ManyEditTextActivityScrollResize.java
+++ b/tests/ImfTest/src/com/android/imftest/samples/ManyEditTextActivityScrollResize.java
@@ -2,6 +2,7 @@ package com.android.imftest.samples;
 
 import android.app.Activity;
 import android.os.Bundle;
+import android.view.View;
 import android.view.WindowManager;
 import android.widget.LinearLayout;
 import android.widget.EditText;
@@ -12,26 +13,33 @@ import android.widget.ScrollView;
  */
 public class ManyEditTextActivityScrollResize extends Activity 
 {
-    private ScrollView mScrollView;
+    public static final int NUM_EDIT_TEXTS = 12;
+    
+    private View mRootView;
+    
     @Override
     public void onCreate(Bundle savedInstanceState) 
     {
         super.onCreate(savedInstanceState);
-        mScrollView = new ScrollView(this);
+        mRootView = new ScrollView(this);
        
         LinearLayout layout = new LinearLayout(this);
         layout.setOrientation(LinearLayout.VERTICAL);
        
-        String string = new String();
-        for (int i=0; i<12; i++) 
+        for (int i=0; i<NUM_EDIT_TEXTS; i++) 
         {
             final EditText editText = new EditText(this);
-            editText.setText(string.valueOf(i));
+            editText.setText(String.valueOf(i));
+            editText.setId(i);
             layout.addView(editText);
         }
 
-        mScrollView.addView(layout);
-        setContentView(mScrollView);
-        this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
+        ((ScrollView) mRootView).addView(layout);
+        setContentView(mRootView);
+        this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
     }  
+
+    public View getRootView() {
+        return mRootView;
+    } 
 }
\ No newline at end of file
diff --git a/tests/ImfTest/src/com/android/imftest/samples/OneEditTextActivityNotSelected.java b/tests/ImfTest/src/com/android/imftest/samples/OneEditTextActivityNotSelected.java
index 5fef8840cd29..88a344779db8 100644
--- a/tests/ImfTest/src/com/android/imftest/samples/OneEditTextActivityNotSelected.java
+++ b/tests/ImfTest/src/com/android/imftest/samples/OneEditTextActivityNotSelected.java
@@ -2,6 +2,7 @@ package com.android.imftest.samples;
 
 import android.app.Activity;
 import android.os.Bundle;
+import android.os.Debug;
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewGroup;
@@ -20,21 +21,36 @@ import com.android.internal.R;
  */
 public class OneEditTextActivityNotSelected extends Activity 
 {
-   @Override
-   public void onCreate(Bundle savedInstanceState) 
-   {
-       super.onCreate(savedInstanceState);
-                
-       LinearLayout layout = new LinearLayout(this);
-       layout.setOrientation(LinearLayout.VERTICAL);
-       
-       final EditText editText = new EditText(this);
-       final TextView textView = new TextView(this);
-       textView.setText("The focus is here.");
-       layout.addView(editText);
-       layout.addView(textView);
-  
-       setContentView(layout);
-       textView.requestFocus();
+    private View mRootView;
+    private View mDefaultFocusedView;
+    
+    @Override
+    public void onCreate(Bundle savedInstanceState) 
+    {
+        super.onCreate(savedInstanceState);
+
+        LinearLayout layout = new LinearLayout(this);
+        layout.setOrientation(LinearLayout.VERTICAL);
+        mRootView = new ScrollView(this);
+
+        EditText editText = new EditText(this);
+        Button button = new Button(this);
+        button.setText("The focus is here.");
+        button.setFocusableInTouchMode(true);
+        button.requestFocus();
+        mDefaultFocusedView = button;
+        layout.addView(button);
+        layout.addView(editText);
+
+        ((ScrollView) mRootView).addView(layout);
+        setContentView(mRootView);
     }  
+
+    public View getRootView() {
+        return mRootView;
+    }
+    
+    public View getDefaultFocusedView() {
+        return mDefaultFocusedView;
+    }
 }
diff --git a/tests/ImfTest/src/com/android/imftest/samples/OneEditTextActivitySelected.java b/tests/ImfTest/src/com/android/imftest/samples/OneEditTextActivitySelected.java
index 2fd19e890d18..1b802636e13a 100644
--- a/tests/ImfTest/src/com/android/imftest/samples/OneEditTextActivitySelected.java
+++ b/tests/ImfTest/src/com/android/imftest/samples/OneEditTextActivitySelected.java
@@ -20,18 +20,32 @@ import com.android.internal.R;
  */
 public class OneEditTextActivitySelected extends Activity 
 {
-   @Override
-   public void onCreate(Bundle savedInstanceState) 
-   {
-       super.onCreate(savedInstanceState);
-                
-       LinearLayout layout = new LinearLayout(this);
-       layout.setOrientation(LinearLayout.VERTICAL);
-       
-       final EditText editText = new EditText(this);
-       layout.addView(editText);
-  
-       setContentView(layout);
-       editText.requestFocus();
+    private View mRootView;
+    private View mDefaultFocusedView;
+    
+    @Override
+    public void onCreate(Bundle savedInstanceState) 
+    {
+        super.onCreate(savedInstanceState);
+
+        LinearLayout layout = new LinearLayout(this);
+        layout.setOrientation(LinearLayout.VERTICAL);
+        mRootView = new ScrollView(this);
+        
+        EditText editText = new EditText(this);
+        editText.requestFocus();
+        mDefaultFocusedView = editText;
+        layout.addView(editText);
+
+        ((ScrollView) mRootView).addView(layout);
+        setContentView(mRootView);
     }  
+
+    public View getRootView() {
+        return mRootView;
+    }
+    
+    public View getDefaultFocusedView() {
+        return mDefaultFocusedView;
+    }
 }
diff --git a/tests/ImfTest/tests/Android.mk b/tests/ImfTest/tests/Android.mk
new file mode 100755
index 000000000000..0f1924cc3342
--- /dev/null
+++ b/tests/ImfTest/tests/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# We only want this apk build for tests.
+LOCAL_MODULE_TAGS := tests
+
+# Include all test java files.
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_PACKAGE_NAME := ImfTestTests
+
+LOCAL_INSTRUMENTATION_FOR := ImfTest
+
+include $(BUILD_PACKAGE)
diff --git a/tests/ImfTest/tests/AndroidManifest.xml b/tests/ImfTest/tests/AndroidManifest.xml
new file mode 100755
index 000000000000..122d202ea307
--- /dev/null
+++ b/tests/ImfTest/tests/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT 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 name must be unique so suffix with "tests" so package loader doesn't ignore us -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.imftest.tests">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <!--
+    This declares that this app uses the instrumentation test runner targeting
+    the package of com.android.imftest.  To run the tests use the command:
+    "adb shell am instrument -w com.android.imftest.tests/android.test.InstrumentationTestRunner"
+    -->
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+                     android:targetPackage="com.android.imftest"
+                     android:label="imf tests"/>
+
+</manifest>
diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollablePanScanTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollablePanScanTests.java
new file mode 100755
index 000000000000..a1c5fd285c34
--- /dev/null
+++ b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollablePanScanTests.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.imftest.samples;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.View;
+
+import com.android.imftest.R;
+
+
+public class BigEditTextActivityNonScrollablePanScanTests extends ImfBaseTestCase<BigEditTextActivityNonScrollablePanScan> {
+
+	public final String TAG = "BigEditTextActivityNonScrollablePanScanTests";
+	
+    public BigEditTextActivityNonScrollablePanScanTests() {
+        super(BigEditTextActivityNonScrollablePanScan.class);
+    }
+	
+	@LargeTest
+	public void testAppAdjustmentPanScan() {
+	    // Give the IME 2 seconds to appear.
+	    pause(2000);
+        
+	    View rootView = ((BigEditTextActivityNonScrollablePanScan) mTargetActivity).getRootView();
+	    View servedView = ((BigEditTextActivityNonScrollablePanScan) mTargetActivity).getDefaultFocusedView();
+	        
+	    assertNotNull(rootView);
+	    assertNotNull(servedView);
+	    
+	    destructiveCheckImeInitialState(rootView, servedView);
+	    
+        verifyEditTextAdjustment(servedView, rootView.getMeasuredHeight());
+	}
+	
+}
diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollableResizeTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollableResizeTests.java
new file mode 100755
index 000000000000..2e0b0eb6e903
--- /dev/null
+++ b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityNonScrollableResizeTests.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.imftest.samples;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.View;
+
+import com.android.imftest.R;
+
+
+public class BigEditTextActivityNonScrollableResizeTests extends ImfBaseTestCase<BigEditTextActivityNonScrollableResize> {
+
+	public final String TAG = "BigEditTextActivityNonScrollableResizeTests";
+	
+    public BigEditTextActivityNonScrollableResizeTests() {
+        super(BigEditTextActivityNonScrollableResize.class);
+    }
+	
+	@LargeTest
+	public void testAppAdjustmentPanScan() {       // Give the IME 2 seconds to appear.
+        pause(2000);
+        
+        View rootView = ((BigEditTextActivityNonScrollableResize) mTargetActivity).getRootView();
+        View servedView = ((BigEditTextActivityNonScrollableResize) mTargetActivity).getDefaultFocusedView();
+         
+        assertNotNull(rootView);
+        assertNotNull(servedView);
+        
+        destructiveCheckImeInitialState(rootView, servedView);
+            
+        verifyEditTextAdjustment(servedView, rootView.getMeasuredHeight());
+	}
+	
+}
diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollablePanScanTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollablePanScanTests.java
new file mode 100755
index 000000000000..d3eefb5b48c1
--- /dev/null
+++ b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollablePanScanTests.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.imftest.samples;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.View;
+
+import com.android.imftest.R;
+
+
+public class BigEditTextActivityScrollablePanScanTests extends ImfBaseTestCase<BigEditTextActivityScrollablePanScan> {
+
+	public final String TAG = "BigEditTextActivityScrollablePanScanTests";
+	
+    public BigEditTextActivityScrollablePanScanTests() {
+        super(BigEditTextActivityScrollablePanScan.class);
+    }
+	
+	@LargeTest
+	public void testAppAdjustmentPanScan() {       // Give the IME 2 seconds to appear.
+        pause(2000);
+        
+        View rootView = ((BigEditTextActivityScrollablePanScan) mTargetActivity).getRootView();
+        View servedView = ((BigEditTextActivityScrollablePanScan) mTargetActivity).getDefaultFocusedView();
+         
+        assertNotNull(rootView);
+        assertNotNull(servedView);
+        
+        destructiveCheckImeInitialState(rootView, servedView);
+            
+        verifyEditTextAdjustment(servedView, rootView.getMeasuredHeight());
+	}
+	
+}
diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollableResizeTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollableResizeTests.java
new file mode 100755
index 000000000000..5c40e6d966d6
--- /dev/null
+++ b/tests/ImfTest/tests/src/com/android/imftest/samples/BigEditTextActivityScrollableResizeTests.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.imftest.samples;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.View;
+
+import com.android.imftest.R;
+
+
+public class BigEditTextActivityScrollableResizeTests extends ImfBaseTestCase<BigEditTextActivityScrollableResize> {
+
+	public final String TAG = "BigEditTextActivityScrollableResizeTests";
+	
+    public BigEditTextActivityScrollableResizeTests() {
+        super(BigEditTextActivityScrollableResize.class);
+    }
+	
+	@LargeTest
+	public void testAppAdjustmentPanScan() {       
+	    // Give the IME 2 seconds to appear.
+        pause(2000);
+        
+        View rootView = ((BigEditTextActivityScrollableResize) mTargetActivity).getRootView();
+        View servedView = ((BigEditTextActivityScrollableResize) mTargetActivity).getDefaultFocusedView();
+          
+        assertNotNull(rootView);
+        assertNotNull(servedView);
+        
+        destructiveCheckImeInitialState(rootView, servedView);
+            
+        verifyEditTextAdjustment(servedView, rootView.getMeasuredHeight());
+	}
+	
+}
diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/BottomEditTextActivityPanScanTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/BottomEditTextActivityPanScanTests.java
new file mode 100755
index 000000000000..9a931331adcd
--- /dev/null
+++ b/tests/ImfTest/tests/src/com/android/imftest/samples/BottomEditTextActivityPanScanTests.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.imftest.samples;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.View;
+
+import com.android.imftest.R;
+
+
+public class BottomEditTextActivityPanScanTests extends ImfBaseTestCase<BottomEditTextActivityPanScan> {
+
+	public final String TAG = "BottomEditTextActivityPanScanTests";
+	
+    public BottomEditTextActivityPanScanTests() {
+        super(BottomEditTextActivityPanScan.class);
+    }
+	
+	@LargeTest
+	public void testAppAdjustmentPanScan() {
+        // Give the IME 2 seconds to appear.
+        pause(2000);
+        
+        View rootView = ((BottomEditTextActivityPanScan) mTargetActivity).getRootView();
+        View servedView = ((BottomEditTextActivityPanScan) mTargetActivity).getDefaultFocusedView();
+        
+        assertNotNull(rootView);
+        assertNotNull(servedView);
+        
+        destructiveCheckImeInitialState(rootView, servedView);
+        
+        verifyEditTextAdjustment(servedView, rootView.getMeasuredHeight());
+	}
+	
+}
diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/BottomEditTextActivityResizeTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/BottomEditTextActivityResizeTests.java
new file mode 100755
index 000000000000..9a69fd509844
--- /dev/null
+++ b/tests/ImfTest/tests/src/com/android/imftest/samples/BottomEditTextActivityResizeTests.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.imftest.samples;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.View;
+
+import com.android.imftest.R;
+
+
+public class BottomEditTextActivityResizeTests extends ImfBaseTestCase<BottomEditTextActivityResize> {
+
+    public final String TAG = "BottomEditTextActivityResizeTests";
+    
+    public BottomEditTextActivityResizeTests() {
+        super(BottomEditTextActivityResize.class);
+    }
+    
+    @LargeTest
+    public void testAppAdjustmentResize() {
+        // Give the IME 2 seconds to appear.
+        pause(2000);
+        
+        View rootView = ((BottomEditTextActivityResize) mTargetActivity).getRootView();
+        View servedView = ((BottomEditTextActivityResize) mTargetActivity).getDefaultFocusedView();
+        
+        assertNotNull(rootView);
+        assertNotNull(servedView);
+        
+        destructiveCheckImeInitialState(rootView, servedView);
+        
+        verifyEditTextAdjustment(servedView, rootView.getMeasuredHeight());
+    }
+    
+}
diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/ButtonActivityTest.java b/tests/ImfTest/tests/src/com/android/imftest/samples/ButtonActivityTest.java
new file mode 100755
index 000000000000..ae900c34ba3b
--- /dev/null
+++ b/tests/ImfTest/tests/src/com/android/imftest/samples/ButtonActivityTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.imftest.samples;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.KeyEvent;
+import android.widget.Button;
+
+
+public class ButtonActivityTest extends ImfBaseTestCase<ButtonActivity> {
+
+	final public String TAG = "ButtonActivityTest";
+	
+    public ButtonActivityTest() {
+        super(ButtonActivity.class);
+    }
+
+    @LargeTest
+    public void testButtonActivatesIme() {
+       
+        final Button button = (Button) mTargetActivity.findViewById(ButtonActivity.BUTTON_ID);
+        
+        // Push button
+        // Bring the target EditText into focus.
+        mTargetActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                button.requestFocus();
+            }
+        });
+        
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+        
+        // Give it a couple seconds
+        pause(2000);
+        
+        // We should have initialized imm.mServedView and imm.mCurrentTextBoxAttribute
+        assertTrue(mImm.isActive());
+        // imm.mServedInputConnection should be null since Button doesn't override onCreateInputConnection().
+        assertFalse(mImm.isAcceptingText());
+        
+        destructiveCheckImeInitialState(mTargetActivity.getRootView(), button);
+        
+    }
+}
diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/ImfBaseTestCase.java b/tests/ImfTest/tests/src/com/android/imftest/samples/ImfBaseTestCase.java
new file mode 100755
index 000000000000..61dc61193a95
--- /dev/null
+++ b/tests/ImfTest/tests/src/com/android/imftest/samples/ImfBaseTestCase.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.imftest.samples;
+
+import android.app.Activity;
+import android.os.SystemClock;
+import android.test.InstrumentationTestCase;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.inputmethod.InputMethodManager;
+
+import com.android.imftest.R;
+
+public abstract class ImfBaseTestCase<T extends Activity> extends InstrumentationTestCase {
+
+    /*
+     * The amount of time we are willing to wait for the IME to appear after a user action
+     * before we give up and fail the test.
+     */
+    public final long WAIT_FOR_IME = 5000;
+
+    /*
+     * Unfortunately there is now way for us to know how tall the IME is, 
+     * so we have to hard code a minimum and maximum value.
+     */
+    public final int IME_MIN_HEIGHT = 150;
+    public final int IME_MAX_HEIGHT = 300;
+
+    public final String TARGET_PACKAGE_NAME = "com.android.imftest";
+    protected InputMethodManager mImm;
+    protected T mTargetActivity;
+    protected boolean mExpectAutoPop;
+    private Class<T> mTargetActivityClass;
+    
+    public ImfBaseTestCase(Class<T> activityClass) {
+        mTargetActivityClass = activityClass;
+    }
+    
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        
+        mTargetActivity = launchActivity(TARGET_PACKAGE_NAME, mTargetActivityClass, null);
+        mExpectAutoPop = mTargetActivity.getResources().getBoolean(R.bool.def_expect_ime_autopop);
+        mImm = InputMethodManager.getInstance(mTargetActivity);
+    }
+    
+    // Utility test methods
+    public void verifyEditTextAdjustment(final View editText, int rootViewHeight) {
+
+        int[] origLocation = new int[2];
+        int[] newLocation = new int[2];
+
+        // Tell the keyboard to go away.
+        mImm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
+
+        // Bring the target EditText into focus.
+        mTargetActivity.runOnUiThread(new Runnable() {
+            public void run() {
+                editText.requestFocus();
+            }
+        });
+
+        // Get the original location of the EditText.
+        editText.getLocationOnScreen(origLocation);
+
+        // Tap the EditText to bring up the IME.
+        sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);
+
+        // Wait until the EditText pops above the IME or until we hit the timeout.
+        editText.getLocationOnScreen(newLocation);
+        long timeoutTime = SystemClock.uptimeMillis() + WAIT_FOR_IME;
+        while (newLocation[1] > rootViewHeight - IME_MIN_HEIGHT && SystemClock.uptimeMillis() < timeoutTime) {
+            editText.getLocationOnScreen(newLocation);
+            pause(100);
+        }
+
+        assertTrue(newLocation[1] <= rootViewHeight - IME_MIN_HEIGHT);
+
+        // Tell the keyboard to go away.
+        mImm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
+    }
+
+    public void destructiveCheckImeInitialState(View rootView, View servedView) {
+        if (mExpectAutoPop && (mTargetActivity.getWindow().getAttributes().
+                softInputMode&WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST) 
+                == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) {
+            assertTrue(destructiveCheckImeUp(rootView, servedView));
+        } else {
+            assertFalse(destructiveCheckImeUp(rootView, servedView));
+        }
+    }
+    
+    public boolean destructiveCheckImeUp(View rootView, View servedView) {
+        int origHeight;
+        int newHeight;
+        
+        origHeight = rootView.getHeight();
+        
+        // Tell the keyboard to go away.
+        mImm.hideSoftInputFromWindow(servedView.getWindowToken(), 0);
+        
+        // Give it five seconds to adjust
+        newHeight = rootView.getHeight();
+        long timeoutTime = SystemClock.uptimeMillis() + WAIT_FOR_IME;
+        while (Math.abs(newHeight - origHeight) < IME_MIN_HEIGHT && SystemClock.uptimeMillis() < timeoutTime) {
+            newHeight = rootView.getHeight();
+        }
+        
+        return (Math.abs(origHeight - newHeight) >= IME_MIN_HEIGHT);
+    }
+    
+    void pause(int millis) {
+        try {
+            Thread.sleep(millis);
+        } catch (InterruptedException e) {
+        }
+    }
+
+}
diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/ManyEditTextActivityBaseTestCase.java b/tests/ImfTest/tests/src/com/android/imftest/samples/ManyEditTextActivityBaseTestCase.java
new file mode 100755
index 000000000000..278efb1f68db
--- /dev/null
+++ b/tests/ImfTest/tests/src/com/android/imftest/samples/ManyEditTextActivityBaseTestCase.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.imftest.samples;
+
+import android.app.Activity;
+import android.widget.EditText;
+
+
+public abstract class ManyEditTextActivityBaseTestCase<T extends Activity> extends ImfBaseTestCase<T> {
+  
+    public ManyEditTextActivityBaseTestCase(Class<T> activityClass){
+        super(activityClass);
+    }
+
+    public abstract void testAllEditTextsAdjust();
+
+    public void verifyAllEditTextAdjustment(int numEditTexts, int rootViewHeight) {
+
+        for (int i = 0; i < numEditTexts; i++) {
+            final EditText lastEditText = (EditText) mTargetActivity.findViewById(i);
+            verifyEditTextAdjustment(lastEditText, rootViewHeight);
+        }
+
+    }
+
+}
diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/ManyEditTextActivityNoScrollPanScanTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/ManyEditTextActivityNoScrollPanScanTests.java
new file mode 100755
index 000000000000..4f8d14e88ad5
--- /dev/null
+++ b/tests/ImfTest/tests/src/com/android/imftest/samples/ManyEditTextActivityNoScrollPanScanTests.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.imftest.samples;
+
+import android.test.suitebuilder.annotation.LargeTest;
+
+
+public class ManyEditTextActivityNoScrollPanScanTests extends ManyEditTextActivityBaseTestCase<ManyEditTextActivityNoScrollPanScan> {
+
+    public final String TAG = "ManyEditTextActivityNoScrollPanScanTests";
+    
+    public ManyEditTextActivityNoScrollPanScanTests() {
+        super(ManyEditTextActivityNoScrollPanScan.class);
+    }
+
+   
+    @LargeTest
+    public void testAllEditTextsAdjust() {
+        verifyAllEditTextAdjustment(mTargetActivity.NUM_EDIT_TEXTS, 
+                mTargetActivity.getRootView().getMeasuredHeight());
+    }
+}
diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/ManyEditTextActivityScrollPanScanTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/ManyEditTextActivityScrollPanScanTests.java
new file mode 100755
index 000000000000..7f98f7fbdf21
--- /dev/null
+++ b/tests/ImfTest/tests/src/com/android/imftest/samples/ManyEditTextActivityScrollPanScanTests.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.imftest.samples;
+
+import android.test.suitebuilder.annotation.LargeTest;
+
+
+public class ManyEditTextActivityScrollPanScanTests extends ManyEditTextActivityBaseTestCase<ManyEditTextActivityScrollPanScan> {
+
+    public final String TAG = "ManyEditTextActivityScrollPanScanTests";
+    
+    
+    public ManyEditTextActivityScrollPanScanTests() {
+        super(ManyEditTextActivityScrollPanScan.class);
+    }
+    
+    @LargeTest
+    public void testAllEditTextsAdjust() {
+        verifyAllEditTextAdjustment(mTargetActivity.NUM_EDIT_TEXTS, 
+                mTargetActivity.getRootView().getMeasuredHeight());
+    }
+
+}
diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/ManyEditTextActivityScrollResizeTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/ManyEditTextActivityScrollResizeTests.java
new file mode 100755
index 000000000000..68dae87ea5c9
--- /dev/null
+++ b/tests/ImfTest/tests/src/com/android/imftest/samples/ManyEditTextActivityScrollResizeTests.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.imftest.samples;
+
+import android.test.suitebuilder.annotation.LargeTest;
+
+
+public class ManyEditTextActivityScrollResizeTests extends ManyEditTextActivityBaseTestCase<ManyEditTextActivityScrollResize> {
+
+    public final String TAG = "ManyEditTextActivityScrollResizeTests";
+    
+    
+    public ManyEditTextActivityScrollResizeTests() {
+        super(ManyEditTextActivityScrollResize.class);
+    }
+
+    @LargeTest
+    public void testAllEditTextsAdjust() {
+        verifyAllEditTextAdjustment(mTargetActivity.NUM_EDIT_TEXTS, 
+                mTargetActivity.getRootView().getMeasuredHeight());
+    }
+
+}
diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/OneEditTextActivityNotSelectedTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/OneEditTextActivityNotSelectedTests.java
new file mode 100755
index 000000000000..ed5b0c9f1728
--- /dev/null
+++ b/tests/ImfTest/tests/src/com/android/imftest/samples/OneEditTextActivityNotSelectedTests.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.imftest.samples;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.View;
+
+
+public class OneEditTextActivityNotSelectedTests extends ImfBaseTestCase<OneEditTextActivityNotSelected> {
+
+	public final String TAG = "OneEditTextActivityNotSelectedTests";
+	
+    public OneEditTextActivityNotSelectedTests() {
+        super(OneEditTextActivityNotSelected.class);
+    }
+    
+	@LargeTest
+	public void testSoftKeyboardNoAutoPop() {
+	    
+	    // Give the IME 2 seconds to appear.
+	    pause(2000);
+	    
+	    assertFalse(mImm.isAcceptingText());
+	    
+	    View rootView = ((OneEditTextActivityNotSelected) mTargetActivity).getRootView();
+        View servedView = ((OneEditTextActivityNotSelected) mTargetActivity).getDefaultFocusedView();
+        
+        assertNotNull(rootView);
+        assertNotNull(servedView);
+        
+        destructiveCheckImeInitialState(rootView, servedView);
+        
+        verifyEditTextAdjustment(servedView, rootView.getMeasuredHeight());
+	}
+	
+}
diff --git a/tests/ImfTest/tests/src/com/android/imftest/samples/OneEditTextActivitySelectedTests.java b/tests/ImfTest/tests/src/com/android/imftest/samples/OneEditTextActivitySelectedTests.java
new file mode 100755
index 000000000000..42fcd66f7922
--- /dev/null
+++ b/tests/ImfTest/tests/src/com/android/imftest/samples/OneEditTextActivitySelectedTests.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.imftest.samples;
+
+import com.android.imftest.R;
+
+import android.test.suitebuilder.annotation.LargeTest;
+import android.view.KeyEvent;
+import android.view.View;
+
+
+public class OneEditTextActivitySelectedTests extends ImfBaseTestCase<OneEditTextActivitySelected> {
+
+    public final String TAG = "OneEditTextActivitySelectedTests";
+    
+    public OneEditTextActivitySelectedTests() {
+        super(OneEditTextActivitySelected.class);
+    }
+    
+    @LargeTest
+    public void testSoftKeyboardAutoPop() {
+        
+        // Give the IME 2 seconds to appear.
+        pause(2000);
+        
+        assertTrue(mImm.isAcceptingText());
+        
+        View rootView = ((OneEditTextActivitySelected) mTargetActivity).getRootView();
+        View servedView = ((OneEditTextActivitySelected) mTargetActivity).getDefaultFocusedView();
+        
+        assertNotNull(rootView);
+        assertNotNull(servedView);
+        
+        destructiveCheckImeInitialState(rootView, servedView);
+        
+        verifyEditTextAdjustment(servedView, rootView.getMeasuredHeight());
+    }
+    
+}
diff --git a/tests/gadgets/GadgetHostTest/AndroidManifest.xml b/tests/gadgets/GadgetHostTest/AndroidManifest.xml
index cac2776d3a34..52e314f6bb4f 100644
--- a/tests/gadgets/GadgetHostTest/AndroidManifest.xml
+++ b/tests/gadgets/GadgetHostTest/AndroidManifest.xml
@@ -17,12 +17,20 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
-        <receiver android:name="TestGadgetProvider" android:label="@string/oh_hai"
-                    android:icon="@drawable/oh_hai_icon">
+
+        <!-- BEGIN_INCLUDE(GadgetProvider) -->
+        <receiver android:name="TestGadgetProvider"
+                    android:label="@string/oh_hai"
+                    android:icon="@drawable/oh_hai_icon"
+                    >
             <intent-filter>
                 <action android:name="android.gadget.action.GADGET_UPDATE" />
             </intent-filter>
-            <meta-data android:name="android.gadget.provider" android:resource="@xml/gadget_info" />
+            <meta-data android:name="android.gadget.provider"
+                        android:resource="@xml/gadget_info"
+                        />
         </receiver>
+        <!-- END_INCLUDE(GadgetProvider) -->
+        
     </application>
 </manifest>
diff --git a/tests/gadgets/GadgetHostTest/res/xml/gadget_info.xml b/tests/gadgets/GadgetHostTest/res/xml/gadget_info.xml
index 353df307821d..e0c4222c8cf4 100644
--- a/tests/gadgets/GadgetHostTest/res/xml/gadget_info.xml
+++ b/tests/gadgets/GadgetHostTest/res/xml/gadget_info.xml
@@ -1,8 +1,10 @@
+<!-- BEGIN_INCLUDE(GadgetProviderInfo) -->
 <gadget-provider xmlns:android="http://schemas.android.com/apk/res/android"
     android:minWidth="40dp"
     android:minHeight="30dp"
-    android:updatePeriodMillis="3000"
+    android:updatePeriodMillis="86400000"
     android:initialLayout="@layout/test_gadget"
     android:configure="com.android.tests.gadgethost.TestGadgetConfigure"
     >
 </gadget-provider>
+<!-- END_INCLUDE(GadgetProviderInfo) -->
diff --git a/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/GadgetHostActivity.java b/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/GadgetHostActivity.java
index d3dcf41deab3..0bd89261a71d 100644
--- a/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/GadgetHostActivity.java
+++ b/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/GadgetHostActivity.java
@@ -23,7 +23,7 @@ import android.content.Intent;
 import android.content.SharedPreferences;
 import android.gadget.GadgetHost;
 import android.gadget.GadgetHostView;
-import android.gadget.GadgetInfo;
+import android.gadget.GadgetProviderInfo;
 import android.gadget.GadgetManager;
 import android.os.Bundle;
 import android.util.Log;
@@ -73,14 +73,13 @@ public class GadgetHostActivity extends Activity
     };
 
     void discoverGadget(int requestCode) {
-        Intent intent = new Intent(GadgetManager.GADGET_PICK_ACTION);
-        intent.putExtra(GadgetManager.EXTRA_HOST_ID, HOST_ID);
+        Intent intent = new Intent(GadgetManager.ACTION_GADGET_PICK);
         intent.putExtra(GadgetManager.EXTRA_GADGET_ID, mHost.allocateGadgetId());
         startActivityForResult(intent, requestCode);
     }
 
     void configureGadget(int requestCode, int gadgetId, ComponentName configure) {
-        Intent intent = new Intent(GadgetManager.GADGET_CONFIGURE_ACTION);
+        Intent intent = new Intent(GadgetManager.ACTION_GADGET_CONFIGURE);
         intent.setComponent(configure);
         intent.putExtra(GadgetManager.EXTRA_GADGET_ID, gadgetId);
         SharedPreferences.Editor prefs = getPreferences(0).edit();
@@ -89,11 +88,13 @@ public class GadgetHostActivity extends Activity
         startActivityForResult(intent, requestCode);
     }
 
-    void handleGadgetPickResult(int resultCode, Intent data) {
-        Bundle extras = data.getExtras();
+    void handleGadgetPickResult(int resultCode, Intent intent) {
+        // BEGIN_INCLUDE(getExtra_EXTRA_GADGET_ID)
+        Bundle extras = intent.getExtras();
         int gadgetId = extras.getInt(GadgetManager.EXTRA_GADGET_ID);
+        // END_INCLUDE(getExtra_EXTRA_GADGET_ID)
         if (resultCode == RESULT_OK) {
-            GadgetInfo gadget = mGadgetManager.getGadgetInfo(gadgetId);
+            GadgetProviderInfo gadget = mGadgetManager.getGadgetInfo(gadgetId);
 
             if (gadget.configure != null) {
                 // configure the gadget if we should
@@ -115,14 +116,14 @@ public class GadgetHostActivity extends Activity
             return;
         }
         if (resultCode == RESULT_OK) {
-            GadgetInfo gadget = mGadgetManager.getGadgetInfo(gadgetId);
+            GadgetProviderInfo gadget = mGadgetManager.getGadgetInfo(gadgetId);
             addGadgetView(gadgetId, gadget);
         } else {
             mHost.deleteGadgetId(gadgetId);
         }
     }
 
-    void addGadgetView(int gadgetId, GadgetInfo gadget) {
+    void addGadgetView(int gadgetId, GadgetProviderInfo gadget) {
         // Inflate the gadget's RemoteViews
         GadgetHostView view = mHost.createView(this, gadgetId, gadget);
 
@@ -188,11 +189,10 @@ public class GadgetHostActivity extends Activity
     }
 
     GadgetHost mHost = new GadgetHost(this, HOST_ID) {
-        protected GadgetHostView onCreateView(Context context, int gadgetId, GadgetInfo gadget) {
+        protected GadgetHostView onCreateView(Context context, int gadgetId, GadgetProviderInfo gadget) {
             return new MyGadgetView(gadgetId);
         }
     };
-
 }
 
 
diff --git a/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/TestGadgetProvider.java b/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/TestGadgetProvider.java
index 7614c9ef0cd9..370a50b94e16 100644
--- a/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/TestGadgetProvider.java
+++ b/tests/gadgets/GadgetHostTest/src/com/android/tests/gadgethost/TestGadgetProvider.java
@@ -37,16 +37,18 @@ public class TestGadgetProvider extends BroadcastReceiver {
         String action = intent.getAction();
         Log.d(TAG, "intent=" + intent);
 
-        if (GadgetManager.GADGET_ENABLED_ACTION.equals(action)) {
+        if (GadgetManager.ACTION_GADGET_ENABLED.equals(action)) {
             Log.d(TAG, "ENABLED");
         }
-        else if (GadgetManager.GADGET_DISABLED_ACTION.equals(action)) {
+        else if (GadgetManager.ACTION_GADGET_DISABLED.equals(action)) {
             Log.d(TAG, "DISABLED");
         }
-        else if (GadgetManager.GADGET_UPDATE_ACTION.equals(action)) {
+        else if (GadgetManager.ACTION_GADGET_UPDATE.equals(action)) {
             Log.d(TAG, "UPDATE");
+            // BEGIN_INCLUDE(getExtra_EXTRA_GADGET_IDS)
             Bundle extras = intent.getExtras();
             int[] gadgetIds = extras.getIntArray(GadgetManager.EXTRA_GADGET_IDS);
+            // END_INCLUDE(getExtra_EXTRA_GADGET_IDS)
 
             SharedPreferences prefs = context.getSharedPreferences(
                     TestGadgetProvider.PREFS_NAME, 0);
diff --git a/tests/gadgets/GadgetProviderTest/res/xml/gadget_info.xml b/tests/gadgets/GadgetProviderTest/res/xml/gadget_info.xml
index 0b8ca2edff7e..0fc78124bdf6 100644
--- a/tests/gadgets/GadgetProviderTest/res/xml/gadget_info.xml
+++ b/tests/gadgets/GadgetProviderTest/res/xml/gadget_info.xml
@@ -1,7 +1,7 @@
 <gadget-provider xmlns:android="http://schemas.android.com/apk/res/android"
     android:minWidth="40dp"
     android:minHeight="30dp"
-    android:updatePeriodMillis="3000"
+    android:updatePeriodMillis="60000"
     android:initialLayout="@layout/test_gadget"
     >
 </gadget-provider>
diff --git a/tests/gadgets/GadgetProviderTest/src/com/android/tests/gadgetprovider/TestGadgetProvider.java b/tests/gadgets/GadgetProviderTest/src/com/android/tests/gadgetprovider/TestGadgetProvider.java
index 8622bc761173..b81575f0c271 100644
--- a/tests/gadgets/GadgetProviderTest/src/com/android/tests/gadgetprovider/TestGadgetProvider.java
+++ b/tests/gadgets/GadgetProviderTest/src/com/android/tests/gadgetprovider/TestGadgetProvider.java
@@ -34,13 +34,13 @@ public class TestGadgetProvider extends BroadcastReceiver {
         String action = intent.getAction();
         Log.d(TAG, "intent=" + intent);
 
-        if (GadgetManager.GADGET_ENABLED_ACTION.equals(action)) {
+        if (GadgetManager.ACTION_GADGET_ENABLED.equals(action)) {
             Log.d(TAG, "ENABLED");
         }
-        else if (GadgetManager.GADGET_DISABLED_ACTION.equals(action)) {
+        else if (GadgetManager.ACTION_GADGET_DISABLED.equals(action)) {
             Log.d(TAG, "DISABLED");
         }
-        else if (GadgetManager.GADGET_UPDATE_ACTION.equals(action)) {
+        else if (GadgetManager.ACTION_GADGET_UPDATE.equals(action)) {
             Log.d(TAG, "UPDATE");
             Bundle extras = intent.getExtras();
             int[] gadgetIds = extras.getIntArray(GadgetManager.EXTRA_GADGET_IDS);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 39200a1c3b46..82fe365a6d7a 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -788,6 +788,12 @@ public final class Bridge implements ILayoutBridge {
             return false;
         }
 
+        @SuppressWarnings("unused")
+        public boolean performHapticFeedback(IWindow window, int effectId, boolean always) {
+            // pass for now.
+            return false;
+        }
+        
         @SuppressWarnings("unused")
         public MotionEvent getPendingPointerMove(IWindow arg0) throws RemoteException {
             // pass for now.
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index 0e70f8bea92b..f0009be7ea49 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -1142,6 +1142,7 @@ public class WifiStateTracker extends NetworkStateTracker {
         // Stop DHCP
         if (mDhcpTarget != null) {
             mDhcpTarget.setCancelCallback(true);
+            mDhcpTarget.removeMessages(EVENT_DHCP_START);
         }
         if (!NetworkUtils.stopDhcp(mInterfaceName)) {
             Log.e(TAG, "Could not stop DHCP");
-- 
GitLab