Merge "Enhance URL regular expression to match more Unicode chars."
diff --git a/Android.mk b/Android.mk
index ec6f96b..a48ef45 100644
--- a/Android.mk
+++ b/Android.mk
@@ -33,6 +33,12 @@
 # FRAMEWORKS_BASE_SUBDIRS comes from build/core/pathmap.mk
 LOCAL_SRC_FILES := $(call find-other-java-files,$(FRAMEWORKS_BASE_SUBDIRS))
 
+# EventLogTags files.
+LOCAL_SRC_FILES += \
+       core/java/android/content/EventLogTags.logtags \
+       core/java/android/webkit/EventLogTags.logtags \
+       telephony/java/com/android/internal/telephony/EventLogTags.logtags \
+
 # The following filters out code we are temporarily not including at all.
 # TODO: Move AWT and beans (and associated harmony code) back into libcore.
 # TODO: Maybe remove javax.microedition entirely?
@@ -84,6 +90,7 @@
 	core/java/android/app/IStatusBar.aidl \
 	core/java/android/app/IThumbnailReceiver.aidl \
 	core/java/android/app/ITransientNotification.aidl \
+	core/java/android/app/IUiModeManager.aidl \
 	core/java/android/app/IWallpaperManager.aidl \
 	core/java/android/app/IWallpaperManagerCallback.aidl \
 	core/java/android/backup/IBackupManager.aidl \
@@ -109,13 +116,11 @@
 	core/java/android/hardware/ISensorService.aidl \
 	core/java/android/net/IConnectivityManager.aidl \
 	core/java/android/net/INetworkManagementEventObserver.aidl \
-	core/java/android/os/ICheckinService.aidl \
 	core/java/android/os/IMessenger.aidl \
 	core/java/android/os/storage/IMountService.aidl \
 	core/java/android/os/storage/IMountServiceListener.aidl \
 	core/java/android/os/INetworkManagementService.aidl \
 	core/java/android/os/INetStatService.aidl \
-	core/java/android/os/IParentalControlCallback.aidl \
 	core/java/android/os/IPermissionController.aidl \
 	core/java/android/os/IPowerManager.aidl \
     core/java/android/os/IRemoteCallback.aidl \
@@ -367,6 +372,8 @@
 
 sample_dir := development/samples
 
+# the list here should match the list of samples included in the sdk samples package
+# (see development/build/sdk.atree)
 web_docs_sample_code_flags := \
 		-hdf android.hasSamples 1 \
 		-samplecode $(sample_dir)/ApiDemos \
@@ -377,6 +384,8 @@
 		            resources/samples/BusinessCard "Business Card" \
 		-samplecode $(sample_dir)/ContactManager \
 		            resources/samples/ContactManager "Contact Manager" \
+                -samplecode $(sample_dir)/CubeLiveWallpaper \
+                            resources/samples/CubeLiveWallpaper "Live Wallpaper" \
 		-samplecode $(sample_dir)/Home \
 		            resources/samples/Home "Home" \
 		-samplecode $(sample_dir)/JetBoy \
@@ -387,6 +396,8 @@
 		            resources/samples/MultiResolution "Multiple Resolutions" \
 		-samplecode $(sample_dir)/NotePad \
 		            resources/samples/NotePad "Note Pad" \
+                -samplecode $(sample_dir)/SampleSyncAdapter \
+                            resources/samples/SampleSyncAdapter "Sample Sync Adapter" \
 		-samplecode $(sample_dir)/SearchableDictionary \
 		            resources/samples/SearchableDictionary "Searchable Dictionary" \
 		-samplecode $(sample_dir)/Snake \
@@ -396,7 +407,9 @@
 		-samplecode $(sample_dir)/Wiktionary \
 		            resources/samples/Wiktionary "Wiktionary" \
 		-samplecode $(sample_dir)/WiktionarySimple \
-		            resources/samples/WiktionarySimple "Wiktionary (Simplified)"
+		            resources/samples/WiktionarySimple "Wiktionary (Simplified)" \
+		-samplecode $(sample_dir)/VoiceRecognitionService \
+		            resources/samples/VoiceRecognitionService "Voice Recognition Service"
 
 ## SDK version identifiers used in the published docs
   # major[.minor] version for current SDK. (full releases only)
diff --git a/api/current.xml b/api/current.xml
index a8f7109..56e8cb6 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -1222,6 +1222,17 @@
  visibility="public"
 >
 </field>
+<field name="WRITE_GEOLOCATION_PERMISSIONS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;com.android.browser.permission.WRITE_GEOLOCATION_PERMISSIONS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="WRITE_GSERVICES"
  type="java.lang.String"
  transient="false"
@@ -1526,6 +1537,17 @@
  visibility="public"
 >
 </field>
+<field name="cycle_interpolator"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17432588"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="decelerate_interpolator"
  type="int"
  transient="false"
@@ -4585,6 +4607,17 @@
  visibility="public"
 >
 </field>
+<field name="installLocation"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843448"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="interpolator"
  type="int"
  transient="false"
@@ -6818,6 +6851,17 @@
  visibility="public"
 >
 </field>
+<field name="safeMode"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843449"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="saveEnabled"
  type="int"
  transient="false"
@@ -20363,7 +20407,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="4"
+ value="3"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -20381,17 +20425,6 @@
  visibility="public"
 >
 </field>
-<field name="USES_POLICY_LIMIT_UNLOCK"
- type="int"
- transient="false"
- volatile="false"
- value="3"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="USES_POLICY_RESET_PASSWORD"
  type="int"
  transient="false"
@@ -20418,7 +20451,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="5"
+ value="4"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -24886,6 +24919,17 @@
  visibility="public"
 >
 </field>
+<field name="INTENT_ACTION_SEARCH_SETTINGS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.search.action.SEARCH_SETTINGS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="INTENT_ACTION_SEARCH_SETTINGS_CHANGED"
  type="java.lang.String"
  transient="false"
@@ -25311,8 +25355,8 @@
  visibility="public"
 >
 </method>
-<method name="getSettingsDescription"
- return="java.lang.String"
+<method name="getSettingsDescriptionId"
+ return="int"
  abstract="false"
  native="false"
  synchronized="false"
@@ -37993,6 +38037,17 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_CAR_MODE_ENABLED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.extra.CAR_MODE_ENABLED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="EXTRA_CC"
  type="java.lang.String"
  transient="false"
@@ -41854,6 +41909,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_VM_SAFE_MODE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16384"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="className"
  type="java.lang.String"
  transient="false"
@@ -43202,6 +43268,19 @@
 <parameter name="activity" type="android.content.ComponentName">
 </parameter>
 </method>
+<method name="canonicalToCurrentPackageNames"
+ return="java.lang.String[]"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="names" type="java.lang.String[]">
+</parameter>
+</method>
 <method name="checkPermission"
  return="int"
  abstract="true"
@@ -43260,6 +43339,19 @@
 <parameter name="packageName" type="java.lang.String">
 </parameter>
 </method>
+<method name="currentToCanonicalPackageNames"
+ return="java.lang.String[]"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="names" type="java.lang.String[]">
+</parameter>
+</method>
 <method name="getActivityIcon"
  return="android.graphics.drawable.Drawable"
  abstract="true"
@@ -66274,6 +66366,10 @@
 </parameter>
 <parameter name="format" type="int">
 </parameter>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
 <parameter name="strides" type="int[]">
 </parameter>
 </constructor>
@@ -66287,17 +66383,24 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="width" type="int">
-</parameter>
-<parameter name="height" type="int">
-</parameter>
-<parameter name="offsets" type="int[]">
+<parameter name="rectangle" type="android.graphics.Rect">
 </parameter>
 <parameter name="quality" type="int">
 </parameter>
 <parameter name="stream" type="java.io.OutputStream">
 </parameter>
 </method>
+<method name="getHeight"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getStrides"
  return="int[]"
  abstract="false"
@@ -66309,6 +66412,17 @@
  visibility="public"
 >
 </method>
+<method name="getWidth"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getYuvData"
  return="byte[]"
  abstract="false"
@@ -66331,25 +66445,6 @@
  visibility="public"
 >
 </method>
-<method name="validate"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="protected"
->
-<parameter name="format" type="int">
-</parameter>
-<parameter name="width" type="int">
-</parameter>
-<parameter name="height" type="int">
-</parameter>
-<parameter name="offsets" type="int[]">
-</parameter>
-</method>
 </class>
 </package>
 <package name="android.graphics.drawable"
@@ -83924,29 +84019,6 @@
  visibility="public"
 >
 </constructor>
-<method name="createImageThumbnail"
- return="android.graphics.Bitmap"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="cr" type="android.content.ContentResolver">
-</parameter>
-<parameter name="filePath" type="java.lang.String">
-</parameter>
-<parameter name="uri" type="android.net.Uri">
-</parameter>
-<parameter name="origId" type="long">
-</parameter>
-<parameter name="kind" type="int">
-</parameter>
-<parameter name="saveMini" type="boolean">
-</parameter>
-</method>
 <method name="createVideoThumbnail"
  return="android.graphics.Bitmap"
  abstract="false"
@@ -83960,7 +84032,7 @@
 <parameter name="filePath" type="java.lang.String">
 </parameter>
 </method>
-<method name="extractMiniThumb"
+<method name="extractThumbnail"
  return="android.graphics.Bitmap"
  abstract="false"
  native="false"
@@ -83976,10 +84048,38 @@
 </parameter>
 <parameter name="height" type="int">
 </parameter>
-<parameter name="recycle" type="boolean">
+</method>
+<method name="extractThumbnail"
+ return="android.graphics.Bitmap"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="android.graphics.Bitmap">
+</parameter>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+<parameter name="options" type="int">
 </parameter>
 </method>
-<field name="MINI_THUMB_TARGET_SIZE"
+<field name="OPTIONS_RECYCLE_INPUT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TARGET_SIZE_MICRO_THUMBNAIL"
  type="int"
  transient="false"
  volatile="false"
@@ -83990,29 +84090,7 @@
  visibility="public"
 >
 </field>
-<field name="NO_RECYCLE_INPUT"
- type="boolean"
- transient="false"
- volatile="false"
- value="false"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="RECYCLE_INPUT"
- type="boolean"
- transient="false"
- volatile="false"
- value="true"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="THUMBNAIL_TARGET_SIZE"
+<field name="TARGET_SIZE_NORMAL_THUMBNAIL"
  type="int"
  transient="false"
  volatile="false"
@@ -85682,6 +85760,461 @@
 >
 </field>
 </class>
+<class name="Downloads"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="isStatusError"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="status" type="int">
+</parameter>
+</method>
+<method name="isStatusSuccess"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="status" type="int">
+</parameter>
+</method>
+<field name="ACTION_DOWNLOAD_COMPLETED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.action.DOWNLOAD_COMPLETED&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="COLUMN_NOTIFICATION_EXTRAS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;notificationextras&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DOWNLOAD_DESTINATION_CACHE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DOWNLOAD_DESTINATION_CACHE_PURGEABLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DOWNLOAD_DESTINATION_EXTERNAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="DOWNLOAD_ID_INVALID"
+ type="long"
+ transient="false"
+ volatile="false"
+ value="-1L"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_DEVICE_NOT_FOUND_ERROR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="499"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_INSUFFICIENT_SPACE_ERROR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="498"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_NOT_ACCEPTABLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="406"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_PENDING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="190"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_RUNNING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="192"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_SUCCESS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="200"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_UNHANDLED_REDIRECT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="493"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_UNKNOWN_ERROR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="491"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Downloads.ById"
+ extends="android.net.Downloads.DownloadBase"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="deleteDownload"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="downloadId" type="long">
+</parameter>
+</method>
+<method name="getMimeTypeForId"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="downloadId" type="long">
+</parameter>
+</method>
+<method name="getStatus"
+ return="android.net.Downloads.StatusInfo"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="downloadId" type="long">
+</parameter>
+</method>
+<method name="openDownload"
+ return="android.os.ParcelFileDescriptor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="downloadId" type="long">
+</parameter>
+<parameter name="mode" type="java.lang.String">
+</parameter>
+<exception name="FileNotFoundException" type="java.io.FileNotFoundException">
+</exception>
+</method>
+<method name="openDownloadStream"
+ return="java.io.InputStream"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="downloadId" type="long">
+</parameter>
+<exception name="FileNotFoundException" type="java.io.FileNotFoundException">
+</exception>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+</class>
+<class name="Downloads.ByUri"
+ extends="android.net.Downloads.DownloadBase"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getStatus"
+ return="android.net.Downloads.StatusInfo"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="url" type="java.lang.String">
+</parameter>
+<parameter name="redownload_threshold" type="long">
+</parameter>
+</method>
+<method name="removeAllDownloadsByPackage"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="notification_package" type="java.lang.String">
+</parameter>
+<parameter name="notification_class" type="java.lang.String">
+</parameter>
+</method>
+</class>
+<class name="Downloads.DownloadBase"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="private"
+>
+<method name="startDownloadByUri"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="url" type="java.lang.String">
+</parameter>
+<parameter name="cookieData" type="java.lang.String">
+</parameter>
+<parameter name="showDownload" type="boolean">
+</parameter>
+<parameter name="downloadDestination" type="int">
+</parameter>
+<parameter name="allowRoaming" type="boolean">
+</parameter>
+<parameter name="skipIntegrityCheck" type="boolean">
+</parameter>
+<parameter name="title" type="java.lang.String">
+</parameter>
+<parameter name="notification_package" type="java.lang.String">
+</parameter>
+<parameter name="notification_class" type="java.lang.String">
+</parameter>
+<parameter name="notification_extras" type="java.lang.String">
+</parameter>
+</method>
+</class>
+<class name="Downloads.StatusInfo"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Downloads.StatusInfo"
+ type="android.net.Downloads.StatusInfo"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="isComplete"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isSuccessful"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<field name="bytesSoFar"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="completed"
+ type="boolean"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="filename"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="id"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="statusCode"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="LocalServerSocket"
  extends="java.lang.Object"
  abstract="false"
@@ -86645,15 +87178,11 @@
  type="android.net.SSLCertificateSocketFactory"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
-<parameter name="socketReadTimeoutForSslHandshake" type="int">
+<parameter name="handshakeTimeoutMillis" type="int">
 </parameter>
-<exception name="KeyManagementException" type="java.security.KeyManagementException">
-</exception>
-<exception name="NoSuchAlgorithmException" type="java.security.NoSuchAlgorithmException">
-</exception>
 </constructor>
 <method name="createSocket"
  return="java.net.Socket"
@@ -86665,13 +87194,13 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="socket" type="java.net.Socket">
+<parameter name="k" type="java.net.Socket">
 </parameter>
-<parameter name="s" type="java.lang.String">
+<parameter name="host" type="java.lang.String">
 </parameter>
-<parameter name="i" type="int">
+<parameter name="port" type="int">
 </parameter>
-<parameter name="flag" type="boolean">
+<parameter name="close" type="boolean">
 </parameter>
 <exception name="IOException" type="java.io.IOException">
 </exception>
@@ -86686,13 +87215,13 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="inaddr" type="java.net.InetAddress">
+<parameter name="addr" type="java.net.InetAddress">
 </parameter>
-<parameter name="i" type="int">
+<parameter name="port" type="int">
 </parameter>
-<parameter name="inaddr2" type="java.net.InetAddress">
+<parameter name="localAddr" type="java.net.InetAddress">
 </parameter>
-<parameter name="j" type="int">
+<parameter name="localPort" type="int">
 </parameter>
 <exception name="IOException" type="java.io.IOException">
 </exception>
@@ -86707,9 +87236,9 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="inaddr" type="java.net.InetAddress">
+<parameter name="addr" type="java.net.InetAddress">
 </parameter>
-<parameter name="i" type="int">
+<parameter name="port" type="int">
 </parameter>
 <exception name="IOException" type="java.io.IOException">
 </exception>
@@ -86724,13 +87253,13 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="s" type="java.lang.String">
+<parameter name="host" type="java.lang.String">
 </parameter>
-<parameter name="i" type="int">
+<parameter name="port" type="int">
 </parameter>
-<parameter name="inaddr" type="java.net.InetAddress">
+<parameter name="localAddr" type="java.net.InetAddress">
 </parameter>
-<parameter name="j" type="int">
+<parameter name="localPort" type="int">
 </parameter>
 <exception name="IOException" type="java.io.IOException">
 </exception>
@@ -86745,9 +87274,9 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="s" type="java.lang.String">
+<parameter name="host" type="java.lang.String">
 </parameter>
-<parameter name="i" type="int">
+<parameter name="port" type="int">
 </parameter>
 <exception name="IOException" type="java.io.IOException">
 </exception>
@@ -86762,7 +87291,22 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="socketReadTimeoutForSslHandshake" type="int">
+<parameter name="handshakeTimeoutMillis" type="int">
+</parameter>
+</method>
+<method name="getDefault"
+ return="javax.net.SocketFactory"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="handshakeTimeoutMillis" type="int">
+</parameter>
+<parameter name="cache" type="android.net.SSLSessionCache">
 </parameter>
 </method>
 <method name="getDefaultCipherSuites"
@@ -86776,6 +87320,21 @@
  visibility="public"
 >
 </method>
+<method name="getHttpSocketFactory"
+ return="org.apache.http.conn.ssl.SSLSocketFactory"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="handshakeTimeoutMillis" type="int">
+</parameter>
+<parameter name="cache" type="android.net.SSLSessionCache">
+</parameter>
+</method>
 <method name="getSupportedCipherSuites"
  return="java.lang.String[]"
  abstract="false"
@@ -86788,6 +87347,37 @@
 >
 </method>
 </class>
+<class name="SSLSessionCache"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="SSLSessionCache"
+ type="android.net.SSLSessionCache"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dir" type="java.io.File">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</constructor>
+<constructor name="SSLSessionCache"
+ type="android.net.SSLSessionCache"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+</class>
 <class name="TrafficStats"
  extends="java.lang.Object"
  abstract="false"
@@ -118029,7 +118619,18 @@
  visibility="public"
 >
 </field>
-<field name="OperationFailedVolumeNotMounted"
+<field name="OperationFailedStorageMounted"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="OperationFailedStorageNotMounted"
  type="int"
  transient="false"
  volatile="false"
@@ -120741,6 +121342,21 @@
 <parameter name="search" type="java.lang.String">
 </parameter>
 </method>
+<method name="allowGeolocation"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cr" type="android.content.ContentResolver">
+</parameter>
+<parameter name="origin" type="java.lang.String">
+</parameter>
+</method>
 <method name="canClearHistory"
  return="boolean"
  abstract="false"
@@ -120754,6 +121370,21 @@
 <parameter name="cr" type="android.content.ContentResolver">
 </parameter>
 </method>
+<method name="clearGeolocation"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cr" type="android.content.ContentResolver">
+</parameter>
+<parameter name="origin" type="java.lang.String">
+</parameter>
+</method>
 <method name="clearHistory"
  return="void"
  abstract="false"
@@ -120953,6 +121584,16 @@
  visibility="public"
 >
 </field>
+<field name="GEOLOCATION_URI"
+ type="android.net.Uri"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="HISTORY_PROJECTION"
  type="java.lang.String[]"
  transient="false"
@@ -121225,6 +121866,34 @@
 >
 </field>
 </class>
+<class name="Browser.GeolocationColumns"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Browser.GeolocationColumns"
+ type="android.provider.Browser.GeolocationColumns"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="ORIGIN"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;origin&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
 <class name="Browser.SearchColumns"
  extends="java.lang.Object"
  abstract="false"
@@ -135740,6 +136409,28 @@
 <parameter name="listener" type="android.speech.RecognitionService.Callback">
 </parameter>
 </method>
+<field name="SERVICE_INTERFACE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.RecognitionService&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SERVICE_META_DATA"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="RecognitionService.Callback"
  extends="java.lang.Object"
@@ -135940,6 +136631,17 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_PARTIAL_RESULTS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.speech.extra.PARTIAL_RESULTS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="EXTRA_PROMPT"
  type="java.lang.String"
  transient="false"
@@ -139648,7 +140350,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="bundleWithValues" type="android.os.Bundle">
+<parameter name="bundle" type="android.os.Bundle">
 </parameter>
 </constructor>
 <method name="fillInNotifierBundle"
@@ -140657,7 +141359,7 @@
  type="android.test.ActivityInstrumentationTestCase2"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="pkg" type="java.lang.String">
@@ -140665,6 +141367,16 @@
 <parameter name="activityClass" type="java.lang.Class&lt;T&gt;">
 </parameter>
 </constructor>
+<constructor name="ActivityInstrumentationTestCase2"
+ type="android.test.ActivityInstrumentationTestCase2"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="activityClass" type="java.lang.Class&lt;T&gt;">
+</parameter>
+</constructor>
 <method name="getActivity"
  return="T"
  abstract="false"
@@ -145785,6 +146497,19 @@
 <parameter name="activity" type="android.content.ComponentName">
 </parameter>
 </method>
+<method name="canonicalToCurrentPackageNames"
+ return="java.lang.String[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="names" type="java.lang.String[]">
+</parameter>
+</method>
 <method name="checkPermission"
  return="int"
  abstract="false"
@@ -145843,6 +146568,19 @@
 <parameter name="packageName" type="java.lang.String">
 </parameter>
 </method>
+<method name="currentToCanonicalPackageNames"
+ return="java.lang.String[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="names" type="java.lang.String[]">
+</parameter>
+</method>
 <method name="getActivityIcon"
  return="android.graphics.drawable.Drawable"
  abstract="false"
@@ -163242,6 +163980,243 @@
 </method>
 </class>
 </package>
+<package name="android.util.base64"
+>
+<class name="Base64"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="decode"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="str" type="java.lang.String">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<method name="decode"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="input" type="byte[]">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<method name="decode"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="input" type="byte[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+<parameter name="len" type="int">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<method name="encode"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="input" type="byte[]">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<method name="encode"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="input" type="byte[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+<parameter name="len" type="int">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<method name="encodeToString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="input" type="byte[]">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<method name="encodeToString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="input" type="byte[]">
+</parameter>
+<parameter name="offset" type="int">
+</parameter>
+<parameter name="len" type="int">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<field name="CRLF"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ 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>
+<field name="NO_CLOSE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NO_PADDING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NO_WRAP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="URL_SAFE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Base64InputStream"
+ extends="java.io.FilterInputStream"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Base64InputStream"
+ type="android.util.base64.Base64InputStream"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="in" type="java.io.InputStream">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</constructor>
+</class>
+<class name="Base64OutputStream"
+ extends="java.io.FilterOutputStream"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="Base64OutputStream"
+ type="android.util.base64.Base64OutputStream"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="out" type="java.io.OutputStream">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</constructor>
+</class>
+</package>
 <package name="android.view"
 >
 <class name="AbsSavedState"
@@ -164453,6 +165428,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYBOARD_TAP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="LONG_PRESS"
  type="int"
  transient="false"
@@ -164464,6 +165450,17 @@
  visibility="public"
 >
 </field>
+<field name="SCROLL_BARRIER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="VIRTUAL_KEY"
  type="int"
  transient="false"
@@ -168106,6 +169103,28 @@
  visibility="public"
 >
 </method>
+<method name="getActionIndex"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getActionMasked"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getDeviceId"
  return="int"
  abstract="false"
@@ -168726,7 +169745,7 @@
  value="5"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -168737,7 +169756,7 @@
  value="6"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -168748,7 +169767,7 @@
  value="261"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -168759,7 +169778,7 @@
  value="262"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -168770,7 +169789,7 @@
  value="517"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -168781,7 +169800,7 @@
  value="518"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -168803,7 +169822,7 @@
  value="65280"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -168814,6 +169833,28 @@
  value="8"
  static="true"
  final="true"
+ deprecated="deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_POINTER_INDEX_MASK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="65280"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_POINTER_INDEX_SHIFT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -172878,6 +173919,25 @@
 <parameter name="heightMeasureSpec" type="int">
 </parameter>
 </method>
+<method name="onOverscrolled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="scrollX" type="int">
+</parameter>
+<parameter name="scrollY" type="int">
+</parameter>
+<parameter name="clampedX" type="boolean">
+</parameter>
+<parameter name="clampedY" type="boolean">
+</parameter>
+</method>
 <method name="onRestoreInstanceState"
  return="void"
  abstract="false"
@@ -173031,6 +174091,33 @@
 <parameter name="visibility" type="int">
 </parameter>
 </method>
+<method name="overscrollBy"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="deltaX" type="int">
+</parameter>
+<parameter name="deltaY" type="int">
+</parameter>
+<parameter name="scrollX" type="int">
+</parameter>
+<parameter name="scrollY" type="int">
+</parameter>
+<parameter name="scrollRangeX" type="int">
+</parameter>
+<parameter name="scrollRangeY" type="int">
+</parameter>
+<parameter name="maxOverscrollX" type="int">
+</parameter>
+<parameter name="maxOverscrollY" type="int">
+</parameter>
+</method>
 <method name="performClick"
  return="boolean"
  abstract="false"
@@ -214037,6 +215124,17 @@
  visibility="public"
 >
 </field>
+<field name="DEBUG_ENABLE_SAFEMODE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 </package>
 <package name="java.awt.font"
diff --git a/camera/libcameraservice/Android.mk b/camera/libcameraservice/Android.mk
index ecaebff..df5c166 100644
--- a/camera/libcameraservice/Android.mk
+++ b/camera/libcameraservice/Android.mk
@@ -48,7 +48,9 @@
     libutils \
     libbinder \
     libcutils \
-    libmedia
+    libmedia \
+    libcamera_client \
+    libsurfaceflinger_client
 
 LOCAL_MODULE:= libcameraservice
 
diff --git a/camera/libcameraservice/CameraHardwareStub.h b/camera/libcameraservice/CameraHardwareStub.h
index 8a67024..957813a4 100644
--- a/camera/libcameraservice/CameraHardwareStub.h
+++ b/camera/libcameraservice/CameraHardwareStub.h
@@ -20,7 +20,7 @@
 
 #include "FakeCamera.h"
 #include <utils/threads.h>
-#include <ui/CameraHardwareInterface.h>
+#include <camera/CameraHardwareInterface.h>
 #include <binder/MemoryBase.h>
 #include <binder/MemoryHeapBase.h>
 #include <utils/threads.h>
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index 405d471..86a6fac 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -25,7 +25,9 @@
 #include <utils/Errors.h>
 #include <binder/MemoryBase.h>
 #include <binder/MemoryHeapBase.h>
-#include <ui/ICameraService.h>
+#include <camera/ICameraService.h>
+#include <surfaceflinger/ISurface.h>
+#include <ui/Overlay.h>
 
 #include <media/mediaplayer.h>
 #include <media/AudioSystem.h>
diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h
index b3d20f6..bc49b1d 100644
--- a/camera/libcameraservice/CameraService.h
+++ b/camera/libcameraservice/CameraService.h
@@ -19,9 +19,9 @@
 #ifndef ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
 #define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
 
-#include <ui/ICameraService.h>
-#include <ui/CameraHardwareInterface.h>
-#include <ui/Camera.h>
+#include <camera/ICameraService.h>
+#include <camera/CameraHardwareInterface.h>
+#include <camera/Camera.h>
 
 namespace android {
 
diff --git a/camera/tests/CameraServiceTest/Android.mk b/camera/tests/CameraServiceTest/Android.mk
index 8da7c1f..9bb190a 100644
--- a/camera/tests/CameraServiceTest/Android.mk
+++ b/camera/tests/CameraServiceTest/Android.mk
@@ -17,6 +17,8 @@
 		libbinder \
                 libcutils \
                 libutils \
-                libui
+                libui \
+                libcamera_client \
+                libsurfaceflinger_client
 
 include $(BUILD_EXECUTABLE)
diff --git a/camera/tests/CameraServiceTest/CameraServiceTest.cpp b/camera/tests/CameraServiceTest/CameraServiceTest.cpp
index f89d9d3..9fc795b 100644
--- a/camera/tests/CameraServiceTest/CameraServiceTest.cpp
+++ b/camera/tests/CameraServiceTest/CameraServiceTest.cpp
@@ -6,13 +6,13 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
-#include <ui/ISurface.h>
-#include <ui/Camera.h>
-#include <ui/CameraParameters.h>
+#include <surfaceflinger/ISurface.h>
+#include <camera/Camera.h>
+#include <camera/CameraParameters.h>
 #include <ui/GraphicBuffer.h>
-#include <ui/ICamera.h>
-#include <ui/ICameraClient.h>
-#include <ui/ICameraService.h>
+#include <camera/ICamera.h>
+#include <camera/ICameraClient.h>
+#include <camera/ICameraService.h>
 #include <ui/Overlay.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk
index 939b63f..2b89759 100644
--- a/cmds/bootanimation/Android.mk
+++ b/cmds/bootanimation/Android.mk
@@ -21,7 +21,8 @@
     libui \
 	libskia \
     libEGL \
-    libGLESv1_CM
+    libGLESv1_CM \
+    libsurfaceflinger_client
 
 LOCAL_C_INCLUDES := \
 	$(call include-path-for, corecg graphics)
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index ce36c4b..ac2eb0d 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -34,11 +34,12 @@
 #include <ui/Rect.h>
 #include <ui/Region.h>
 #include <ui/DisplayInfo.h>
-#include <ui/ISurfaceComposer.h>
-#include <ui/ISurfaceFlingerClient.h>
 #include <ui/FramebufferNativeWindow.h>
 #include <ui/EGLUtils.h>
 
+#include <surfaceflinger/ISurfaceComposer.h>
+#include <surfaceflinger/ISurfaceFlingerClient.h>
+
 #include <core/SkBitmap.h>
 #include <images/SkImageDecoder.h>
 
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index e53ba8b..8e28bba 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -23,8 +23,8 @@
 #include <utils/threads.h>
 #include <utils/AssetManager.h>
 
-#include <ui/ISurfaceComposer.h>
-#include <ui/SurfaceComposerClient.h>
+#include <surfaceflinger/ISurfaceComposer.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
 
 #include <EGL/egl.h>
 #include <GLES/gl.h>
diff --git a/cmds/bootanimation/bootanimation_main.cpp b/cmds/bootanimation/bootanimation_main.cpp
index 3c82fe5..5f8b744 100644
--- a/cmds/bootanimation/bootanimation_main.cpp
+++ b/cmds/bootanimation/bootanimation_main.cpp
@@ -25,7 +25,7 @@
 #include <utils/Log.h>
 #include <utils/threads.h>
 
-#include <ui/ISurfaceComposer.h>
+#include <surfaceflinger/ISurfaceComposer.h>
 
 #if defined(HAVE_PTHREADS)
 # include <pthread.h>
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 1e8555b..a447f53 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -39,7 +39,7 @@
             return -1;
     }
 
-    if (mkdir(pkgdir, 0755) < 0) {
+    if (mkdir(pkgdir, 0751) < 0) {
         LOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
         return -errno;
     }
@@ -690,6 +690,83 @@
     }
 }
 
+int movefileordir(char* srcpath, char* dstpath, int dstuid, int dstgid,
+        struct stat* statbuf)
+{
+    DIR *d;
+    struct dirent *de;
+    int res;
+
+    int srcend = strlen(srcpath);
+    int dstend = strlen(dstpath);
+    
+    if (lstat(srcpath, statbuf) < 0) {
+        LOGW("Unable to stat %s: %s\n", srcpath, strerror(errno));
+        return 1;
+    }
+    
+    if ((statbuf->st_mode&S_IFDIR) == 0) {
+        LOGI("Renaming %s to %s (uid %d)\n", srcpath, dstpath, dstuid);
+        mkinnerdirs(dstpath, dstend-1, S_IRWXU|S_IRWXG|S_IXOTH, dstuid, dstgid);
+        if (rename(srcpath, dstpath) >= 0) {
+            if (chown(dstpath, dstuid, dstgid) < 0) {
+                LOGE("cannot chown %s: %s\n", dstpath, strerror(errno));
+                unlink(dstpath);
+                return 1;
+            }
+        } else {
+            LOGW("Unable to rename %s to %s: %s\n",
+                srcpath, dstpath, strerror(errno));
+            return 1;
+        }
+        return 0;
+    }
+
+    d = opendir(srcpath);
+    if (d == NULL) {
+        LOGW("Unable to opendir %s: %s\n", srcpath, strerror(errno));
+        return 1;
+    }
+
+    res = 0;
+    
+    while ((de = readdir(d))) {
+        const char *name = de->d_name;
+            /* always skip "." and ".." */
+        if (name[0] == '.') {
+            if (name[1] == 0) continue;
+            if ((name[1] == '.') && (name[2] == 0)) continue;
+        }
+        
+        if ((srcend+strlen(name)) >= (PKG_PATH_MAX-2)) {
+            LOGW("Source path too long; skipping: %s/%s\n", srcpath, name);
+            continue;
+        }
+        
+        if ((dstend+strlen(name)) >= (PKG_PATH_MAX-2)) {
+            LOGW("Destination path too long; skipping: %s/%s\n", dstpath, name);
+            continue;
+        }
+        
+        srcpath[srcend] = dstpath[dstend] = '/';
+        strcpy(srcpath+srcend+1, name);
+        strcpy(dstpath+dstend+1, name);
+        
+        if (movefileordir(srcpath, dstpath, dstuid, dstgid, statbuf) != 0) {
+            res = 1;
+        }
+        
+        // Note: we will be leaving empty directories behind in srcpath,
+        // but that is okay, the package manager will be erasing all of the
+        // data associated with .apks that disappear.
+        
+        srcpath[srcend] = dstpath[dstend] = 0;
+    }
+    
+    closedir(d);
+    return res;
+}
+
 int movefiles()
 {
     DIR *d;
@@ -703,7 +780,7 @@
     char dstpkg[PKG_NAME_MAX];
     char srcpath[PKG_PATH_MAX];
     char dstpath[PKG_PATH_MAX];
-    int dstuid, dstgid;
+    int dstuid=-1, dstgid=-1;
     int hasspace;
 
     d = opendir(UPDATE_COMMANDS_DIR_PREFIX);
@@ -757,18 +834,7 @@
                             LOGV("Move file: %s (from %s to %s)\n", buf+bufp, srcpkg, dstpkg);
                             if (!create_move_path(srcpath, PKG_DIR_PREFIX, srcpkg, buf+bufp) &&
                                     !create_move_path(dstpath, PKG_DIR_PREFIX, dstpkg, buf+bufp)) {
-                                LOGI("Renaming %s to %s (uid %d)\n", srcpath, dstpath, dstuid);
-                                mkinnerdirs(dstpath, strlen(dstpath)-(bufi-bufp),
-                                    S_IRWXU|S_IRWXG|S_IXOTH, dstuid, dstgid);
-                                if (rename(srcpath, dstpath) >= 0) {
-                                    if (chown(dstpath, dstuid, dstgid) < 0) {
-                                        LOGE("cannot chown %s: %s\n", dstpath, strerror(errno));
-                                        unlink(dstpath);
-                                    }
-                                } else {
-                                    LOGW("Unable to rename %s to %s: %s\n",
-                                        srcpath, dstpath, strerror(errno));
-                                }
+                                movefileordir(srcpath, dstpath, dstuid, dstgid, &s);
                             }
                         }
                     } else {
@@ -812,10 +878,11 @@
                                             dstuid = s.st_uid;
                                             dstgid = s.st_gid;
                                         } else {
+                                            // Destination package doesn't
+                                            // exist...  due to original-package,
+                                            // this is normal, so don't be
+                                            // noisy about it.
                                             srcpkg[0] = 0;
-                                            LOGW("Can't stat path %s in %s%s: %s\n",
-                                                    dstpath, UPDATE_COMMANDS_DIR_PREFIX,
-                                                    name, strerror(errno));
                                         }
                                     } else {
                                         srcpkg[0] = 0;
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 68373cb..ff16c6e 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -600,7 +600,7 @@
             } else if (opt.equals("-t")) {
                 installFlags |= PackageManager.INSTALL_ALLOW_TEST;
             } else if (opt.equals("-s")) {
-                installFlags |= PackageManager.INSTALL_ON_SDCARD;
+                installFlags |= PackageManager.INSTALL_EXTERNAL;
             } else {
                 System.err.println("Error: Unknown option: " + opt);
                 showUsage();
diff --git a/cmds/runtime/main_runtime.cpp b/cmds/runtime/main_runtime.cpp
index 21e0e4d..83cb533 100644
--- a/cmds/runtime/main_runtime.cpp
+++ b/cmds/runtime/main_runtime.cpp
@@ -19,7 +19,7 @@
 
 #include <private/utils/Static.h>
 
-#include <ui/ISurfaceComposer.h>
+#include <surfaceflinger/ISurfaceComposer.h>
 
 #include <android_runtime/AndroidRuntime.h>
 
diff --git a/common/Android.mk b/common/Android.mk
index 76091eb..5c5b01b 100644
--- a/common/Android.mk
+++ b/common/Android.mk
@@ -19,6 +19,7 @@
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := android-common
+LOCAL_SDK_VERSION := current
 LOCAL_SRC_FILES := $(call all-java-files-under, java)
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
diff --git a/common/java/com/android/common/AndroidHttpClient.java b/common/java/com/android/common/AndroidHttpClient.java
index 99faf6e..4c65eb0 100644
--- a/common/java/com/android/common/AndroidHttpClient.java
+++ b/common/java/com/android/common/AndroidHttpClient.java
@@ -47,8 +47,6 @@
 import org.apache.http.protocol.BasicHttpProcessor;
 import org.apache.http.protocol.HttpContext;
 import org.apache.http.protocol.BasicHttpContext;
-import org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache;
-import org.apache.harmony.xnet.provider.jsse.SSLContextImpl;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -59,11 +57,11 @@
 import java.net.URI;
 import java.security.KeyManagementException;
 
+import android.content.Context;
 import android.content.ContentResolver;
+import android.net.SSLCertificateSocketFactory;
+import android.net.SSLSessionCache;
 import android.os.Looper;
-import android.os.SystemProperties;
-import android.provider.Settings;
-import android.text.TextUtils;
 import android.util.Log;
 
 /**
@@ -76,11 +74,9 @@
  * To retain cookies, simply add a cookie store to the HttpContext:</p>
  *
  * <pre>context.setAttribute(ClientContext.COOKIE_STORE, cookieStore);</pre>
- * 
- * {@hide}
  */
 public final class AndroidHttpClient implements HttpClient {
-        
+
     // Gzip of data shorter than this probably won't be worthwhile
     public static long DEFAULT_SYNC_MIN_GZIP_BYTES = 256;
 
@@ -101,12 +97,11 @@
     /**
      * Create a new HttpClient with reasonable defaults (which you can update).
      *
-     * @param userAgent to report in your HTTP requests.
-     * @param sessionCache persistent session cache
+     * @param userAgent to report in your HTTP requests
+     * @param context to use for caching SSL sessions (may be null for no caching)
      * @return AndroidHttpClient for you to use for all your requests.
      */
-    public static AndroidHttpClient newInstance(String userAgent,
-            SSLClientSessionCache sessionCache) {
+    public static AndroidHttpClient newInstance(String userAgent, Context context) {
         HttpParams params = new BasicHttpParams();
 
         // Turn off stale checking.  Our connections break all the time anyway,
@@ -122,13 +117,16 @@
         // often wants to re-POST after a redirect, which we must do ourselves.
         HttpClientParams.setRedirecting(params, false);
 
+        // Use a session cache for SSL sockets
+        SSLSessionCache sessionCache = context == null ? null : new SSLSessionCache(context);
+
         // Set the specified user agent and register standard protocols.
         HttpProtocolParams.setUserAgent(params, userAgent);
         SchemeRegistry schemeRegistry = new SchemeRegistry();
         schemeRegistry.register(new Scheme("http",
                 PlainSocketFactory.getSocketFactory(), 80));
         schemeRegistry.register(new Scheme("https",
-                socketFactoryWithCache(sessionCache), 443));
+                SSLCertificateSocketFactory.getHttpSocketFactory(30 * 1000, sessionCache), 443));
 
         ClientConnectionManager manager =
                 new ThreadSafeClientConnManager(params, schemeRegistry);
@@ -139,32 +137,6 @@
     }
 
     /**
-     * Returns a socket factory backed by the given persistent session cache.
-     *
-     * @param sessionCache to retrieve sessions from, null for no cache
-     */
-    private static SSLSocketFactory socketFactoryWithCache(
-            SSLClientSessionCache sessionCache) {
-        if (sessionCache == null) {
-            // Use the default factory which doesn't support persistent
-            // caching.
-            return SSLSocketFactory.getSocketFactory();
-        }
-
-        // Create a new SSL context backed by the cache.
-        // TODO: Keep a weak *identity* hash map of caches to engines. In the
-        // mean time, if we have two engines for the same cache, they'll still
-        // share sessions but will have to do so through the persistent cache.
-        SSLContextImpl sslContext = new SSLContextImpl();
-        try {
-            sslContext.engineInit(null, null, null, sessionCache, null);
-        } catch (KeyManagementException e) {
-            throw new AssertionError(e);
-        }
-        return new SSLSocketFactory(sslContext.engineGetSocketFactory());
-    }
-
-    /**
      * Create a new HttpClient with reasonable defaults (which you can update).
      * @param userAgent to report in your HTTP requests.
      * @return AndroidHttpClient for you to use for all your requests.
@@ -339,9 +311,7 @@
      * Shorter data will not be compressed.
      */
     public static long getMinGzipSize(ContentResolver resolver) {
-        return Settings.Secure.getLong(resolver,
-                                       Settings.Secure.SYNC_MIN_GZIP_BYTES,
-                                       DEFAULT_SYNC_MIN_GZIP_BYTES);
+        return DEFAULT_SYNC_MIN_GZIP_BYTES;  // For now, this is just a constant.
     }
 
     /* cURL logging support. */
@@ -367,15 +337,6 @@
         }
 
         /**
-         * Returns true if auth logging is turned on for this configuration.  Can only be set on
-         * insecure devices.
-         */
-        private boolean isAuthLoggable() {
-            String secure = SystemProperties.get("ro.secure");
-            return "0".equals(secure) && Log.isLoggable(tag + "-auth", level);
-        }
-
-        /**
          * Prints a message using this configuration.
          */
         private void println(String message) {
@@ -421,8 +382,9 @@
             if (configuration != null
                     && configuration.isLoggable()
                     && request instanceof HttpUriRequest) {
-                configuration.println(toCurl((HttpUriRequest) request,
-                        configuration.isAuthLoggable()));
+                // Never print auth token -- we used to check ro.secure=0 to
+                // enable that, but can't do that in unbundled code.
+                configuration.println(toCurl((HttpUriRequest) request, false));
             }
         }
     }
diff --git a/common/java/com/android/common/ArrayListCursor.java b/common/java/com/android/common/ArrayListCursor.java
index cc1fe27..9ad5c36 100644
--- a/common/java/com/android/common/ArrayListCursor.java
+++ b/common/java/com/android/common/ArrayListCursor.java
@@ -115,11 +115,6 @@
     }
 
     @Override
-    public boolean deleteRow() {
-        return false;
-    }
-
-    @Override
     public String[] getColumnNames() {
         return mColumnNames;
     }
diff --git a/common/java/com/android/common/Base64.java b/common/java/com/android/common/Base64.java
deleted file mode 100644
index 771875c..0000000
--- a/common/java/com/android/common/Base64.java
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.common;
-
-/**
- * Utilities for encoding and decoding the Base64 encoding.  See RFCs
- * 2045 and 3548.
- */
-public class Base64 {
-    /**
-     * Default values for encoder/decoder flags.
-     */
-    public static final int DEFAULT = 0;
-
-    /**
-     * Encoder flag bit to indicate you want the padding '='
-     * characters at the end (if any) to be omitted.
-     */
-    public static final int NO_PADDING = 1;
-
-    /**
-     * Encoder flag bit to indicate you want all line terminators to
-     * be omitted (ie, the output will be on one long line).
-     */
-    public static final int NO_WRAP = 2;
-
-    /**
-     * Encoder flag bit to indicate you want lines to be ended with
-     * CRLF instead of just LF.
-     */
-    public static final int CRLF = 4;
-
-    /**
-     * Encoder/decoder flag bit to indicate using the "web safe"
-     * variant of Base64 (see RFC 3548 section 4) where '-' and '_'
-     * are used in place of '+' and '/'.
-     */
-    public static final int WEB_SAFE = 8;
-
-    /**
-     * Lookup table for turning bytes into their position in the
-     * Base64 alphabet.
-     */
-    private static final int DECODE[] = {
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
-        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
-        -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
-        15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
-        -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    };
-
-    /**
-     * Decode lookup table for the "web safe" variant (RFC 3548
-     * sec. 4) where - and _ replace + and /.
-     */
-    private static final int DECODE_WEBSAFE[] = {
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1,
-        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
-        -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
-        15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63,
-        -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    };
-
-    /** Non-data values in the DECODE arrays. */
-    private static final int SKIP = -1;
-    private static final int EQUALS = -2;
-
-    /**
-     * Decode the Base64-encoded data in input and return the data in
-     * a new byte array.
-     *
-     * The padding '=' characters at the end are considered optional, but
-     * if any are present, there must be the correct number of them.
-     *
-     * @param input the input String to decode, which is converted to
-     *               bytes using the default charset
-     * @param flags  controls certain features of the decoded output.
-     *               Pass {@code DEFAULT} to decode standard Base64.
-     *
-     * @throws IllegalArgumentException if the input contains
-     * incorrect padding
-     */
-    public static byte[] decode(String str, int flags) {
-        return decode(str.getBytes(), flags);
-    }
-
-    /**
-     * Decode the Base64-encoded data in input and return the data in
-     * a new byte array.
-     *
-     * The padding '=' characters at the end are considered optional, but
-     * if any are present, there must be the correct number of them.
-     *
-     * @param input the input array to decode
-     * @param flags  controls certain features of the decoded output.
-     *               Pass {@code DEFAULT} to decode standard Base64.
-     *
-     * @throws IllegalArgumentException if the input contains
-     * incorrect padding
-     */
-    public static byte[] decode(byte[] input, int flags) {
-        return decode(input, 0, input.length, flags);
-    }
-
-    /**
-     * Decode the Base64-encoded data in input and return the data in
-     * a new byte array.
-     *
-     * The padding '=' characters at the end are considered optional, but
-     * if any are present, there must be the correct number of them.
-     *
-     * @param input  the data to decode
-     * @param offset the position within the input array at which to start
-     * @param len    the number of bytes of input to decode
-     * @param flags  controls certain features of the decoded output.
-     *               Pass {@code DEFAULT} to decode standard Base64.
-     *
-     * @throws IllegalArgumentException if the input contains
-     * incorrect padding
-     */
-    public static byte[] decode(byte[] input, int offset, int len, int flags) {
-        int p = offset;
-        // Allocate space for the most data the input could represent.
-        // (It could contain less if it contains whitespace, etc.)
-        byte[] output = new byte[len*3/4];
-        len += offset;
-        int op = 0;
-
-        final int[] decode = ((flags & WEB_SAFE) == 0) ?
-            DECODE : DECODE_WEBSAFE;
-
-        int state = 0;
-        int value = 0;
-
-        while (p < len) {
-
-            // Try the fast path:  we're starting a new tuple and the
-            // next four bytes of the input stream are all data
-            // bytes.  This corresponds to going through states
-            // 0-1-2-3-0.  We expect to use this method for most of
-            // the data.
-            //
-            // If any of the next four bytes of input are non-data
-            // (whitespace, etc.), value will end up negative.  (All
-            // the non-data values in decode are small negative
-            // numbers, so shifting any of them up and or'ing them
-            // together will result in a value with its top bit set.)
-            //
-            // You can remove this whole block and the output should
-            // be the same, just slower.
-            if (state == 0 && p+4 <= len &&
-                (value = ((decode[input[p] & 0xff] << 18) |
-                          (decode[input[p+1] & 0xff] << 12) |
-                          (decode[input[p+2] & 0xff] << 6) |
-                          (decode[input[p+3] & 0xff]))) >= 0) {
-                output[op+2] = (byte) value;
-                output[op+1] = (byte) (value >> 8);
-                output[op] = (byte) (value >> 16);
-                op += 3;
-                p += 4;
-                continue;
-            }
-
-            // The fast path isn't available -- either we've read a
-            // partial tuple, or the next four input bytes aren't all
-            // data, or whatever.  Fall back to the slower state
-            // machine implementation.
-            //
-            // States 0-3 are reading through the next input tuple.
-            // State 4 is having read one '=' and expecting exactly
-            // one more.
-            // State 5 is expecting no more data or padding characters
-            // in the input.
-
-            int d = decode[input[p++] & 0xff];
-
-            switch (state) {
-                case 0:
-                    if (d >= 0) {
-                        value = d;
-                        ++state;
-                    } else if (d != SKIP) {
-                        throw new IllegalArgumentException("bad base-64");
-                    }
-                    break;
-
-                case 1:
-                    if (d >= 0) {
-                        value = (value << 6) | d;
-                        ++state;
-                    } else if (d != SKIP) {
-                        throw new IllegalArgumentException("bad base-64");
-                    }
-                    break;
-
-                case 2:
-                    if (d >= 0) {
-                        value = (value << 6) | d;
-                        ++state;
-                    } else if (d == EQUALS) {
-                        // Emit the last (partial) output tuple;
-                        // expect exactly one more padding character.
-                        output[op++] = (byte) (value >> 4);
-                        state = 4;
-                    } else if (d != SKIP) {
-                        throw new IllegalArgumentException("bad base-64");
-                    }
-                    break;
-
-                case 3:
-                    if (d >= 0) {
-                        // Emit the output triple and return to state 0.
-                        value = (value << 6) | d;
-                        output[op+2] = (byte) value;
-                        output[op+1] = (byte) (value >> 8);
-                        output[op] = (byte) (value >> 16);
-                        op += 3;
-                        state = 0;
-                    } else if (d == EQUALS) {
-                        // Emit the last (partial) output tuple;
-                        // expect no further data or padding characters.
-                        output[op+1] = (byte) (value >> 2);
-                        output[op] = (byte) (value >> 10);
-                        op += 2;
-                        state = 5;
-                    } else if (d != SKIP) {
-                        throw new IllegalArgumentException("bad base-64");
-                    }
-                    break;
-
-                case 4:
-                    if (d == EQUALS) {
-                        ++state;
-                    } else if (d != SKIP) {
-                        throw new IllegalArgumentException("bad base-64");
-                    }
-                    break;
-
-                case 5:
-                    if (d != SKIP) {
-                        throw new IllegalArgumentException("bad base-64");
-                    }
-                    break;
-            }
-        }
-
-        // Done reading input.  Now figure out where we are left in
-        // the state machine and finish up.
-
-        switch (state) {
-            case 0:
-                // Output length is a multiple of three.  Fine.
-                break;
-            case 1:
-                // Read one extra input byte, which isn't enough to
-                // make another output byte.  Illegal.
-                throw new IllegalArgumentException("bad base-64");
-            case 2:
-                // Read two extra input bytes, enough to emit 1 more
-                // output byte.  Fine.
-                output[op++] = (byte) (value >> 4);
-                break;
-            case 3:
-                // Read three extra input bytes, enough to emit 2 more
-                // output bytes.  Fine.
-                output[op+1] = (byte) (value >> 2);
-                output[op] = (byte) (value >> 10);
-                op += 2;
-                break;
-            case 4:
-                // Read one padding '=' when we expected 2.  Illegal.
-                throw new IllegalArgumentException("bad base-64");
-            case 5:
-                // Read all the padding '='s we expected and no more.
-                // Fine.
-                break;
-        }
-
-        // Maybe we got lucky and allocated exactly enough output space.
-        if (op == output.length) {
-            return output;
-        }
-
-        // Need to shorten the array, so allocate a new one of the
-        // right size and copy.
-        byte[] temp = new byte[op];
-        System.arraycopy(output, 0, temp, 0, op);
-        return temp;
-    }
-
-    /**
-     * Emit a new line every this many output tuples.  Corresponds to
-     * a 76-character line length (the maximum allowable according to
-     * RFC 2045).
-     */
-    private static final int LINE_GROUPS = 19;
-
-    /**
-     * Lookup table for turning Base64 alphabet positions (6 bits)
-     * into output bytes.
-     */
-    private static final byte ENCODE[] = {
-        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
-        'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
-        'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
-        'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
-        'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
-        'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
-        'w', 'x', 'y', 'z', '0', '1', '2', '3',
-        '4', '5', '6', '7', '8', '9', '+', '/',
-    };
-
-    /**
-     * Lookup table for turning Base64 alphabet positions (6 bits)
-     * into output bytes.
-     */
-    private static final byte ENCODE_WEBSAFE[] = {
-        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
-        'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
-        'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
-        'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
-        'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
-        'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
-        'w', 'x', 'y', 'z', '0', '1', '2', '3',
-        '4', '5', '6', '7', '8', '9', '-', '_',
-    };
-
-    /**
-     * Base64-encode the given data and return a newly allocated
-     * String with the result.
-     *
-     * @param input  the data to encode
-     * @param flags  controls certain features of the encoded output.
-     *               Passing {@code DEFAULT} results in output that
-     *               adheres to RFC 2045.
-     */
-    public static String encodeToString(byte[] input, int flags) {
-        return new String(encode(input, flags));
-    }
-
-    /**
-     * Base64-encode the given data and return a newly allocated
-     * String with the result.
-     *
-     * @param input  the data to encode
-     * @param offset the position within the input array at which to
-     *               start
-     * @param len    the number of bytes of input to encode
-     * @param flags  controls certain features of the encoded output.
-     *               Passing {@code DEFAULT} results in output that
-     *               adheres to RFC 2045.
-     */
-    public static String encodeToString(byte[] input, int offset, int len, int flags) {
-        return new String(encode(input, offset, len, flags));
-    }
-
-    /**
-     * Base64-encode the given data and return a newly allocated
-     * byte[] with the result.
-     *
-     * @param input  the data to encode
-     * @param flags  controls certain features of the encoded output.
-     *               Passing {@code DEFAULT} results in output that
-     *               adheres to RFC 2045.
-     */
-    public static byte[] encode(byte[] input, int flags) {
-        return encode(input, 0, input.length, flags);
-    }
-
-    /**
-     * Base64-encode the given data and return a newly allocated
-     * byte[] with the result.
-     *
-     * @param input  the data to encode
-     * @param offset the position within the input array at which to
-     *               start
-     * @param len    the number of bytes of input to encode
-     * @param flags  controls certain features of the encoded output.
-     *               Passing {@code DEFAULT} results in output that
-     *               adheres to RFC 2045.
-     */
-    public static byte[] encode(byte[] input, int offset, int len, int flags) {
-        final boolean do_padding = (flags & NO_PADDING) == 0;
-        final boolean do_newline = (flags & NO_WRAP) == 0;
-        final boolean do_cr = (flags & CRLF) != 0;
-
-        final byte[] encode = ((flags & WEB_SAFE) == 0) ? ENCODE : ENCODE_WEBSAFE;
-
-        // Compute the exact length of the array we will produce.
-        int output_len = len / 3 * 4;
-
-        // Account for the tail of the data and the padding bytes, if any.
-        if (do_padding) {
-            if (len % 3 > 0) {
-                output_len += 4;
-            }
-        } else {
-            switch (len % 3) {
-                case 0: break;
-                case 1: output_len += 2; break;
-                case 2: output_len += 3; break;
-            }
-        }
-
-        // Account for the newlines, if any.
-        if (do_newline && len > 0) {
-            output_len += (((len-1) / (3 * LINE_GROUPS)) + 1) * (do_cr ? 2 : 1);
-        }
-
-        int op = 0;
-        byte[] output = new byte[output_len];
-
-        // The main loop, turning 3 input bytes into 4 output bytes on
-        // each iteration.
-        int count = do_newline ? LINE_GROUPS : -1;
-        int p = offset;
-        len += offset;
-        while (p+3 <= len) {
-            int v = ((input[p++] & 0xff) << 16) |
-                ((input[p++] & 0xff) << 8) |
-                (input[p++] & 0xff);
-            output[op++] = encode[(v >> 18) & 0x3f];
-            output[op++] = encode[(v >> 12) & 0x3f];
-            output[op++] = encode[(v >> 6) & 0x3f];
-            output[op++] = encode[v & 0x3f];
-            if (--count == 0) {
-                if (do_cr) output[op++] = '\r';
-                output[op++] = '\n';
-                count = LINE_GROUPS;
-            }
-        }
-
-        // Finish up the tail of the input.
-        if (p == len-1) {
-            int v = (input[p] & 0xff) << 4;
-            output[op++] = encode[(v >> 6) & 0x3f];
-            output[op++] = encode[v & 0x3f];
-            if (do_padding) {
-                output[op++] = '=';
-                output[op++] = '=';
-            }
-            if (do_newline) {
-                if (do_cr) output[op++] = '\r';
-                output[op++] = '\n';
-            }
-        } else if (p == len-2) {
-            int v = ((input[p] & 0xff) << 10) | ((input[p+1] & 0xff) << 2);
-            output[op++] = encode[(v >> 12) & 0x3f];
-            output[op++] = encode[(v >> 6) & 0x3f];
-            output[op++] = encode[v & 0x3f];
-            if (do_padding) {
-                output[op++] = '=';
-            }
-            if (do_newline) {
-                if (do_cr) output[op++] = '\r';
-                output[op++] = '\n';
-            }
-        } else if (do_newline && op > 0 && count != LINE_GROUPS) {
-            if (do_cr) output[op++] = '\r';
-            output[op++] = '\n';
-        }
-
-        assert op == output.length;
-        return output;
-    }
-
-    private Base64() { }   // don't instantiate
-}
diff --git a/common/java/com/android/common/Search.java b/common/java/com/android/common/Search.java
new file mode 100644
index 0000000..55fa6f5
--- /dev/null
+++ b/common/java/com/android/common/Search.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.common;
+
+/**
+ * Utilities for search implementations.
+ *
+ * @see android.app.SearchManager
+ */
+public class Search {
+
+    /**
+     * Key for the source identifier set by the application that launched a search intent.
+     * The identifier is search-source specific string. It can be used
+     * by the search provider to keep statistics of where searches are started from.
+     *
+     * The source identifier is stored in the {@link android.app.SearchManager#APP_DATA}
+     * Bundle in {@link android.content.Intent#ACTION_SEARCH} and
+     * {@link android.content.Intent#ACTION_WEB_SEARCH} intents.
+     */
+    public final static String SOURCE = "source";
+
+    private Search() { }   // don't instantiate
+}
diff --git a/common/java/com/android/common/ui/PointerLocationView.java b/common/java/com/android/common/ui/PointerLocationView.java
new file mode 100644
index 0000000..7bdb0bc
--- /dev/null
+++ b/common/java/com/android/common/ui/PointerLocationView.java
@@ -0,0 +1,337 @@
+package com.android.common.ui;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.FontMetricsInt;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+
+import java.util.ArrayList;
+
+public class PointerLocationView extends View {
+    public static class PointerState {
+        private final ArrayList<Float> mXs = new ArrayList<Float>();
+        private final ArrayList<Float> mYs = new ArrayList<Float>();
+        private boolean mCurDown;
+        private int mCurX;
+        private int mCurY;
+        private float mCurPressure;
+        private float mCurSize;
+        private int mCurWidth;
+        private VelocityTracker mVelocity;
+    }
+
+    private final ViewConfiguration mVC;
+    private final Paint mTextPaint;
+    private final Paint mTextBackgroundPaint;
+    private final Paint mTextLevelPaint;
+    private final Paint mPaint;
+    private final Paint mTargetPaint;
+    private final Paint mPathPaint;
+    private final FontMetricsInt mTextMetrics = new FontMetricsInt();
+    private int mHeaderBottom;
+    private boolean mCurDown;
+    private int mCurNumPointers;
+    private int mMaxNumPointers;
+    private final ArrayList<PointerState> mPointers
+             = new ArrayList<PointerState>();
+    
+    private boolean mPrintCoords = true;
+    
+    public PointerLocationView(Context c) {
+        super(c);
+        mVC = ViewConfiguration.get(c);
+        mTextPaint = new Paint();
+        mTextPaint.setAntiAlias(true);
+        mTextPaint.setTextSize(10
+                * getResources().getDisplayMetrics().density);
+        mTextPaint.setARGB(255, 0, 0, 0);
+        mTextBackgroundPaint = new Paint();
+        mTextBackgroundPaint.setAntiAlias(false);
+        mTextBackgroundPaint.setARGB(128, 255, 255, 255);
+        mTextLevelPaint = new Paint();
+        mTextLevelPaint.setAntiAlias(false);
+        mTextLevelPaint.setARGB(192, 255, 0, 0);
+        mPaint = new Paint();
+        mPaint.setAntiAlias(true);
+        mPaint.setARGB(255, 255, 255, 255);
+        mPaint.setStyle(Paint.Style.STROKE);
+        mPaint.setStrokeWidth(2);
+        mTargetPaint = new Paint();
+        mTargetPaint.setAntiAlias(false);
+        mTargetPaint.setARGB(255, 0, 0, 192);
+        mPathPaint = new Paint();
+        mPathPaint.setAntiAlias(false);
+        mPathPaint.setARGB(255, 0, 96, 255);
+        mPaint.setStyle(Paint.Style.STROKE);
+        mPaint.setStrokeWidth(1);
+        
+        PointerState ps = new PointerState();
+        ps.mVelocity = VelocityTracker.obtain();
+        mPointers.add(ps);
+    }
+
+    public void setPrintCoords(boolean state) {
+        mPrintCoords = state;
+    }
+    
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        mTextPaint.getFontMetricsInt(mTextMetrics);
+        mHeaderBottom = -mTextMetrics.ascent+mTextMetrics.descent+2;
+        if (false) {
+            Log.i("foo", "Metrics: ascent=" + mTextMetrics.ascent
+                    + " descent=" + mTextMetrics.descent
+                    + " leading=" + mTextMetrics.leading
+                    + " top=" + mTextMetrics.top
+                    + " bottom=" + mTextMetrics.bottom);
+        }
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        synchronized (mPointers) {
+            final int w = getWidth();
+            final int itemW = w/7;
+            final int base = -mTextMetrics.ascent+1;
+            final int bottom = mHeaderBottom;
+            
+            final int NP = mPointers.size();
+            
+            if (NP > 0) {
+                final PointerState ps = mPointers.get(0);
+                canvas.drawRect(0, 0, itemW-1, bottom,mTextBackgroundPaint);
+                canvas.drawText("P: " + mCurNumPointers + " / " + mMaxNumPointers,
+                        1, base, mTextPaint);
+                
+                final int N = ps.mXs.size();
+                if ((mCurDown && ps.mCurDown) || N == 0) {
+                    canvas.drawRect(itemW, 0, (itemW * 2) - 1, bottom, mTextBackgroundPaint);
+                    canvas.drawText("X: " + ps.mCurX, 1 + itemW, base, mTextPaint);
+                    canvas.drawRect(itemW * 2, 0, (itemW * 3) - 1, bottom, mTextBackgroundPaint);
+                    canvas.drawText("Y: " + ps.mCurY, 1 + itemW * 2, base, mTextPaint);
+                } else {
+                    float dx = ps.mXs.get(N-1) - ps.mXs.get(0);
+                    float dy = ps.mYs.get(N-1) - ps.mYs.get(0);
+                    canvas.drawRect(itemW, 0, (itemW * 2) - 1, bottom,
+                            Math.abs(dx) < mVC.getScaledTouchSlop()
+                            ? mTextBackgroundPaint : mTextLevelPaint);
+                    canvas.drawText("dX: " + String.format("%.1f", dx), 1 + itemW, base, mTextPaint);
+                    canvas.drawRect(itemW * 2, 0, (itemW * 3) - 1, bottom,
+                            Math.abs(dy) < mVC.getScaledTouchSlop()
+                            ? mTextBackgroundPaint : mTextLevelPaint);
+                    canvas.drawText("dY: " + String.format("%.1f", dy), 1 + itemW * 2, base, mTextPaint);
+                }
+                
+                canvas.drawRect(itemW * 3, 0, (itemW * 4) - 1, bottom, mTextBackgroundPaint);
+                int velocity = ps.mVelocity == null ? 0 : (int) (ps.mVelocity.getXVelocity() * 1000);
+                canvas.drawText("Xv: " + velocity, 1 + itemW * 3, base, mTextPaint);
+                
+                canvas.drawRect(itemW * 4, 0, (itemW * 5) - 1, bottom, mTextBackgroundPaint);
+                velocity = ps.mVelocity == null ? 0 : (int) (ps.mVelocity.getYVelocity() * 1000);
+                canvas.drawText("Yv: " + velocity, 1 + itemW * 4, base, mTextPaint);
+                
+                canvas.drawRect(itemW * 5, 0, (itemW * 6) - 1, bottom, mTextBackgroundPaint);
+                canvas.drawRect(itemW * 5, 0, (itemW * 5) + (ps.mCurPressure * itemW) - 1,
+                        bottom, mTextLevelPaint);
+                canvas.drawText("Prs: " + String.format("%.2f", ps.mCurPressure), 1 + itemW * 5,
+                        base, mTextPaint);
+                
+                canvas.drawRect(itemW * 6, 0, w, bottom, mTextBackgroundPaint);
+                canvas.drawRect(itemW * 6, 0, (itemW * 6) + (ps.mCurSize * itemW) - 1,
+                        bottom, mTextLevelPaint);
+                canvas.drawText("Size: " + String.format("%.2f", ps.mCurSize), 1 + itemW * 6,
+                        base, mTextPaint);
+            }
+            
+            for (int p=0; p<NP; p++) {
+                final PointerState ps = mPointers.get(p);
+                
+                if (mCurDown && ps.mCurDown) {
+                    canvas.drawLine(0, (int)ps.mCurY, getWidth(), (int)ps.mCurY, mTargetPaint);
+                    canvas.drawLine((int)ps.mCurX, 0, (int)ps.mCurX, getHeight(), mTargetPaint);
+                    int pressureLevel = (int)(ps.mCurPressure*255);
+                    mPaint.setARGB(255, pressureLevel, 128, 255-pressureLevel);
+                    canvas.drawPoint(ps.mCurX, ps.mCurY, mPaint);
+                    canvas.drawCircle(ps.mCurX, ps.mCurY, ps.mCurWidth, mPaint);
+                }
+            }
+            
+            for (int p=0; p<NP; p++) {
+                final PointerState ps = mPointers.get(p);
+                
+                final int N = ps.mXs.size();
+                float lastX=0, lastY=0;
+                boolean haveLast = false;
+                boolean drawn = false;
+                mPaint.setARGB(255, 128, 255, 255);
+                for (int i=0; i<N; i++) {
+                    float x = ps.mXs.get(i);
+                    float y = ps.mYs.get(i);
+                    if (Float.isNaN(x)) {
+                        haveLast = false;
+                        continue;
+                    }
+                    if (haveLast) {
+                        canvas.drawLine(lastX, lastY, x, y, mPathPaint);
+                        canvas.drawPoint(lastX, lastY, mPaint);
+                        drawn = true;
+                    }
+                    lastX = x;
+                    lastY = y;
+                    haveLast = true;
+                }
+                
+                if (drawn) {
+                    if (ps.mVelocity != null) {
+                        mPaint.setARGB(255, 255, 64, 128);
+                        float xVel = ps.mVelocity.getXVelocity() * (1000/60);
+                        float yVel = ps.mVelocity.getYVelocity() * (1000/60);
+                        canvas.drawLine(lastX, lastY, lastX+xVel, lastY+yVel, mPaint);
+                    } else {
+                        canvas.drawPoint(lastX, lastY, mPaint);
+                    }
+                }
+            }
+        }
+    }
+
+    public void addTouchEvent(MotionEvent event) {
+        synchronized (mPointers) {
+            int action = event.getAction();
+            
+            //Log.i("Pointer", "Motion: action=0x" + Integer.toHexString(action)
+            //        + " pointers=" + event.getPointerCount());
+            
+            int NP = mPointers.size();
+            
+            //mRect.set(0, 0, getWidth(), mHeaderBottom+1);
+            //invalidate(mRect);
+            //if (mCurDown) {
+            //    mRect.set(mCurX-mCurWidth-3, mCurY-mCurWidth-3,
+            //            mCurX+mCurWidth+3, mCurY+mCurWidth+3);
+            //} else {
+            //    mRect.setEmpty();
+            //}
+            if (action == MotionEvent.ACTION_DOWN) {
+                for (int p=0; p<NP; p++) {
+                    final PointerState ps = mPointers.get(p);
+                    ps.mXs.clear();
+                    ps.mYs.clear();
+                    ps.mVelocity = VelocityTracker.obtain();
+                    ps.mCurDown = false;
+                }
+                mPointers.get(0).mCurDown = true;
+                mMaxNumPointers = 0;
+                if (mPrintCoords) {
+                    Log.i("Pointer", "Pointer 1: DOWN");
+                }
+            }
+            
+            if ((action&MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_DOWN) {
+                final int index = (action&MotionEvent.ACTION_POINTER_INDEX_MASK)
+                        >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+                final int id = event.getPointerId(index);
+                while (NP <= id) {
+                    PointerState ps = new PointerState();
+                    ps.mVelocity = VelocityTracker.obtain();
+                    mPointers.add(ps);
+                    NP++;
+                }
+                final PointerState ps = mPointers.get(id);
+                ps.mVelocity = VelocityTracker.obtain();
+                ps.mCurDown = true;
+                if (mPrintCoords) {
+                    Log.i("Pointer", "Pointer " + (id+1) + ": DOWN");
+                }
+            }
+            
+            final int NI = event.getPointerCount();
+            
+            mCurDown = action != MotionEvent.ACTION_UP
+                    && action != MotionEvent.ACTION_CANCEL;
+            mCurNumPointers = mCurDown ? NI : 0;
+            if (mMaxNumPointers < mCurNumPointers) {
+                mMaxNumPointers = mCurNumPointers;
+            }
+            
+            for (int i=0; i<NI; i++) {
+                final int id = event.getPointerId(i);
+                final PointerState ps = mPointers.get(id);
+                ps.mVelocity.addMovement(event);
+                ps.mVelocity.computeCurrentVelocity(1);
+                final int N = event.getHistorySize();
+                for (int j=0; j<N; j++) {
+                    if (mPrintCoords) {
+                        Log.i("Pointer", "Pointer " + (id+1) + ": ("
+                                + event.getHistoricalX(i, j)
+                                + ", " + event.getHistoricalY(i, j) + ")"
+                                + " Prs=" + event.getHistoricalPressure(i, j)
+                                + " Size=" + event.getHistoricalSize(i, j));
+                    }
+                    ps.mXs.add(event.getHistoricalX(i, j));
+                    ps.mYs.add(event.getHistoricalY(i, j));
+                }
+                if (mPrintCoords) {
+                    Log.i("Pointer", "Pointer " + (id+1) + ": ("
+                            + event.getX(i) + ", " + event.getY(i) + ")"
+                            + " Prs=" + event.getPressure(i)
+                            + " Size=" + event.getSize(i));
+                }
+                ps.mXs.add(event.getX(i));
+                ps.mYs.add(event.getY(i));
+                ps.mCurX = (int)event.getX(i);
+                ps.mCurY = (int)event.getY(i);
+                //Log.i("Pointer", "Pointer #" + p + ": (" + ps.mCurX
+                //        + "," + ps.mCurY + ")");
+                ps.mCurPressure = event.getPressure(i);
+                ps.mCurSize = event.getSize(i);
+                ps.mCurWidth = (int)(ps.mCurSize*(getWidth()/3));
+            }
+            
+            if ((action&MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_UP) {
+                final int index = (action&MotionEvent.ACTION_POINTER_INDEX_MASK)
+                        >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+                final int id = event.getPointerId(index);
+                final PointerState ps = mPointers.get(id);
+                ps.mXs.add(Float.NaN);
+                ps.mYs.add(Float.NaN);
+                ps.mCurDown = false;
+                if (mPrintCoords) {
+                    Log.i("Pointer", "Pointer " + (id+1) + ": UP");
+                }
+            }
+            
+            if (action == MotionEvent.ACTION_UP) {
+                for (int i=0; i<NI; i++) {
+                    final int id = event.getPointerId(i);
+                    final PointerState ps = mPointers.get(id);
+                    if (ps.mCurDown) {
+                        ps.mCurDown = false;
+                        if (mPrintCoords) {
+                            Log.i("Pointer", "Pointer " + (id+1) + ": UP");
+                        }
+                    }
+                }
+            }
+            
+            //if (mCurDown) {
+            //    mRect.union(mCurX-mCurWidth-3, mCurY-mCurWidth-3,
+            //            mCurX+mCurWidth+3, mCurY+mCurWidth+3);
+            //}
+            //invalidate(mRect);
+            postInvalidate();
+        }
+    }
+    
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        addTouchEvent(event);
+        return true;
+    }
+}
diff --git a/common/tests/src/com/android/common/Base64Test.java b/common/tests/src/com/android/common/Base64Test.java
deleted file mode 100644
index 5c9712a..0000000
--- a/common/tests/src/com/android/common/Base64Test.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.common;
-
-import junit.framework.TestCase;
-
-public class Base64Test extends TestCase {
-    private static final String TAG = "B64Test";
-
-    /** Decodes a string, returning a string. */
-    private String decodeString(String in) throws Exception {
-        byte[] out = Base64.decode(in, 0);
-        return new String(out);
-    }
-
-    /**
-     * Encodes the string 'in' using 'flags'.  Asserts that decoding
-     * gives the same string.  Returns the encoded string.
-     */
-    private String encodeToString(String in, int flags) throws Exception {
-        String b64 = Base64.encodeToString(in.getBytes(), flags);
-        String dec = decodeString(b64);
-        assertEquals(in, dec);
-        return b64;
-    }
-
-    /** Assert that decoding 'in' throws IllegalArgumentException. */
-    private void assertBad(String in) throws Exception {
-        try {
-            byte[] out = Base64.decode(in, 0);
-            fail("should have failed to decode");
-        } catch (IllegalArgumentException e) {
-        }
-    }
-
-    /** Assert that actual equals the first len bytes of expected. */
-    private void assertEquals(byte[] expected, int len, byte[] actual) {
-        assertEquals(len, actual.length);
-        for (int i = 0; i < len; ++i) {
-            assertEquals(expected[i], actual[i]);
-        }
-    }
-
-    public void testDecodeExtraChars() throws Exception {
-        // padding 0
-        assertEquals("hello, world", decodeString("aGVsbG8sIHdvcmxk"));
-        assertBad("aGVsbG8sIHdvcmxk=");
-        assertBad("aGVsbG8sIHdvcmxk==");
-        assertBad("aGVsbG8sIHdvcmxk =");
-        assertBad("aGVsbG8sIHdvcmxk = = ");
-        assertEquals("hello, world", decodeString(" aGVs bG8s IHdv cmxk  "));
-        assertEquals("hello, world", decodeString(" aGV sbG8 sIHd vcmx k "));
-        assertEquals("hello, world", decodeString(" aG VsbG 8sIH dvcm xk "));
-        assertEquals("hello, world", decodeString(" a GVsb G8sI Hdvc mxk "));
-        assertEquals("hello, world", decodeString(" a G V s b G 8 s I H d v c m x k "));
-        assertEquals("hello, world", decodeString("_a*G_V*s_b*G_8*s_I*H_d*v_c*m_x*k_"));
-        assertEquals("hello, world", decodeString("aGVsbG8sIHdvcmxk"));
-
-        // padding 1
-        assertEquals("hello, world?!", decodeString("aGVsbG8sIHdvcmxkPyE="));
-        assertEquals("hello, world?!", decodeString("aGVsbG8sIHdvcmxkPyE"));
-        assertBad("aGVsbG8sIHdvcmxkPyE==");
-        assertBad("aGVsbG8sIHdvcmxkPyE ==");
-        assertBad("aGVsbG8sIHdvcmxkPyE = = ");
-        assertEquals("hello, world?!", decodeString("aGVsbG8sIHdvcmxkPy E="));
-        assertEquals("hello, world?!", decodeString("aGVsbG8sIHdvcmxkPy E"));
-        assertEquals("hello, world?!", decodeString("aGVsbG8sIHdvcmxkPy E ="));
-        assertEquals("hello, world?!", decodeString("aGVsbG8sIHdvcmxkPy E "));
-        assertEquals("hello, world?!", decodeString("aGVsbG8sIHdvcmxkPy E = "));
-        assertEquals("hello, world?!", decodeString("aGVsbG8sIHdvcmxkPy E   "));
-
-        // padding 2
-        assertEquals("hello, world.", decodeString("aGVsbG8sIHdvcmxkLg=="));
-        assertEquals("hello, world.", decodeString("aGVsbG8sIHdvcmxkLg"));
-        assertBad("aGVsbG8sIHdvcmxkLg=");
-        assertBad("aGVsbG8sIHdvcmxkLg =");
-        assertBad("aGVsbG8sIHdvcmxkLg = ");
-        assertEquals("hello, world.", decodeString("aGVsbG8sIHdvcmxkL g=="));
-        assertEquals("hello, world.", decodeString("aGVsbG8sIHdvcmxkL g"));
-        assertEquals("hello, world.", decodeString("aGVsbG8sIHdvcmxkL g =="));
-        assertEquals("hello, world.", decodeString("aGVsbG8sIHdvcmxkL g "));
-        assertEquals("hello, world.", decodeString("aGVsbG8sIHdvcmxkL g = = "));
-        assertEquals("hello, world.", decodeString("aGVsbG8sIHdvcmxkL g   "));
-    }
-
-    private static final byte[] BYTES = { (byte) 0xff, (byte) 0xee, (byte) 0xdd,
-                                          (byte) 0xcc, (byte) 0xbb, (byte) 0xaa,
-                                          (byte) 0x99, (byte) 0x88, (byte) 0x77 };
-
-    public void testBinaryDecode() throws Exception {
-        assertEquals(BYTES, 0, Base64.decode("", 0));
-        assertEquals(BYTES, 1, Base64.decode("/w==", 0));
-        assertEquals(BYTES, 2, Base64.decode("/+4=", 0));
-        assertEquals(BYTES, 3, Base64.decode("/+7d", 0));
-        assertEquals(BYTES, 4, Base64.decode("/+7dzA==", 0));
-        assertEquals(BYTES, 5, Base64.decode("/+7dzLs=", 0));
-        assertEquals(BYTES, 6, Base64.decode("/+7dzLuq", 0));
-        assertEquals(BYTES, 7, Base64.decode("/+7dzLuqmQ==", 0));
-        assertEquals(BYTES, 8, Base64.decode("/+7dzLuqmYg=", 0));
-    }
-
-    public void testWebSafe() throws Exception {
-        assertEquals(BYTES, 0, Base64.decode("", Base64.WEB_SAFE));
-        assertEquals(BYTES, 1, Base64.decode("_w==", Base64.WEB_SAFE));
-        assertEquals(BYTES, 2, Base64.decode("_-4=", Base64.WEB_SAFE));
-        assertEquals(BYTES, 3, Base64.decode("_-7d", Base64.WEB_SAFE));
-        assertEquals(BYTES, 4, Base64.decode("_-7dzA==", Base64.WEB_SAFE));
-        assertEquals(BYTES, 5, Base64.decode("_-7dzLs=", Base64.WEB_SAFE));
-        assertEquals(BYTES, 6, Base64.decode("_-7dzLuq", Base64.WEB_SAFE));
-        assertEquals(BYTES, 7, Base64.decode("_-7dzLuqmQ==", Base64.WEB_SAFE));
-        assertEquals(BYTES, 8, Base64.decode("_-7dzLuqmYg=", Base64.WEB_SAFE));
-
-        assertEquals("", Base64.encodeToString(BYTES, 0, 0, Base64.WEB_SAFE));
-        assertEquals("_w==\n", Base64.encodeToString(BYTES, 0, 1, Base64.WEB_SAFE));
-        assertEquals("_-4=\n", Base64.encodeToString(BYTES, 0, 2, Base64.WEB_SAFE));
-        assertEquals("_-7d\n", Base64.encodeToString(BYTES, 0, 3, Base64.WEB_SAFE));
-        assertEquals("_-7dzA==\n", Base64.encodeToString(BYTES, 0, 4, Base64.WEB_SAFE));
-        assertEquals("_-7dzLs=\n", Base64.encodeToString(BYTES, 0, 5, Base64.WEB_SAFE));
-        assertEquals("_-7dzLuq\n", Base64.encodeToString(BYTES, 0, 6, Base64.WEB_SAFE));
-        assertEquals("_-7dzLuqmQ==\n", Base64.encodeToString(BYTES, 0, 7, Base64.WEB_SAFE));
-        assertEquals("_-7dzLuqmYg=\n", Base64.encodeToString(BYTES, 0, 8, Base64.WEB_SAFE));
-    }
-
-    public void testFlags() throws Exception {
-        assertEquals("YQ==\n",       encodeToString("a", 0));
-        assertEquals("YQ==",         encodeToString("a", Base64.NO_WRAP));
-        assertEquals("YQ\n",         encodeToString("a", Base64.NO_PADDING));
-        assertEquals("YQ",           encodeToString("a", Base64.NO_PADDING | Base64.NO_WRAP));
-        assertEquals("YQ==\r\n",     encodeToString("a", Base64.CRLF));
-        assertEquals("YQ\r\n",       encodeToString("a", Base64.CRLF | Base64.NO_PADDING));
-
-        assertEquals("YWI=\n",       encodeToString("ab", 0));
-        assertEquals("YWI=",         encodeToString("ab", Base64.NO_WRAP));
-        assertEquals("YWI\n",        encodeToString("ab", Base64.NO_PADDING));
-        assertEquals("YWI",          encodeToString("ab", Base64.NO_PADDING | Base64.NO_WRAP));
-        assertEquals("YWI=\r\n",     encodeToString("ab", Base64.CRLF));
-        assertEquals("YWI\r\n",      encodeToString("ab", Base64.CRLF | Base64.NO_PADDING));
-
-        assertEquals("YWJj\n",       encodeToString("abc", 0));
-        assertEquals("YWJj",         encodeToString("abc", Base64.NO_WRAP));
-        assertEquals("YWJj\n",       encodeToString("abc", Base64.NO_PADDING));
-        assertEquals("YWJj",         encodeToString("abc", Base64.NO_PADDING | Base64.NO_WRAP));
-        assertEquals("YWJj\r\n",     encodeToString("abc", Base64.CRLF));
-        assertEquals("YWJj\r\n",     encodeToString("abc", Base64.CRLF | Base64.NO_PADDING));
-
-        assertEquals("YWJjZA==\n",   encodeToString("abcd", 0));
-        assertEquals("YWJjZA==",     encodeToString("abcd", Base64.NO_WRAP));
-        assertEquals("YWJjZA\n",     encodeToString("abcd", Base64.NO_PADDING));
-        assertEquals("YWJjZA",       encodeToString("abcd", Base64.NO_PADDING | Base64.NO_WRAP));
-        assertEquals("YWJjZA==\r\n", encodeToString("abcd", Base64.CRLF));
-        assertEquals("YWJjZA\r\n",   encodeToString("abcd", Base64.CRLF | Base64.NO_PADDING));
-    }
-
-    public void testLineLength() throws Exception {
-        String in_56 = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd";
-        String in_57 = in_56 + "e";
-        String in_58 = in_56 + "ef";
-        String in_59 = in_56 + "efg";
-        String in_60 = in_56 + "efgh";
-        String in_61 = in_56 + "efghi";
-
-        String prefix = "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5emFi";
-        String out_56 = prefix + "Y2Q=\n";
-        String out_57 = prefix + "Y2Rl\n";
-        String out_58 = prefix + "Y2Rl\nZg==\n";
-        String out_59 = prefix + "Y2Rl\nZmc=\n";
-        String out_60 = prefix + "Y2Rl\nZmdo\n";
-        String out_61 = prefix + "Y2Rl\nZmdoaQ==\n";
-
-        // no newline for an empty input array.
-        assertEquals("", encodeToString("", 0));
-
-        assertEquals(out_56, encodeToString(in_56, 0));
-        assertEquals(out_57, encodeToString(in_57, 0));
-        assertEquals(out_58, encodeToString(in_58, 0));
-        assertEquals(out_59, encodeToString(in_59, 0));
-        assertEquals(out_60, encodeToString(in_60, 0));
-        assertEquals(out_61, encodeToString(in_61, 0));
-
-        assertEquals(out_56.replaceAll("=", ""), encodeToString(in_56, Base64.NO_PADDING));
-        assertEquals(out_57.replaceAll("=", ""), encodeToString(in_57, Base64.NO_PADDING));
-        assertEquals(out_58.replaceAll("=", ""), encodeToString(in_58, Base64.NO_PADDING));
-        assertEquals(out_59.replaceAll("=", ""), encodeToString(in_59, Base64.NO_PADDING));
-        assertEquals(out_60.replaceAll("=", ""), encodeToString(in_60, Base64.NO_PADDING));
-        assertEquals(out_61.replaceAll("=", ""), encodeToString(in_61, Base64.NO_PADDING));
-
-        assertEquals(out_56.replaceAll("\n", ""), encodeToString(in_56, Base64.NO_WRAP));
-        assertEquals(out_57.replaceAll("\n", ""), encodeToString(in_57, Base64.NO_WRAP));
-        assertEquals(out_58.replaceAll("\n", ""), encodeToString(in_58, Base64.NO_WRAP));
-        assertEquals(out_59.replaceAll("\n", ""), encodeToString(in_59, Base64.NO_WRAP));
-        assertEquals(out_60.replaceAll("\n", ""), encodeToString(in_60, Base64.NO_WRAP));
-        assertEquals(out_61.replaceAll("\n", ""), encodeToString(in_61, Base64.NO_WRAP));
-    }
-}
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 652f405..be15ac9 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -27,6 +27,7 @@
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.Parcelable;
+import android.os.Build;
 import android.util.Log;
 
 import java.io.IOException;
@@ -841,7 +842,9 @@
                     "calling this from your main thread can lead to deadlock");
             Log.e(TAG, "calling this from your main thread can lead to deadlock and/or ANRs",
                     exception);
-            throw exception;
+            if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.FROYO) {
+                throw exception;
+            }
         }
     }
 
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index e3ccd00..7850124 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -1788,7 +1788,7 @@
         if (!permissionGranted && isDebuggableMonkeyBuild) {
             // TODO: Skip this check when running automated tests. Replace this
             // with a more general solution.
-            Log.w(TAG, "no credentials permission for usage of " + account + ", "
+            Log.d(TAG, "no credentials permission for usage of " + account + ", "
                     + authTokenType + " by uid " + Binder.getCallingUid()
                     + " but ignoring since this is a monkey build");
             return true;
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 9b9cbd5..db6a4bf 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -52,6 +52,7 @@
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
+import android.content.pm.PackageParser.Package;
 import android.content.res.AssetManager;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
@@ -85,6 +86,7 @@
 import android.os.Vibrator;
 import android.os.FileUtils.FileStatus;
 import android.os.storage.StorageManager;
+import android.provider.Settings;
 import android.telephony.TelephonyManager;
 import android.text.ClipboardManager;
 import android.util.AndroidRuntimeException;
@@ -1613,6 +1615,24 @@
         }
 
         @Override
+        public String[] currentToCanonicalPackageNames(String[] names) {
+            try {
+                return mPM.currentToCanonicalPackageNames(names);
+            } catch (RemoteException e) {
+                throw new RuntimeException("Package manager has died", e);
+            }
+        }
+        
+        @Override
+        public String[] canonicalToCurrentPackageNames(String[] names) {
+            try {
+                return mPM.canonicalToCurrentPackageNames(names);
+            } catch (RemoteException e) {
+                throw new RuntimeException("Package manager has died", e);
+            }
+        }
+        
+        @Override
         public Intent getLaunchIntentForPackage(String packageName) {
             // First see if the package has an INFO activity; the existence of
             // such an activity is implied to be the desired front-door for the
@@ -2639,76 +2659,6 @@
             return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
         }
 
-        // Constants related to app heuristics
-        // No-installation limit for internal flash: 10% or less space available
-        private static final double LOW_NAND_FLASH_TRESHOLD = 0.1;
-
-        // SD-to-internal app size threshold: currently set to 1 MB
-        private static final long INSTALL_ON_SD_THRESHOLD = (1024 * 1024);
-
-        @Override
-        public int recommendAppInstallLocation(ApplicationInfo appInfo, Uri packageURI) {
-            // Initial implementation:
-            // Package size = code size + cache size + data size
-            // If code size > 1 MB, install on SD card.
-            // Else install on internal NAND flash, unless space on NAND is less than 10%
-
-            if ((packageURI == null) || (appInfo == null)) {
-                return INSTALL_PARSE_FAILED_NOT_APK;
-            }
-
-            StatFs internalFlashStats = new StatFs(Environment.getDataDirectory().getPath());
-            StatFs sdcardStats = new StatFs(Environment.getExternalStorageDirectory().getPath());
-
-            long totalInternalFlashSize = (long)internalFlashStats.getBlockCount() *
-                    (long)internalFlashStats.getBlockSize();
-            long availInternalFlashSize = (long)internalFlashStats.getAvailableBlocks() *
-                    (long)internalFlashStats.getBlockSize();
-            long availSDSize = (long)sdcardStats.getAvailableBlocks() *
-                    (long)sdcardStats.getBlockSize();
-
-            double pctNandFree = (double)availInternalFlashSize / (double)totalInternalFlashSize;
-
-            final String archiveFilePath = packageURI.getPath();
-            File apkFile = new File(archiveFilePath);
-            long pkgLen = apkFile.length();
-
-            // Consider application flags preferences as well...
-            boolean installOnlyOnSD = ((appInfo.flags & PackageManager.INSTALL_ON_SDCARD) != 0);
-
-            // These are not very precise measures, but I guess it is hard to estimate sizes
-            // before installing the package.
-            // As a shortcut, I am assuming that the package fits on NAND flash if the available
-            // space is three times that of the APK size. For SD, we only worry about the APK size.
-            // Since packages are downloaded into SD, this might not even be necessary.
-            boolean fitsOnSD = (pkgLen < availSDSize) && ((2 * pkgLen) < availInternalFlashSize);
-            boolean fitsOnInternalFlash = ((pkgLen * 3) < availInternalFlashSize);
-
-            // Does not fit, recommend no installation.
-            if (!fitsOnSD && !fitsOnInternalFlash) {
-                return INSTALL_FAILED_INSUFFICIENT_STORAGE;
-            }
-
-            if (pkgLen < (INSTALL_ON_SD_THRESHOLD) && fitsOnInternalFlash && !(installOnlyOnSD)) {
-                // recommend internal NAND likely
-                if (pctNandFree < LOW_NAND_FLASH_TRESHOLD) {
-                    // Low space on NAND (<10%) - install on SD
-                    return INSTALL_ON_SDCARD;
-                }
-                return INSTALL_ON_INTERNAL_FLASH;
-            } else {
-                if (fitsOnSD) {
-                    // Recommend SD card
-                    return INSTALL_ON_SDCARD;
-                } else if (fitsOnInternalFlash && (pctNandFree >= LOW_NAND_FLASH_TRESHOLD) &&
-                        !(installOnlyOnSD)) {
-                    return INSTALL_ON_INTERNAL_FLASH;
-                } else {
-                    return INSTALL_FAILED_INSUFFICIENT_STORAGE;
-                }
-            }
-        }
-
         private final ContextImpl mContext;
         private final IPackageManager mPM;
 
diff --git a/core/java/android/app/DeviceAdminInfo.java b/core/java/android/app/DeviceAdminInfo.java
index ab9c44f..159fa75 100644
--- a/core/java/android/app/DeviceAdminInfo.java
+++ b/core/java/android/app/DeviceAdminInfo.java
@@ -80,23 +80,15 @@
     public static final int USES_POLICY_RESET_PASSWORD = 2;
 
     /**
-     * A type of policy that this device admin can use: able to limit the
+     * A type of policy that this device admin can use: able to force the device
+     * to lock via{@link DevicePolicyManager#lockNow} or limit the
      * maximum lock timeout for the device via
      * {@link DevicePolicyManager#setMaximumTimeToLock}.
      * 
-     * <p>To control this policy, the device admin must have a "limit-unlock"
-     * tag in the "uses-policies" section of its meta-data.
-     */
-    public static final int USES_POLICY_LIMIT_UNLOCK = 3;
-
-    /**
-     * A type of policy that this device admin can use: able to force the device
-     * to lock via{@link DevicePolicyManager#lockNow}.
-     * 
      * <p>To control this policy, the device admin must have a "force-lock"
      * tag in the "uses-policies" section of its meta-data.
      */
-    public static final int USES_POLICY_FORCE_LOCK = 4;
+    public static final int USES_POLICY_FORCE_LOCK = 3;
 
     /**
      * A type of policy that this device admin can use: able to factory
@@ -106,7 +98,7 @@
      * <p>To control this policy, the device admin must have a "wipe-data"
      * tag in the "uses-policies" section of its meta-data.
      */
-    public static final int USES_POLICY_WIPE_DATA = 5;
+    public static final int USES_POLICY_WIPE_DATA = 4;
 
     /** @hide */
     public static class PolicyInfo {
@@ -140,9 +132,6 @@
         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_WATCH_LOGIN, "watch-login",
                 com.android.internal.R.string.policylab_watchLogin,
                 com.android.internal.R.string.policydesc_watchLogin));
-        sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_LIMIT_UNLOCK, "limit-unlock",
-                com.android.internal.R.string.policylab_limitUnlock,
-                com.android.internal.R.string.policydesc_limitUnlock));
         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_FORCE_LOCK, "force-lock",
                 com.android.internal.R.string.policylab_forceLock,
                 com.android.internal.R.string.policydesc_forceLock));
@@ -314,8 +303,8 @@
      * Return true if the device admin has requested that it be able to use
      * the given policy control.  The possible policy identifier inputs are:
      * {@link #USES_POLICY_LIMIT_PASSWORD}, {@link #USES_POLICY_WATCH_LOGIN},
-     * {@link #USES_POLICY_RESET_PASSWORD}, {@link #USES_POLICY_LIMIT_UNLOCK},
-     * {@link #USES_POLICY_FORCE_LOCK}, {@link #USES_POLICY_WIPE_DATA}.
+     * {@link #USES_POLICY_RESET_PASSWORD}, {@link #USES_POLICY_FORCE_LOCK},
+     * {@link #USES_POLICY_WIPE_DATA}.
      */
     public boolean usesPolicy(int policyIdent) {
         return (mUsesPolicies & (1<<policyIdent)) != 0;
diff --git a/core/java/android/app/DevicePolicyManager.java b/core/java/android/app/DevicePolicyManager.java
index 847e879..82c43dc 100644
--- a/core/java/android/app/DevicePolicyManager.java
+++ b/core/java/android/app/DevicePolicyManager.java
@@ -410,7 +410,7 @@
      * the length that the user can set.  It takes effect immediately.
      * 
      * <p>The calling device admin must have requested
-     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_UNLOCK} to be able to call
+     * {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} to be able to call
      * this method; if it has not, a security exception will be thrown.
      * 
      * @param admin Which {@link DeviceAdmin} this request is associated with.
diff --git a/core/java/android/app/IUiModeManager.aidl b/core/java/android/app/IUiModeManager.aidl
new file mode 100644
index 0000000..6ac8a2a
--- /dev/null
+++ b/core/java/android/app/IUiModeManager.aidl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+/**
+ * Interface used to control special UI modes.
+ * @hide
+ */
+interface IUiModeManager {
+    /**
+     * Enables the car mode. Only the system can do this.
+     * @hide
+     */
+    void enableCarMode();
+
+    /**
+     * Disables the car mode.
+     */
+    void disableCarMode();
+
+    /**
+     * Sets the night mode.
+     * The mode can be one of:
+     *   1 - notnight mode
+     *   2 - night mode
+     *   3 - automatic mode switching
+     */
+    void setNightMode(int mode);
+
+    /**
+     * Gets the currently configured night mode.  Return 1 for notnight,
+     * 2 for night, and 3 for automatic mode switching.
+     */
+    int getNightMode();
+}
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 7fa5b08..63e95c0 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -761,12 +761,6 @@
             return false;
         }
 
-        if (keyCode == KeyEvent.KEYCODE_SEARCH && event.getRepeatCount() == 0) {
-            event.startTracking();
-            // Consume search key for later use.
-            return true;
-        }
-
         // if it's an action specified by the searchable activity, launch the
         // entered query with the action key
         SearchableInfo.ActionKeyInfo actionKey = mSearchable.findActionKey(keyCode);
@@ -778,24 +772,6 @@
         return super.onKeyDown(keyCode, event);
     }
     
-    @Override
-    public boolean onKeyUp(int keyCode, KeyEvent event) {
-        if (DBG) Log.d(LOG_TAG, "onKeyUp(" + keyCode + "," + event + ")");
-        if (mSearchable == null) {
-            return false;
-        }
-
-        if (keyCode == KeyEvent.KEYCODE_SEARCH && event.isTracking()
-                && !event.isCanceled()) {
-            // If the search key is pressed, toggle between global and in-app search. If we are
-            // currently doing global search and there is no in-app search context to toggle to,
-            // just don't do anything.
-            return toggleGlobalSearch();
-        }
-
-        return super.onKeyUp(keyCode, event);
-    }
-    
     /**
      * Callback to watch the textedit field for empty/non-empty
      */
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 3046a2c..5a9a675 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -1279,16 +1279,6 @@
     public final static String APP_DATA = "app_data";
 
     /**
-     * Intent app_data bundle key: Use this key with the bundle from
-     * {@link android.content.Intent#getBundleExtra
-     * content.Intent.getBundleExtra(APP_DATA)} to obtain the source identifier
-     * set by the activity that launched the search.
-     *
-     * @hide
-     */
-    public final static String SOURCE = "source";
-
-    /**
      * Intent extra data key: Use {@link android.content.Intent#getBundleExtra
      * content.Intent.getBundleExtra(SEARCH_MODE)} to get the search mode used
      * to launch the intent.
@@ -1638,8 +1628,6 @@
     /**
      * Intent action for starting the global search settings activity.
      * The global search provider should handle this intent.
-     * 
-     * @hide Pending API council approval.
      */
     public final static String INTENT_ACTION_SEARCH_SETTINGS 
             = "android.search.action.SEARCH_SETTINGS";
diff --git a/core/java/android/app/SearchableInfo.java b/core/java/android/app/SearchableInfo.java
index 9897742..4496354 100644
--- a/core/java/android/app/SearchableInfo.java
+++ b/core/java/android/app/SearchableInfo.java
@@ -73,7 +73,7 @@
     private final boolean mIncludeInGlobalSearch;
     private final boolean mQueryAfterZeroResults;
     private final boolean mAutoUrlDetect;
-    private final String mSettingsDescription;
+    private final int mSettingsDescriptionId;
     private final String mSuggestAuthority;
     private final String mSuggestPath;
     private final String mSuggestSelection;
@@ -155,11 +155,11 @@
     }
     
     /**
-     * Gets the description to use for this source in system search settings, or null if
-     * none has been specified.
+     * Gets the resource ID of the description string to use for this source in system search
+     * settings, or {@code 0} if none has been specified.
      */
-    public String getSettingsDescription() {
-        return mSettingsDescription;
+    public int getSettingsDescriptionId() {
+        return mSettingsDescriptionId;
     }
 
     /**
@@ -311,8 +311,8 @@
         mAutoUrlDetect = a.getBoolean(
                 com.android.internal.R.styleable.Searchable_autoUrlDetect, false);
 
-        mSettingsDescription = a.getString(
-                com.android.internal.R.styleable.Searchable_searchSettingsDescription);
+        mSettingsDescriptionId = a.getResourceId(
+                com.android.internal.R.styleable.Searchable_searchSettingsDescription, 0);
         mSuggestAuthority = a.getString(
                 com.android.internal.R.styleable.Searchable_searchSuggestAuthority);
         mSuggestPath = a.getString(
@@ -495,7 +495,7 @@
                         + ",suggestAuthority=" + searchable.getSuggestAuthority()
                         + ",target=" + searchable.getSearchActivity().getClassName()
                         + ",global=" + searchable.shouldIncludeInGlobalSearch()
-                        + ",settingsDescription=" + searchable.getSettingsDescription()
+                        + ",settingsDescription=" + searchable.getSettingsDescriptionId()
                         + ",threshold=" + searchable.getSuggestThreshold());
             } else {
                 Log.d(LOG_TAG, "Checked " + activityInfo.name + ", no searchable meta-data");
@@ -746,7 +746,7 @@
         mQueryAfterZeroResults = in.readInt() != 0;
         mAutoUrlDetect = in.readInt() != 0;
         
-        mSettingsDescription = in.readString();
+        mSettingsDescriptionId = in.readInt();
         mSuggestAuthority = in.readString();
         mSuggestPath = in.readString();
         mSuggestSelection = in.readString();
@@ -784,7 +784,7 @@
         dest.writeInt(mQueryAfterZeroResults ? 1 : 0);
         dest.writeInt(mAutoUrlDetect ? 1 : 0);
         
-        dest.writeString(mSettingsDescription);
+        dest.writeInt(mSettingsDescriptionId);
         dest.writeString(mSuggestAuthority);
         dest.writeString(mSuggestPath);
         dest.writeString(mSuggestSelection);
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index b33be23..45f361e 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -16,6 +16,8 @@
 
 package android.content;
 
+import android.accounts.Account;
+import android.app.ActivityThread;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources;
@@ -29,9 +31,10 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemClock;
 import android.text.TextUtils;
-import android.accounts.Account;
 import android.util.Config;
+import android.util.EventLog;
 import android.util.Log;
 
 import java.io.File;
@@ -41,6 +44,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.List;
+import java.util.Random;
 import java.util.ArrayList;
 
 
@@ -163,6 +167,11 @@
     /** @hide */
     public static final int SYNC_OBSERVER_TYPE_ALL = 0x7fffffff;
 
+    // Always log queries which take 100ms+; shorter queries are
+    // sampled accordingly.
+    private static final int SLOW_THRESHOLD_MILLIS = 100;
+    private final Random mRandom = new Random();  // guarded by itself
+
     public ContentResolver(Context context) {
         mContext = context;
     }
@@ -235,12 +244,15 @@
             return null;
         }
         try {
+            long startTime = SystemClock.uptimeMillis();
             Cursor qCursor = provider.query(uri, projection, selection, selectionArgs, sortOrder);
-            if(qCursor == null) {
+            if (qCursor == null) {
                 releaseProvider(provider);
                 return null;
             }
-            //Wrap the cursor object into CursorWrapperInner object
+            long durationMillis = SystemClock.uptimeMillis() - startTime;
+            maybeLogQueryToEventLog(durationMillis, uri, projection, selection, sortOrder);
+            // Wrap the cursor object into CursorWrapperInner object
             return new CursorWrapperInner(qCursor, provider);
         } catch (RemoteException e) {
             releaseProvider(provider);
@@ -572,7 +584,11 @@
             throw new IllegalArgumentException("Unknown URL " + url);
         }
         try {
-            return provider.insert(url, values);
+            long startTime = SystemClock.uptimeMillis();
+            Uri createdRow = provider.insert(url, values);
+            long durationMillis = SystemClock.uptimeMillis() - startTime;
+            maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */);
+            return createdRow;
         } catch (RemoteException e) {
             return null;
         } finally {
@@ -627,7 +643,11 @@
             throw new IllegalArgumentException("Unknown URL " + url);
         }
         try {
-            return provider.bulkInsert(url, values);
+            long startTime = SystemClock.uptimeMillis();
+            int rowsCreated = provider.bulkInsert(url, values);
+            long durationMillis = SystemClock.uptimeMillis() - startTime;
+            maybeLogUpdateToEventLog(durationMillis, url, "bulkinsert", null /* where */);
+            return rowsCreated;
         } catch (RemoteException e) {
             return 0;
         } finally {
@@ -652,7 +672,11 @@
             throw new IllegalArgumentException("Unknown URL " + url);
         }
         try {
-            return provider.delete(url, where, selectionArgs);
+            long startTime = SystemClock.uptimeMillis();
+            int rowsDeleted = provider.delete(url, where, selectionArgs);
+            long durationMillis = SystemClock.uptimeMillis() - startTime;
+            maybeLogUpdateToEventLog(durationMillis, url, "delete", where);
+            return rowsDeleted;
         } catch (RemoteException e) {
             return -1;
         } finally {
@@ -680,7 +704,11 @@
             throw new IllegalArgumentException("Unknown URI " + uri);
         }
         try {
-            return provider.update(uri, values, where, selectionArgs);
+            long startTime = SystemClock.uptimeMillis();
+            int rowsUpdated = provider.update(uri, values, where, selectionArgs);
+            long durationMillis = SystemClock.uptimeMillis() - startTime;
+            maybeLogUpdateToEventLog(durationMillis, uri, "update", where);
+            return rowsUpdated;
         } catch (RemoteException e) {
             return -1;
         } finally {
@@ -1217,6 +1245,78 @@
         }
     }
 
+    /**
+     * Returns sampling percentage for a given duration.
+     *
+     * Always returns at least 1%.
+     */
+    private int samplePercentForDuration(long durationMillis) {
+        if (durationMillis >= SLOW_THRESHOLD_MILLIS) {
+            return 100;
+        }
+        return (int) (100 * durationMillis / SLOW_THRESHOLD_MILLIS) + 1;
+    }
+
+    private void maybeLogQueryToEventLog(long durationMillis,
+                                         Uri uri, String[] projection,
+                                         String selection, String sortOrder) {
+        int samplePercent = samplePercentForDuration(durationMillis);
+        if (samplePercent < 100) {
+            synchronized (mRandom) {
+                if (mRandom.nextInt(100) >= samplePercent) {
+                    return;
+                }
+            }
+        }
+
+        StringBuilder projectionBuffer = new StringBuilder(100);
+        if (projection != null) {
+            for (int i = 0; i < projection.length; ++i) {
+                // Note: not using a comma delimiter here, as the
+                // multiple arguments to EventLog.writeEvent later
+                // stringify with a comma delimiter, which would make
+                // parsing uglier later.
+                if (i != 0) projectionBuffer.append('/');
+                projectionBuffer.append(projection[i]);
+            }
+        }
+
+        // ActivityThread.currentPackageName() only returns non-null if the
+        // current thread is an application main thread.  This parameter tells
+        // us whether an event loop is blocked, and if so, which app it is.
+        String blockingPackage = ActivityThread.currentPackageName();
+
+        EventLog.writeEvent(
+            EventLogTags.CONTENT_QUERY_OPERATION,
+            uri.toString(),
+            projectionBuffer.toString(),
+            selection != null ? selection : "",
+            sortOrder != null ? sortOrder : "",
+            durationMillis,
+            blockingPackage != null ? blockingPackage : "",
+            samplePercent);
+    }
+
+    private void maybeLogUpdateToEventLog(
+        long durationMillis, Uri uri, String operation, String selection) {
+        int samplePercent = samplePercentForDuration(durationMillis);
+        if (samplePercent < 100) {
+            synchronized (mRandom) {
+                if (mRandom.nextInt(100) >= samplePercent) {
+                    return;
+                }
+            }
+        }
+        String blockingPackage = ActivityThread.currentPackageName();
+        EventLog.writeEvent(
+            EventLogTags.CONTENT_UPDATE_OPERATION,
+            uri.toString(),
+            operation,
+            selection != null ? selection : "",
+            durationMillis,
+            blockingPackage != null ? blockingPackage : "",
+            samplePercent);
+    }
 
     private final class CursorWrapperInner extends CursorWrapper {
         private IContentProvider mContentProvider;
diff --git a/core/java/android/content/EventLogTags.logtags b/core/java/android/content/EventLogTags.logtags
new file mode 100644
index 0000000..a815b95
--- /dev/null
+++ b/core/java/android/content/EventLogTags.logtags
@@ -0,0 +1,6 @@
+# See system/core/logcat/event.logtags for a description of the format of this file.
+
+option java_package android.content;
+
+52002 content_query_operation (uri|3),(projection|3),(selection|3),(sortorder|3),(time|1|3),(blocking_package|3),(sample_percent|1|6)
+52003 content_update_operation (uri|3),(operation|3),(selection|3),(time|1|3),(blocking_package|3),(sample_percent|1|6)
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index c32999f..e36eba9 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1816,7 +1816,9 @@
     /**
      * Broadcast Action:  A sticky broadcast indicating the phone was docked
      * or undocked.  Includes the extra
-     * field {@link #EXTRA_DOCK_STATE}, containing the current dock state.
+     * field {@link #EXTRA_DOCK_STATE}, containing the current dock state. It also
+     * includes the boolean extra field {@link #EXTRA_CAR_MODE_ENABLED}, indicating
+     * the state of the car mode.
      * This is intended for monitoring the current dock state.
      * To launch an activity from a dock state change, use {@link #CATEGORY_CAR_DOCK}
      * or {@link #CATEGORY_DESK_DOCK} instead.
@@ -2152,6 +2154,12 @@
     public static final int EXTRA_DOCK_STATE_CAR = 2;
 
     /**
+     * Used as an boolean extra field in {@link android.content.Intent#ACTION_DOCK_EVENT}
+     * intents to indicate that the car mode is enabled or not.
+     */
+    public static final String EXTRA_CAR_MODE_ENABLED = "android.intent.extra.CAR_MODE_ENABLED";
+
+    /**
      * Boolean that can be supplied as meta-data with a dock activity, to
      * indicate that the dock should take over the home key when it is active.
      */
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index ebb95e87..9ff2e25 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -1041,7 +1041,7 @@
                     continue;
                 }
 
-                SyncStorageEngine.AuthorityInfo settings = mSyncStorageEngine.getAuthority(
+                SyncStorageEngine.AuthorityInfo settings = mSyncStorageEngine.getOrCreateAuthority(
                         account, syncAdapterType.type.authority);
                 SyncStatusInfo status = mSyncStorageEngine.getOrCreateSyncStatus(settings);
                 pw.print("    "); pw.print(settings.authority);
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index 07a1f46..fcb910d 100644
--- a/core/java/android/content/SyncStorageEngine.java
+++ b/core/java/android/content/SyncStorageEngine.java
@@ -632,9 +632,11 @@
         }
     }
 
-    public AuthorityInfo getAuthority(Account account, String authority) {
+    public AuthorityInfo getOrCreateAuthority(Account account, String authority) {
         synchronized (mAuthorities) {
-            return getAuthorityLocked(account, authority, null);
+            return getOrCreateAuthorityLocked(account, authority,
+                    -1 /* assign a new identifier if creating a new authority */,
+                    true /* write to storage if this results in a change */);
         }
     }
 
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index b94bb51..a13f7f9 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -251,6 +251,13 @@
     public static final int CONFIG_SCREEN_LAYOUT = 0x0100;
     /**
      * Bit in {@link #configChanges} that indicates that the activity
+     * can itself handle the ui mode. Set from the
+     * {@link android.R.attr#configChanges} attribute.
+     * @hide (UIMODE) Pending API council approval
+     */
+    public static final int CONFIG_UI_MODE = 0x0200;
+    /**
+     * Bit in {@link #configChanges} that indicates that the activity
      * can itself handle changes to the font scaling factor.  Set from the
      * {@link android.R.attr#configChanges} attribute.  This is
      * not a core resource configutation, but a higher-level value, so its
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 6591313..123d9b7 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -178,12 +178,20 @@
     public static final int FLAG_SUPPORTS_SCREEN_DENSITIES = 1<<13;
     
     /**
+     * Value for {@link #flags}: set to true if this application would like to
+     * request the VM to operate under the safe mode. Comes from
+     * {@link android.R.styleable#AndroidManifestApplication_safeMode
+     * android:safeMode} of the &lt;application&gt; tag.
+     */
+    public static final int FLAG_VM_SAFE_MODE = 1<<14;
+
+    /**
      * Value for {@link #flags}: this is false if the application has set
      * its android:allowBackup to false, true otherwise.
      * 
      * {@hide}
      */
-    public static final int FLAG_ALLOW_BACKUP = 1<<14;
+    public static final int FLAG_ALLOW_BACKUP = 1<<15;
 
     /**
      * Value for {@link #flags}: this is false if the application has set
@@ -194,7 +202,7 @@
      *
      * {@hide}
      */
-    public static final int FLAG_KILL_AFTER_RESTORE = 1<<15;
+    public static final int FLAG_KILL_AFTER_RESTORE = 1<<16;
 
     /**
      * Value for {@link #flags}: this is true if the application has set
@@ -205,7 +213,7 @@
      *
      * {@hide}
      */
-    public static final int FLAG_RESTORE_NEEDS_APPLICATION = 1<<16;
+    public static final int FLAG_RESTORE_NEEDS_APPLICATION = 1<<17;
 
     /**
      * Value for {@link #flags}: this is true if the application has set
@@ -215,7 +223,7 @@
      *
      * {@hide}
      */
-    public static final int FLAG_NEVER_ENCRYPT = 1<<17;
+    public static final int FLAG_NEVER_ENCRYPT = 1<<18;
 
     /**
      * Value for {@link #flags}: Set to true if the application has been
@@ -223,7 +231,7 @@
      *
      * {@hide}
      */
-    public static final int FLAG_FORWARD_LOCK = 1<<18;
+    public static final int FLAG_FORWARD_LOCK = 1<<19;
 
     /**
      * Value for {@link #flags}: Set to true if the application is
@@ -231,7 +239,7 @@
      *
      * {@hide}
      */
-    public static final int FLAG_ON_SDCARD = 1<<19;
+    public static final int FLAG_ON_SDCARD = 1<<20;
 
     /**
      * Value for {@link #flags}: Set to true if the application is
@@ -239,7 +247,7 @@
      *
      * {@hide}
      */
-    public static final int FLAG_NATIVE_DEBUGGABLE = 1<<20;
+    public static final int FLAG_NATIVE_DEBUGGABLE = 1<<21;
 
     /**
      * Flags associated with the application.  Any combination of
@@ -250,7 +258,7 @@
      * {@link #FLAG_TEST_ONLY}, {@link #FLAG_SUPPORTS_SMALL_SCREENS},
      * {@link #FLAG_SUPPORTS_NORMAL_SCREENS},
      * {@link #FLAG_SUPPORTS_LARGE_SCREENS}, {@link #FLAG_RESIZEABLE_FOR_SCREENS},
-     * {@link #FLAG_SUPPORTS_SCREEN_DENSITIES}
+     * {@link #FLAG_SUPPORTS_SCREEN_DENSITIES}, {@link #FLAG_VM_SAFE_MODE}
      */
     public int flags = 0;
     
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 2c8c112..47789a5 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -47,6 +47,9 @@
     PackageInfo getPackageInfo(String packageName, int flags);
     int getPackageUid(String packageName);
     int[] getPackageGids(String packageName);
+    
+    String[] currentToCanonicalPackageNames(in String[] names);
+    String[] canonicalToCurrentPackageNames(in String[] names);
 
     PermissionInfo getPermissionInfo(String name, int flags);
     
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index a8ce889..c003355 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -131,6 +131,34 @@
      * The features that this application has said it requires.
      */
     public FeatureInfo[] reqFeatures;
+
+    /**
+     * Constant corresponding to <code>auto</code> in
+     * the {@link android.R.attr#installLocation} attribute.
+     * @hide
+     */
+    public static final int INSTALL_LOCATION_AUTO = 0;
+    /**
+     * Constant corresponding to <code>internalOnly</code> in
+     * the {@link android.R.attr#installLocation} attribute.
+     * @hide
+     */
+    public static final int INSTALL_LOCATION_INTERNAL_ONLY = 1;
+    /**
+     * Constant corresponding to <code>preferExternal</code> in
+     * the {@link android.R.attr#installLocation} attribute.
+     * @hide
+     */
+    public static final int INSTALL_LOCATION_PREFER_EXTERNAL = 2;
+    /**
+     * The launch mode style requested by the activity.  From the
+     * {@link android.R.attr#installLocation} attribute, one of
+     * {@link #INSTALL_LOCATION_AUTO},
+     * {@link #INSTALL_LOCATION_INTERNAL_ONLY},
+     * {@link #INSTALL_LOCATION_PREFER_EXTERNAL}
+     * @hide
+     */
+    public int installLocation = INSTALL_LOCATION_INTERNAL_ONLY;
     
     public PackageInfo() {
     }
@@ -168,6 +196,7 @@
         dest.writeTypedArray(signatures, parcelableFlags);
         dest.writeTypedArray(configPreferences, parcelableFlags);
         dest.writeTypedArray(reqFeatures, parcelableFlags);
+        dest.writeInt(installLocation);
     }
 
     public static final Parcelable.Creator<PackageInfo> CREATOR
@@ -202,5 +231,6 @@
         signatures = source.createTypedArray(Signature.CREATOR);
         configPreferences = source.createTypedArray(ConfigurationInfo.CREATOR);
         reqFeatures = source.createTypedArray(FeatureInfo.CREATOR);
+        installLocation = source.readInt();
     }
 }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index fca8588..ff2ed3d 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -258,14 +258,7 @@
      * package has to be installed on the sdcard.
      * @hide
      */
-    public static final int INSTALL_ON_SDCARD = 0x00000008;
-
-    /**
-     * Convenience flag parameter to indicate that this package has to be installed
-     * on internal flash.
-     * @hide
-     */
-    public static final int INSTALL_ON_INTERNAL_FLASH = 0x00000000;
+    public static final int INSTALL_EXTERNAL = 0x00000008;
 
     /**
      * Flag parameter for
@@ -529,6 +522,14 @@
     public static final int INSTALL_PARSE_FAILED_MANIFEST_EMPTY = -109;
 
     /**
+     * Installation failed return code: this is passed to the {@link IPackageInstallObserver} by
+     * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
+     * if the system failed to install the package because of system issues.
+     * @hide
+     */
+    public static final int INSTALL_FAILED_INTERNAL_ERROR = -110;
+
+    /**
      * Indicates the state of installation. Used by PackageManager to
      * figure out incomplete installations. Say a package is being installed
      * (the state is set to PKG_INSTALL_INCOMPLETE) and remains so till
@@ -627,22 +628,6 @@
      */
     public static final String ACTION_CLEAN_EXTERNAL_STORAGE
             = "android.content.pm.CLEAN_EXTERNAL_STORAGE";
-    
-    /**
-     * Determines best place to install an application: either SD or internal FLASH.
-     * Tweak the algorithm for best results.
-     * @param appInfo ApplicationInfo object of the package to install.
-     * Call utility method to obtain.
-     * @param packageURI URI identifying the package's APK file.
-     * @return {@link INSTALL_ON_INTERNAL_FLASH} if it is best to install package on internal
-     * storage, {@link INSTALL_ON_SDCARD} if it is best to install package on SD card,
-     * and {@link INSTALL_FAILED_INSUFFICIENT_STORAGE} if insufficient space to safely install
-     * the application. {@link INSTALL_PARSE_FAILED_NOT_APK} Is returned if any input
-     * parameter is <code>null</code>.
-     * This recommendation does take into account the package's own flags.
-     * @hide
-     */
-    public abstract int recommendAppInstallLocation(ApplicationInfo appInfo, Uri packageURI);
 
     /**
      * Retrieve overall information about an application package that is
@@ -690,6 +675,23 @@
             throws NameNotFoundException;
 
     /**
+     * Map from the current package names in use on the device to whatever
+     * the current canonical name of that package is.
+     * @param names Array of current names to be mapped.
+     * @return Returns an array of the same size as the original, containing
+     * the canonical name for each package.
+     */
+    public abstract String[] currentToCanonicalPackageNames(String[] names);
+    
+    /**
+     * Map from a packages canonical name to the current name in use on the device.
+     * @param names Array of new names to be mapped.
+     * @return Returns an array of the same size as the original, containing
+     * the current name for each package.
+     */
+    public abstract String[] canonicalToCurrentPackageNames(String[] names);
+    
+    /**
      * Return a "good" intent to launch a front-door activity in a package,
      * for use for example to implement an "open" button when browsing through
      * packages.  The current implementation will look first for a main
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index b31df32..5823560 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -177,6 +177,7 @@
         pi.sharedUserId = p.mSharedUserId;
         pi.sharedUserLabel = p.mSharedUserLabel;
         pi.applicationInfo = p.applicationInfo;
+        pi.installLocation = p.installLocation;
         if ((flags&PackageManager.GET_GIDS) != 0) {
             pi.gids = gids;
         }
@@ -709,6 +710,9 @@
                     com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
         }
         sa.recycle();
+        pkg.installLocation = sa.getInteger(
+                com.android.internal.R.styleable.AndroidManifest_installLocation,
+                PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
 
         // Resource boolean are -1, so 1 means we don't know the value.
         int supportsSmallScreens = 1;
@@ -957,15 +961,15 @@
                 sa = res.obtainAttributes(attrs,
                         com.android.internal.R.styleable.AndroidManifestOriginalPackage);
 
-                String name = sa.getNonResourceString(
+                String orig =sa.getNonResourceString(
                         com.android.internal.R.styleable.AndroidManifestOriginalPackage_name);
+                if (!pkg.packageName.equals(orig)) {
+                    pkg.mOriginalPackage = orig;
+                    pkg.mRealPackage = pkg.packageName;
+                }
 
                 sa.recycle();
 
-                if (name != null && (flags&PARSE_IS_SYSTEM) != 0) {
-                    pkg.mOriginalPackage = name;
-                }
-
                 XmlUtils.skipCurrentTag(parser);
                 
             } else if (tagName.equals("adopt-permissions")) {
@@ -977,7 +981,7 @@
 
                 sa.recycle();
 
-                if (name != null && (flags&PARSE_IS_SYSTEM) != 0) {
+                if (name != null) {
                     if (pkg.mAdoptPermissions == null) {
                         pkg.mAdoptPermissions = new ArrayList<String>();
                     }
@@ -1425,6 +1429,12 @@
         }
 
         if (sa.getBoolean(
+                com.android.internal.R.styleable.AndroidManifestApplication_safeMode,
+                false)) {
+            ai.flags |= ApplicationInfo.FLAG_VM_SAFE_MODE;
+        }
+
+        if (sa.getBoolean(
                 com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
                 true)) {
             ai.flags |= ApplicationInfo.FLAG_HAS_CODE;
@@ -2540,7 +2550,7 @@
     }
 
     public final static class Package {
-        public final String packageName;
+        public String packageName;
 
         // For now we only support one application per package.
         public final ApplicationInfo applicationInfo = new ApplicationInfo();
@@ -2562,6 +2572,7 @@
         public String[] usesLibraryFiles = null;
 
         public String mOriginalPackage = null;
+        public String mRealPackage = null;
         public ArrayList<String> mAdoptPermissions = null;
         
         // We store the application meta-data independently to avoid multiple unwanted references
@@ -2610,12 +2621,40 @@
          */
         public ArrayList<FeatureInfo> reqFeatures = null;
 
+        public int installLocation;
+
         public Package(String _name) {
             packageName = _name;
             applicationInfo.packageName = _name;
             applicationInfo.uid = -1;
         }
 
+        public void setPackageName(String newName) {
+            packageName = newName;
+            applicationInfo.packageName = newName;
+            for (int i=permissions.size()-1; i>=0; i--) {
+                permissions.get(i).setPackageName(newName);
+            }
+            for (int i=permissionGroups.size()-1; i>=0; i--) {
+                permissionGroups.get(i).setPackageName(newName);
+            }
+            for (int i=activities.size()-1; i>=0; i--) {
+                activities.get(i).setPackageName(newName);
+            }
+            for (int i=receivers.size()-1; i>=0; i--) {
+                receivers.get(i).setPackageName(newName);
+            }
+            for (int i=providers.size()-1; i>=0; i--) {
+                providers.get(i).setPackageName(newName);
+            }
+            for (int i=services.size()-1; i>=0; i--) {
+                services.get(i).setPackageName(newName);
+            }
+            for (int i=instrumentation.size()-1; i>=0; i--) {
+                instrumentation.get(i).setPackageName(newName);
+            }
+        }
+        
         public String toString() {
             return "Package{"
                 + Integer.toHexString(System.identityHashCode(this))
@@ -2626,15 +2665,16 @@
     public static class Component<II extends IntentInfo> {
         public final Package owner;
         public final ArrayList<II> intents;
-        public final ComponentName component;
-        public final String componentShortName;
+        public final String className;
         public Bundle metaData;
 
+        ComponentName componentName;
+        String componentShortName;
+        
         public Component(Package _owner) {
             owner = _owner;
             intents = null;
-            component = null;
-            componentShortName = null;
+            className = null;
         }
 
         public Component(final ParsePackageItemArgs args, final PackageItemInfo outInfo) {
@@ -2642,8 +2682,7 @@
             intents = new ArrayList<II>(0);
             String name = args.sa.getNonResourceString(args.nameRes);
             if (name == null) {
-                component = null;
-                componentShortName = null;
+                className = null;
                 args.outError[0] = args.tag + " does not specify android:name";
                 return;
             }
@@ -2651,15 +2690,12 @@
             outInfo.name
                 = buildClassName(owner.applicationInfo.packageName, name, args.outError);
             if (outInfo.name == null) {
-                component = null;
-                componentShortName = null;
+                className = null;
                 args.outError[0] = args.tag + " does not have valid android:name";
                 return;
             }
 
-            component = new ComponentName(owner.applicationInfo.packageName,
-                    outInfo.name);
-            componentShortName = component.flattenToShortString();
+            className = outInfo.name;
 
             int iconVal = args.sa.getResourceId(args.iconRes, 0);
             if (iconVal != 0) {
@@ -2697,9 +2733,36 @@
         public Component(Component<II> clone) {
             owner = clone.owner;
             intents = clone.intents;
-            component = clone.component;
+            className = clone.className;
+            componentName = clone.componentName;
             componentShortName = clone.componentShortName;
-            metaData = clone.metaData;
+        }
+        
+        public ComponentName getComponentName() {
+            if (componentName != null) {
+                return componentName;
+            }
+            if (className != null) {
+                componentName = new ComponentName(owner.applicationInfo.packageName,
+                        className);
+            }
+            return componentName;
+        }
+        
+        public String getComponentShortName() {
+            if (componentShortName != null) {
+                return componentShortName;
+            }
+            ComponentName component = getComponentName();
+            if (component != null) {
+                componentShortName = component.flattenToShortString();
+            }
+            return componentShortName;
+        }
+        
+        public void setPackageName(String packageName) {
+            componentName = null;
+            componentShortName = null;
         }
     }
     
@@ -2717,6 +2780,11 @@
             super(_owner);
             info = _info;
         }
+        
+        public void setPackageName(String packageName) {
+            super.setPackageName(packageName);
+            info.packageName = packageName;
+        }
 
         public String toString() {
             return "Permission{"
@@ -2738,6 +2806,11 @@
             info = _info;
         }
 
+        public void setPackageName(String packageName) {
+            super.setPackageName(packageName);
+            info.packageName = packageName;
+        }
+
         public String toString() {
             return "PermissionGroup{"
                 + Integer.toHexString(System.identityHashCode(this))
@@ -2813,10 +2886,15 @@
             info.applicationInfo = args.owner.applicationInfo;
         }
         
+        public void setPackageName(String packageName) {
+            super.setPackageName(packageName);
+            info.packageName = packageName;
+        }
+
         public String toString() {
             return "Activity{"
                 + Integer.toHexString(System.identityHashCode(this))
-                + " " + component.flattenToString() + "}";
+                + " " + getComponentShortName() + "}";
         }
     }
 
@@ -2842,10 +2920,15 @@
             info.applicationInfo = args.owner.applicationInfo;
         }
         
+        public void setPackageName(String packageName) {
+            super.setPackageName(packageName);
+            info.packageName = packageName;
+        }
+
         public String toString() {
             return "Service{"
                 + Integer.toHexString(System.identityHashCode(this))
-                + " " + component.flattenToString() + "}";
+                + " " + getComponentShortName() + "}";
         }
     }
 
@@ -2878,6 +2961,11 @@
             this.syncable = existingProvider.syncable;
         }
 
+        public void setPackageName(String packageName) {
+            super.setPackageName(packageName);
+            info.packageName = packageName;
+        }
+
         public String toString() {
             return "Provider{"
                 + Integer.toHexString(System.identityHashCode(this))
@@ -2911,10 +2999,15 @@
             info = _info;
         }
         
+        public void setPackageName(String packageName) {
+            super.setPackageName(packageName);
+            info.packageName = packageName;
+        }
+
         public String toString() {
             return "Instrumentation{"
                 + Integer.toHexString(System.identityHashCode(this))
-                + " " + component.flattenToString() + "}";
+                + " " + getComponentShortName() + "}";
         }
     }
 
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 23a408b..7f9a5c6 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -619,7 +619,7 @@
     public native final void setConfiguration(int mcc, int mnc, String locale,
             int orientation, int touchscreen, int density, int keyboard,
             int keyboardHidden, int navigation, int screenWidth, int screenHeight,
-            int screenLayout, int majorVersion);
+            int screenLayout, int uiMode, int majorVersion);
 
     /**
      * Retrieve the resource identifier for the given resource name.
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 1fe34b5..aa5f128 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -161,7 +161,37 @@
      * or {@link #ORIENTATION_SQUARE}.
      */
     public int orientation;
-    
+
+    /** @hide (UIMODE) Pending API council approval */
+    public static final int UI_MODE_TYPE_MASK = 0x0f;
+    /** @hide (UIMODE) Pending API council approval */
+    public static final int UI_MODE_TYPE_NORMAL = 0x00;
+    /** @hide (UIMODE) Pending API council approval */
+    public static final int UI_MODE_TYPE_CAR = 0x01;
+
+    /** @hide (UIMODE) Pending API council approval */
+    public static final int UI_MODE_NIGHT_MASK = 0x30;
+    /** @hide (UIMODE) Pending API council approval */
+    public static final int UI_MODE_NIGHT_UNDEFINED = 0x00;
+    /** @hide (UIMODE) Pending API council approval */
+    public static final int UI_MODE_NIGHT_NO = 0x10;
+    /** @hide (UIMODE) Pending API council approval */
+    public static final int UI_MODE_NIGHT_YES = 0x20;
+
+    /**
+     * Bit mask of the ui mode.  Currently there are two fields:
+     * <p>The {@link #UI_MODE_TYPE_MASK} bits define the overall ui mode of the
+     * device. They may be one of
+     * {@link #UI_MODE_TYPE_NORMAL} or {@link #UI_MODE_TYPE_CAR}.
+     *
+     * <p>The {@link #UI_MODE_NIGHT_MASK} defines whether the screen
+     * is in a special mode. They may be one of
+     * {@link #UI_MODE_NIGHT_NO} or {@link #UI_MODE_NIGHT_YES}.
+     *
+     * @hide (UIMODE) Pending API council approval
+     */
+    public int uiMode;
+
     /**
      * Construct an invalid Configuration.  You must call {@link #setToDefaults}
      * for this object to be valid.  {@more}
@@ -189,6 +219,7 @@
         navigationHidden = o.navigationHidden;
         orientation = o.orientation;
         screenLayout = o.screenLayout;
+        uiMode = o.uiMode;
     }
 
     public String toString() {
@@ -217,6 +248,8 @@
         sb.append(orientation);
         sb.append(" layout=");
         sb.append(screenLayout);
+        sb.append(" uiMode=");
+        sb.append(uiMode);
         sb.append('}');
         return sb.toString();
     }
@@ -237,6 +270,7 @@
         navigationHidden = NAVIGATIONHIDDEN_UNDEFINED;
         orientation = ORIENTATION_UNDEFINED;
         screenLayout = SCREENLAYOUT_SIZE_UNDEFINED;
+        uiMode = UI_MODE_TYPE_NORMAL;
     }
 
     /** {@hide} */
@@ -317,6 +351,11 @@
             changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
             screenLayout = delta.screenLayout;
         }
+        if (delta.uiMode != UI_MODE_TYPE_NORMAL
+                && uiMode != delta.uiMode) {
+            changed |= ActivityInfo.CONFIG_UI_MODE;
+            uiMode = delta.uiMode;
+        }
         
         return changed;
     }
@@ -393,6 +432,10 @@
                 && screenLayout != delta.screenLayout) {
             changed |= ActivityInfo.CONFIG_SCREEN_LAYOUT;
         }
+        if (delta.uiMode != UI_MODE_TYPE_NORMAL
+                && uiMode != delta.uiMode) {
+            changed |= ActivityInfo.CONFIG_UI_MODE;
+        }
         
         return changed;
     }
@@ -444,6 +487,7 @@
         dest.writeInt(navigationHidden);
         dest.writeInt(orientation);
         dest.writeInt(screenLayout);
+        dest.writeInt(uiMode);
     }
 
     public static final Parcelable.Creator<Configuration> CREATOR
@@ -477,6 +521,7 @@
         navigationHidden = source.readInt();
         orientation = source.readInt();
         screenLayout = source.readInt();
+        uiMode = source.readInt();
     }
 
     public int compareTo(Configuration that) {
@@ -510,6 +555,8 @@
         n = this.orientation - that.orientation;
         if (n != 0) return n;
         n = this.screenLayout - that.screenLayout;
+        if (n != 0) return n;
+        n = this.uiMode - that.uiMode;
         //if (n != 0) return n;
         return n;
     }
@@ -533,6 +580,6 @@
                 + this.locale.hashCode() + this.touchscreen
                 + this.keyboard + this.keyboardHidden + this.hardKeyboardHidden
                 + this.navigation + this.navigationHidden
-                + this.orientation + this.screenLayout;
+                + this.orientation + this.screenLayout + this.uiMode;
     }
 }
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index e4fc259..ae8e297 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1294,7 +1294,7 @@
                     mConfiguration.touchscreen,
                     (int)(mMetrics.density*160), mConfiguration.keyboard,
                     keyboardHidden, mConfiguration.navigation, width, height,
-                    mConfiguration.screenLayout, sSdkVersion);
+                    mConfiguration.screenLayout, mConfiguration.uiMode, sSdkVersion);
             int N = mDrawableCache.size();
             if (DEBUG_CONFIG) {
                 Log.d(TAG, "Cleaning up drawables config changes: 0x"
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 5d1e7cf..9ac8a4d 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -201,10 +201,17 @@
 
     private long mLastLockMessageTime = 0L;
 
-    // always log queries which take 100ms+; shorter queries are sampled accordingly
-    private static final int QUERY_LOG_TIME_IN_NANOS = 100 * 1000000;
+    // Things related to query logging/sampling for debugging
+    // slow/frequent queries during development.  Always log queries
+    // which take 100ms+; shorter queries are sampled accordingly.
+    // Commit statements, which are typically slow, are logged
+    // together with the most recently executed SQL statement, for
+    // disambiguation.
+    private static final int QUERY_LOG_TIME_IN_MILLIS = 100;
     private static final int QUERY_LOG_SQL_LENGTH = 64;
+    private static final String COMMIT_SQL = "COMMIT;";
     private final Random mRandom = new Random();
+    private String mLastSqlStatement = null;
 
     /** Used by native code, do not rename */
     /* package */ int mNativeHandle = 0;
@@ -540,7 +547,7 @@
                 }
             }
             if (mTransactionIsSuccessful) {
-                execSQL("COMMIT;");
+                execSQL(COMMIT_SQL);
             } else {
                 try {
                     execSQL("ROLLBACK;");
@@ -1650,7 +1657,7 @@
      * @throws SQLException If the SQL string is invalid for some reason
      */
     public void execSQL(String sql) throws SQLException {
-        long timeStart = Debug.threadCpuTimeNanos();
+        long timeStart = SystemClock.uptimeMillis();
         lock();
         try {
             native_execSQL(sql);
@@ -1660,7 +1667,15 @@
         } finally {
             unlock();
         }
-        logTimeStat(sql, timeStart);
+
+        // Log commit statements along with the most recently executed
+        // SQL statement for disambiguation.  Note that instance
+        // equality to COMMIT_SQL is safe here.
+        if (sql == COMMIT_SQL) {
+            logTimeStat(sql + mLastSqlStatement, timeStart);
+        } else {
+            logTimeStat(sql, timeStart);
+        }
     }
 
     /**
@@ -1676,7 +1691,7 @@
         if (bindArgs == null) {
             throw new IllegalArgumentException("Empty bindArgs");
         }
-        long timeStart = Debug.threadCpuTimeNanos();
+        long timeStart = SystemClock.uptimeMillis();
         lock();
         SQLiteStatement statement = null;
         try {
@@ -1785,17 +1800,22 @@
 
 
 
-    /* package */ void logTimeStat(String sql, long beginNanos) {
+    /* package */ void logTimeStat(String sql, long beginMillis) {
+        // Keep track of the last statement executed here, as this is
+        // the common funnel through which all methods of hitting
+        // libsqlite eventually flow.
+        mLastSqlStatement = sql;
+
         // Sample fast queries in proportion to the time taken.
         // Quantize the % first, so the logged sampling probability
         // exactly equals the actual sampling rate for this query.
 
         int samplePercent;
-        long nanos = Debug.threadCpuTimeNanos() - beginNanos;
-        if (nanos >= QUERY_LOG_TIME_IN_NANOS) {
+        long durationMillis = SystemClock.uptimeMillis() - beginMillis;
+        if (durationMillis >= QUERY_LOG_TIME_IN_MILLIS) {
             samplePercent = 100;
         } else {
-            samplePercent = (int) (100 * nanos / QUERY_LOG_TIME_IN_NANOS) + 1;
+            samplePercent = (int) (100 * durationMillis / QUERY_LOG_TIME_IN_MILLIS) + 1;
             if (mRandom.nextInt(100) >= samplePercent) return;
         }
 
@@ -1812,8 +1832,8 @@
         String blockingPackage = ActivityThread.currentPackageName();
         if (blockingPackage == null) blockingPackage = "";
 
-        int millis = (int) (nanos / 1000000);
-        EventLog.writeEvent(EVENT_DB_OPERATION, mPath, sql, millis, blockingPackage, samplePercent);
+        EventLog.writeEvent(
+            EVENT_DB_OPERATION, mPath, sql, durationMillis, blockingPackage, samplePercent);
     }
 
     /**
diff --git a/core/java/android/database/sqlite/SQLiteQuery.java b/core/java/android/database/sqlite/SQLiteQuery.java
index 5bcad4b..7cd9561 100644
--- a/core/java/android/database/sqlite/SQLiteQuery.java
+++ b/core/java/android/database/sqlite/SQLiteQuery.java
@@ -17,7 +17,7 @@
 package android.database.sqlite;
 
 import android.database.CursorWindow;
-import android.os.Debug;
+import android.os.SystemClock;
 import android.util.Log;
 
 /**
@@ -57,7 +57,7 @@
      */
     /* package */ int fillWindow(CursorWindow window,  
             int maxRead, int lastPos) {
-        long timeStart = Debug.threadCpuTimeNanos();
+        long timeStart = SystemClock.uptimeMillis();
         mDatabase.lock();
 
         try {
diff --git a/core/java/android/database/sqlite/SQLiteStatement.java b/core/java/android/database/sqlite/SQLiteStatement.java
index f1f5a2a..f29b69f 100644
--- a/core/java/android/database/sqlite/SQLiteStatement.java
+++ b/core/java/android/database/sqlite/SQLiteStatement.java
@@ -16,7 +16,7 @@
 
 package android.database.sqlite;
 
-import android.os.Debug;
+import android.os.SystemClock;
 
 /**
  * A pre-compiled statement against a {@link SQLiteDatabase} that can be reused.
@@ -44,7 +44,7 @@
      *         some reason
      */
     public void execute() {
-        long timeStart = Debug.threadCpuTimeNanos();
+        long timeStart = SystemClock.uptimeMillis();
         mDatabase.lock();
 
         acquireReference();
@@ -68,7 +68,7 @@
      *         some reason
      */
     public long executeInsert() {
-        long timeStart = Debug.threadCpuTimeNanos();
+        long timeStart = SystemClock.uptimeMillis();
         mDatabase.lock();
 
         acquireReference();
@@ -91,7 +91,7 @@
      * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
      */
     public long simpleQueryForLong() {
-        long timeStart = Debug.threadCpuTimeNanos();
+        long timeStart = SystemClock.uptimeMillis();
         mDatabase.lock();
 
         acquireReference();
@@ -114,7 +114,7 @@
      * @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
      */
     public String simpleQueryForString() {
-        long timeStart = Debug.threadCpuTimeNanos();
+        long timeStart = SystemClock.uptimeMillis();
         mDatabase.lock();
 
         acquireReference();
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 47c2cac..c0bff66 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -723,6 +723,7 @@
         private static final String KEY_FOCAL_LENGTH = "focal-length";
         private static final String KEY_HORIZONTAL_VIEW_ANGLE = "horizontal-view-angle";
         private static final String KEY_VERTICAL_VIEW_ANGLE = "vertical-view-angle";
+        private static final String KEY_EXPOSURE_COMPENSATION = "exposure-compensation";
         // Parameter key suffix for supported values.
         private static final String SUPPORTED_VALUES_SUFFIX = "-values";
 
@@ -1051,7 +1052,8 @@
         }
 
         /**
-         * Sets the rate at which preview frames are received.
+         * Sets the rate at which preview frames are received. This is the
+         * target frame rate. The actual frame rate depends on the driver.
          *
          * @param fps the frame rate (frames per second)
          */
@@ -1060,8 +1062,9 @@
         }
 
         /**
-         * Returns the setting for the rate at which preview frames
-         * are received.
+         * Returns the setting for the rate at which preview frames are
+         * received. This is the target frame rate. The actual frame rate
+         * depends on the driver.
          *
          * @return the frame rate setting (frames per second)
          */
@@ -1540,6 +1543,41 @@
         }
 
         /**
+         * Gets the current exposure compensation setting.
+         *
+         * @return the current exposure compensation value multiplied by 100.
+         *         null if exposure compensation is not supported. Ex: -100
+         *         means -1 EV. 130 means +1.3 EV.
+         * @hide
+         */
+        public int getExposureCompensation() {
+            return getInt(KEY_EXPOSURE_COMPENSATION);
+        }
+
+        /**
+         * Sets the exposure compensation.
+         *
+         * @param value exposure compensation multiplied by 100. Ex: -100 means
+         *        -1 EV. 130 means +1.3 EV.
+         * @hide
+         */
+        public void setExposureCompensation(int value) {
+            set(KEY_EXPOSURE_COMPENSATION, value);
+        }
+
+        /**
+         * Gets the supported exposure compensation.
+         *
+         * @return a List of Integer constants. null if exposure compensation is
+         *         not supported. The list is sorted from small to large. Ex:
+         *         -100, -66, -33, 0, 33, 66, 100.
+         * @hide
+         */
+        public List<Integer> getSupportedExposureCompensation() {
+            return splitInt(get(KEY_EXPOSURE_COMPENSATION + SUPPORTED_VALUES_SUFFIX));
+        }
+
+        /**
          * Gets current zoom value. This also works when smooth zoom is in
          * progress.
          *
diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java
index 28a86b8..9201e3b 100644
--- a/core/java/android/inputmethodservice/KeyboardView.java
+++ b/core/java/android/inputmethodservice/KeyboardView.java
@@ -165,6 +165,7 @@
 
     private static final int DELAY_BEFORE_PREVIEW = 0;
     private static final int DELAY_AFTER_PREVIEW = 70;
+    private static final int DEBOUNCE_TIME = 70;
     
     private int mVerticalCorrection;
     private int mProximityThreshold;
@@ -1122,7 +1123,8 @@
         mSwipeTracker.addMovement(me);
 
         // Ignore all motion events until a DOWN.
-        if (mAbortKey && action != MotionEvent.ACTION_DOWN) {
+        if (mAbortKey
+                && action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_CANCEL) {
             return true;
         }
 
@@ -1206,6 +1208,7 @@
                     }
                 }
                 showPreview(mCurrentKey);
+                mLastMoveTime = eventTime;
                 break;
 
             case MotionEvent.ACTION_UP:
@@ -1219,7 +1222,8 @@
                     mCurrentKey = keyIndex;
                     mCurrentKeyTime = 0;
                 }
-                if (mCurrentKeyTime < mLastKeyTime && mLastKey != NOT_A_KEY) {
+                if (mCurrentKeyTime < mLastKeyTime && mCurrentKeyTime < DEBOUNCE_TIME
+                        && mLastKey != NOT_A_KEY) {
                     mCurrentKey = mLastKey;
                     touchX = mLastCodeX;
                     touchY = mLastCodeY;
diff --git a/core/java/android/net/Downloads.java b/core/java/android/net/Downloads.java
new file mode 100644
index 0000000..a794af2
--- /dev/null
+++ b/core/java/android/net/Downloads.java
@@ -0,0 +1,642 @@
+/*
+ * Copyright (C) 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.
+ */
+
+package android.net;
+
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+import android.os.SystemClock;
+import android.provider.BaseColumns;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.File;
+import java.io.InputStream;
+
+/**
+ * The Download Manager
+ *
+ *
+ */
+public final class Downloads {
+
+
+    /**
+     * Download status codes
+     */
+
+    /**
+     * This download hasn't started yet
+     */
+    public static final int STATUS_PENDING = 190;
+
+    /**
+     * This download has started
+     */
+    public static final int STATUS_RUNNING = 192;
+
+    /**
+     * This download has successfully completed.
+     * Warning: there might be other status values that indicate success
+     * in the future.
+     * Use isSucccess() to capture the entire category.
+     */
+    public static final int STATUS_SUCCESS = 200;
+
+    /**
+     * This download can't be performed because the content type cannot be
+     * handled.
+     */
+    public static final int STATUS_NOT_ACCEPTABLE = 406;
+
+    /**
+     * This download has completed with an error.
+     * Warning: there will be other status values that indicate errors in
+     * the future. Use isStatusError() to capture the entire category.
+     */
+    public static final int STATUS_UNKNOWN_ERROR = 491;
+
+    /**
+     * This download couldn't be completed because of an HTTP
+     * redirect response that the download manager couldn't
+     * handle.
+     */
+    public static final int STATUS_UNHANDLED_REDIRECT = 493;
+
+    /**
+     * This download couldn't be completed due to insufficient storage
+     * space.  Typically, this is because the SD card is full.
+     */
+    public static final int STATUS_INSUFFICIENT_SPACE_ERROR = 498;
+
+    /**
+     * This download couldn't be completed because no external storage
+     * device was found.  Typically, this is because the SD card is not
+     * mounted.
+     */
+    public static final int STATUS_DEVICE_NOT_FOUND_ERROR = 499;
+
+    /**
+     * Returns whether the status is a success (i.e. 2xx).
+     */
+    public static boolean isStatusSuccess(int status) {
+        return (status >= 200 && status < 300);
+    }
+
+    /**
+     * Returns whether the status is an error (i.e. 4xx or 5xx).
+     */
+    public static boolean isStatusError(int status) {
+        return (status >= 400 && status < 600);
+    }
+
+    /**
+     * Download destinations
+     */
+
+    /**
+     * This download will be saved to the external storage. This is the
+     * default behavior, and should be used for any file that the user
+     * can freely access, copy, delete. Even with that destination,
+     * unencrypted DRM files are saved in secure internal storage.
+     * Downloads to the external destination only write files for which
+     * there is a registered handler. The resulting files are accessible
+     * by filename to all applications.
+     */
+    public static final int DOWNLOAD_DESTINATION_EXTERNAL = 1;
+
+    /**
+     * This download will be saved to the download manager's private
+     * partition. This is the behavior used by applications that want to
+     * download private files that are used and deleted soon after they
+     * get downloaded. All file types are allowed, and only the initiating
+     * application can access the file (indirectly through a content
+     * provider). This requires the
+     * android.permission.ACCESS_DOWNLOAD_MANAGER_ADVANCED permission.
+     */
+    public static final int DOWNLOAD_DESTINATION_CACHE = 2;
+
+    /**
+     * This download will be saved to the download manager's private
+     * partition and will be purged as necessary to make space. This is
+     * for private files (similar to CACHE_PARTITION) that aren't deleted
+     * immediately after they are used, and are kept around by the download
+     * manager as long as space is available.
+     */
+    public static final int DOWNLOAD_DESTINATION_CACHE_PURGEABLE = 3;
+
+
+    /**
+     * An invalid download id
+     */
+    public static final long DOWNLOAD_ID_INVALID = -1;
+
+
+    /**
+     * Broadcast Action: this is sent by the download manager to the app
+     * that had initiated a download when that download completes. The
+     * download's content: uri is specified in the intent's data.
+     */
+    public static final String ACTION_DOWNLOAD_COMPLETED =
+            "android.intent.action.DOWNLOAD_COMPLETED";
+
+    /**
+     * If extras are specified when requesting a download they will be provided in the intent that
+     * is sent to the specified class and package when a download has finished.
+     * <P>Type: TEXT</P>
+     * <P>Owner can Init</P>
+     */
+    public static final String COLUMN_NOTIFICATION_EXTRAS = "notificationextras";
+
+
+    /**
+     * Status class for a download
+     */
+    public static final class StatusInfo {
+        public boolean completed = false;
+        /** The filename of the active download. */
+        public String filename = null;
+        /** An opaque id for the download */
+        public long id = DOWNLOAD_ID_INVALID;
+        /** An opaque status code for the download */
+        public int statusCode = -1;
+        /** Approximate number of bytes downloaded so far, for debugging purposes. */
+        public long bytesSoFar = -1;
+
+        /**
+         * Returns whether the download is completed
+         * @return a boolean whether the download is complete.
+         */
+        public boolean isComplete() {
+            return android.provider.Downloads.Impl.isStatusCompleted(statusCode);
+        }
+
+        /**
+         * Returns whether the download is successful
+         * @return a boolean whether the download is successful.
+         */
+        public boolean isSuccessful() {
+            return android.provider.Downloads.Impl.isStatusCompleted(statusCode);
+        }
+    }
+
+    /**
+     * Class to access initiate and query download by server uri
+     */
+    public static final class ByUri extends DownloadBase {
+        /** @hide */
+        private ByUri() {}
+
+        /**
+         * Query where clause by app data.
+         * @hide
+         */
+        private static final String QUERY_WHERE_APP_DATA_CLAUSE =
+                android.provider.Downloads.Impl.COLUMN_APP_DATA + "=?";
+
+        /**
+         * Gets a Cursor pointing to the download(s) of the current system update.
+         * @hide
+         */
+        private static final Cursor getCurrentOtaDownloads(Context context, String url) {
+            return context.getContentResolver().query(
+                    android.provider.Downloads.Impl.CONTENT_URI,
+                    DOWNLOADS_PROJECTION,
+                    QUERY_WHERE_APP_DATA_CLAUSE,
+                    new String[] {url},
+                    null);
+        }
+
+        /**
+         * Returns a StatusInfo with the result of trying to download the
+         * given URL.  Returns null if no attempts have been made.
+         */
+        public static final StatusInfo getStatus(
+                Context context,
+                String url,
+                long redownload_threshold) {
+            StatusInfo result = null;
+            boolean hasFailedDownload = false;
+            long failedDownloadModificationTime = 0;
+            Cursor c = getCurrentOtaDownloads(context, url);
+            try {
+                while (c != null && c.moveToNext()) {
+                    if (result == null) {
+                        result = new StatusInfo();
+                    }
+                    int status = getStatusOfDownload(c, redownload_threshold);
+                    if (status == STATUS_DOWNLOADING_UPDATE ||
+                        status == STATUS_DOWNLOADED_UPDATE) {
+                        result.completed = (status == STATUS_DOWNLOADED_UPDATE);
+                        result.filename = c.getString(DOWNLOADS_COLUMN_FILENAME);
+                        result.id = c.getLong(DOWNLOADS_COLUMN_ID);
+                        result.statusCode = c.getInt(DOWNLOADS_COLUMN_STATUS);
+                        result.bytesSoFar = c.getLong(DOWNLOADS_COLUMN_CURRENT_BYTES);
+                        return result;
+                    }
+
+                    long modTime = c.getLong(DOWNLOADS_COLUMN_LAST_MODIFICATION);
+                    if (hasFailedDownload &&
+                        modTime < failedDownloadModificationTime) {
+                        // older than the one already in result; skip it.
+                        continue;
+                    }
+
+                    hasFailedDownload = true;
+                    failedDownloadModificationTime = modTime;
+                    result.statusCode = c.getInt(DOWNLOADS_COLUMN_STATUS);
+                    result.bytesSoFar = c.getLong(DOWNLOADS_COLUMN_CURRENT_BYTES);
+                }
+            } finally {
+                if (c != null) {
+                    c.close();
+                }
+            }
+            return result;
+        }
+
+        /**
+         * Query where clause for general querying.
+         */
+        private static final String QUERY_WHERE_CLAUSE =
+                android.provider.Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE + "=? AND " +
+                android.provider.Downloads.Impl.COLUMN_NOTIFICATION_CLASS + "=?";
+
+        /**
+         * Delete all the downloads for a package/class pair.
+         */
+        public static final void removeAllDownloadsByPackage(
+                Context context,
+                String notification_package,
+                String notification_class) {
+            context.getContentResolver().delete(
+                    android.provider.Downloads.Impl.CONTENT_URI,
+                    QUERY_WHERE_CLAUSE,
+                    new String[] { notification_package, notification_class });
+        }
+
+        /**
+         * @pending
+         */
+        public static final int getProgressColumnId() {
+            return 0;
+        }
+
+        /**
+         * @pending
+         */
+        public static final int getProgressColumnCurrentBytes() {
+            return 1;
+        }
+
+        /**
+         * @pending
+         */
+        public static final int getProgressColumnTotalBytes() {
+            return 2;
+        }
+
+        /** @hide */
+        private static final String[] PROJECTION = {
+            BaseColumns._ID,
+            android.provider.Downloads.Impl.COLUMN_CURRENT_BYTES,
+            android.provider.Downloads.Impl.COLUMN_TOTAL_BYTES
+        };
+
+        /**
+         * @pending
+         */
+        public static final Cursor getProgressCursor(Context context, long id) {
+            Uri downloadUri = Uri.withAppendedPath(android.provider.Downloads.Impl.CONTENT_URI,
+                    String.valueOf(id));
+            return context.getContentResolver().query(downloadUri, PROJECTION, null, null, null);
+        }
+    }
+
+    /**
+     * Class to access downloads by opaque download id
+     */
+    public static final class ById extends DownloadBase {
+        /** @hide */
+        private ById() {}
+
+        /**
+         * Get the mime tupe of the download specified by the download id
+         */
+        public static String getMimeTypeForId(Context context, long downloadId) {
+            ContentResolver cr = context.getContentResolver();
+
+            String mimeType = null;
+            Cursor downloadCursor = null;
+
+            try {
+                Uri downloadUri = getDownloadUri(downloadId);
+
+                downloadCursor = cr.query(
+                        downloadUri, new String[]{android.provider.Downloads.Impl.COLUMN_MIME_TYPE},
+                        null, null, null);
+                if (downloadCursor.moveToNext()) {
+                    mimeType = downloadCursor.getString(0);
+                }
+            } finally {
+                if (downloadCursor != null) downloadCursor.close();
+            }
+            return mimeType;
+        }
+
+        /**
+         * Delete a download by Id
+         */
+        public static void deleteDownload(Context context, long downloadId) {
+            ContentResolver cr = context.getContentResolver();
+
+            String mimeType = null;
+
+            Uri downloadUri = getDownloadUri(downloadId);
+
+            cr.delete(downloadUri, null, null);
+        }
+
+        /**
+         * Open a filedescriptor to a particular download
+         */
+        public static ParcelFileDescriptor openDownload(
+                Context context, long downloadId, String mode)
+            throws FileNotFoundException
+        {
+            ContentResolver cr = context.getContentResolver();
+
+            String mimeType = null;
+
+            Uri downloadUri = getDownloadUri(downloadId);
+
+            return cr.openFileDescriptor(downloadUri, mode);
+        }
+
+        /**
+         * Open a stream to a particular download
+         */
+        public static InputStream openDownloadStream(Context context, long downloadId)
+                throws FileNotFoundException, IOException
+        {
+            ContentResolver cr = context.getContentResolver();
+
+            String mimeType = null;
+
+            Uri downloadUri = getDownloadUri(downloadId);
+
+            return cr.openInputStream(downloadUri);
+        }
+
+        private static Uri getDownloadUri(long downloadId) {
+            return Uri.parse(android.provider.Downloads.Impl.CONTENT_URI + "/" + downloadId);
+        }
+
+        /**
+         * Returns a StatusInfo with the result of trying to download the
+         * given URL.  Returns null if no attempts have been made.
+         */
+        public static final StatusInfo getStatus(
+                Context context,
+                long downloadId) {
+            StatusInfo result = null;
+            boolean hasFailedDownload = false;
+            long failedDownloadModificationTime = 0;
+
+            Uri downloadUri = getDownloadUri(downloadId);
+
+            ContentResolver cr = context.getContentResolver();
+
+            Cursor c = cr.query(
+                    downloadUri, DOWNLOADS_PROJECTION, null /* selection */, null /* selection args */,
+                    null /* sort order */);
+            try {
+                if (!c.moveToNext()) {
+                    return result;
+                }
+
+                if (result == null) {
+                    result = new StatusInfo();
+                }
+                int status = getStatusOfDownload(c,0);
+                if (status == STATUS_DOWNLOADING_UPDATE ||
+                        status == STATUS_DOWNLOADED_UPDATE) {
+                    result.completed = (status == STATUS_DOWNLOADED_UPDATE);
+                    result.filename = c.getString(DOWNLOADS_COLUMN_FILENAME);
+                    result.id = c.getLong(DOWNLOADS_COLUMN_ID);
+                    result.statusCode = c.getInt(DOWNLOADS_COLUMN_STATUS);
+                    result.bytesSoFar = c.getLong(DOWNLOADS_COLUMN_CURRENT_BYTES);
+                    return result;
+                }
+
+                long modTime = c.getLong(DOWNLOADS_COLUMN_LAST_MODIFICATION);
+
+                result.statusCode = c.getInt(DOWNLOADS_COLUMN_STATUS);
+                result.bytesSoFar = c.getLong(DOWNLOADS_COLUMN_CURRENT_BYTES);
+            } finally {
+                if (c != null) {
+                    c.close();
+                }
+            }
+            return result;
+        }
+    }
+
+
+    /**
+     * Base class with common functionality for the various download classes
+     */
+    private static class DownloadBase {
+        /** @hide */
+        DownloadBase() {}
+
+        /**
+          * Initiate a download where the download will be tracked by its URI.
+          */
+        public static long startDownloadByUri(
+                Context context,
+                String url,
+                String cookieData,
+                boolean showDownload,
+                int downloadDestination,
+                boolean allowRoaming,
+                boolean skipIntegrityCheck,
+                String title,
+                String notification_package,
+                String notification_class,
+                String notification_extras) {
+            ContentResolver cr = context.getContentResolver();
+
+            // Tell download manager to start downloading update.
+            ContentValues values = new ContentValues();
+            values.put(android.provider.Downloads.Impl.COLUMN_URI, url);
+            values.put(android.provider.Downloads.Impl.COLUMN_COOKIE_DATA, cookieData);
+            values.put(android.provider.Downloads.Impl.COLUMN_VISIBILITY,
+                       showDownload ? android.provider.Downloads.Impl.VISIBILITY_VISIBLE
+                       : android.provider.Downloads.Impl.VISIBILITY_HIDDEN);
+            if (title != null) {
+                values.put(android.provider.Downloads.Impl.COLUMN_TITLE, title);
+            }
+            values.put(android.provider.Downloads.Impl.COLUMN_APP_DATA, url);
+
+
+            // NOTE:  destination should be seperated from whether the download
+            // can happen when roaming
+            int destination = android.provider.Downloads.Impl.DESTINATION_EXTERNAL;
+            switch (downloadDestination) {
+                case DOWNLOAD_DESTINATION_EXTERNAL:
+                    destination = android.provider.Downloads.Impl.DESTINATION_EXTERNAL;
+                    break;
+                case DOWNLOAD_DESTINATION_CACHE:
+                    if (allowRoaming) {
+                        destination = android.provider.Downloads.Impl.DESTINATION_CACHE_PARTITION;
+                    } else {
+                        destination =
+                                android.provider.Downloads.Impl.DESTINATION_CACHE_PARTITION_NOROAMING;
+                    }
+                    break;
+                case DOWNLOAD_DESTINATION_CACHE_PURGEABLE:
+                    destination =
+                            android.provider.Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE;
+                    break;
+            }
+            values.put(android.provider.Downloads.Impl.COLUMN_DESTINATION, destination);
+            values.put(android.provider.Downloads.Impl.COLUMN_NO_INTEGRITY,
+                    skipIntegrityCheck);  // Don't check ETag
+            if (notification_package != null && notification_class != null) {
+                values.put(android.provider.Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE,
+                        notification_package);
+                values.put(android.provider.Downloads.Impl.COLUMN_NOTIFICATION_CLASS,
+                        notification_class);
+
+                if (notification_extras != null) {
+                    values.put(android.provider.Downloads.Impl.COLUMN_NOTIFICATION_EXTRAS,
+                            notification_extras);
+                }
+            }
+
+            Uri downloadUri = cr.insert(android.provider.Downloads.Impl.CONTENT_URI, values);
+
+            long downloadId = DOWNLOAD_ID_INVALID;
+            if (downloadUri != null) {
+                downloadId = Long.parseLong(downloadUri.getLastPathSegment());
+            }
+            return downloadId;
+        }
+    }
+
+    /** @hide */
+    private static final int STATUS_INVALID = 0;
+    /** @hide */
+    private static final int STATUS_DOWNLOADING_UPDATE = 3;
+    /** @hide */
+    private static final int STATUS_DOWNLOADED_UPDATE = 4;
+
+    /**
+     * Column projection for the query to the download manager. This must match
+     * with the constants DOWNLOADS_COLUMN_*.
+     * @hide
+     */
+    private static final String[] DOWNLOADS_PROJECTION = {
+            BaseColumns._ID,
+            android.provider.Downloads.Impl.COLUMN_APP_DATA,
+            android.provider.Downloads.Impl.COLUMN_STATUS,
+            android.provider.Downloads.Impl._DATA,
+            android.provider.Downloads.Impl.COLUMN_LAST_MODIFICATION,
+            android.provider.Downloads.Impl.COLUMN_CURRENT_BYTES,
+    };
+
+    /**
+     * The column index for the ID.
+     * @hide
+     */
+    private static final int DOWNLOADS_COLUMN_ID = 0;
+    /**
+     * The column index for the URI.
+     * @hide
+     */
+    private static final int DOWNLOADS_COLUMN_URI = 1;
+    /**
+     * The column index for the status code.
+     * @hide
+     */
+    private static final int DOWNLOADS_COLUMN_STATUS = 2;
+    /**
+     * The column index for the filename.
+     * @hide
+     */
+    private static final int DOWNLOADS_COLUMN_FILENAME = 3;
+    /**
+     * The column index for the last modification time.
+     * @hide
+     */
+    private static final int DOWNLOADS_COLUMN_LAST_MODIFICATION = 4;
+    /**
+     * The column index for the number of bytes downloaded so far.
+     * @hide
+     */
+    private static final int DOWNLOADS_COLUMN_CURRENT_BYTES = 5;
+
+    /**
+     * Gets the status of a download.
+     *
+     * @param c A Cursor pointing to a download.  The URL column is assumed to be valid.
+     * @return The status of the download.
+     * @hide
+     */
+    private static final int getStatusOfDownload( Cursor c, long redownload_threshold) {
+        int status = c.getInt(DOWNLOADS_COLUMN_STATUS);
+        long realtime = SystemClock.elapsedRealtime();
+
+        // TODO(dougz): special handling of 503, 404?  (eg, special
+        // explanatory messages to user)
+
+        if (!android.provider.Downloads.Impl.isStatusCompleted(status)) {
+            // Check if it's stuck
+            long modified = c.getLong(DOWNLOADS_COLUMN_LAST_MODIFICATION);
+            long now = System.currentTimeMillis();
+            if (now < modified || now - modified > redownload_threshold) {
+                return STATUS_INVALID;
+            }
+
+            return STATUS_DOWNLOADING_UPDATE;
+        }
+
+        if (android.provider.Downloads.Impl.isStatusError(status)) {
+            return STATUS_INVALID;
+        }
+
+        String filename = c.getString(DOWNLOADS_COLUMN_FILENAME);
+        if (filename == null) {
+            return STATUS_INVALID;
+        }
+
+        return STATUS_DOWNLOADED_UPDATE;
+    }
+
+
+    /**
+     * @hide
+     */
+    private Downloads() {}
+}
diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java
index e40f1b8..ed76b15 100644
--- a/core/java/android/net/SSLCertificateSocketFactory.java
+++ b/core/java/android/net/SSLCertificateSocketFactory.java
@@ -40,224 +40,174 @@
 import javax.net.ssl.TrustManagerFactory;
 import javax.net.ssl.X509TrustManager;
 
+import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl;
 import org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache;
 import org.apache.harmony.xnet.provider.jsse.SSLContextImpl;
 import org.apache.harmony.xnet.provider.jsse.SSLParameters;
 
 /**
- * SSLSocketFactory that provides optional (on debug devices, only) skipping of ssl certificfate
- * chain validation and custom read timeouts used just when connecting to the server/negotiating
- * an ssl session.
- *
- * You can skip the ssl certificate checking at runtime by setting socket.relaxsslcheck=yes on
- * devices that do not have have ro.secure set.
+ * SSLSocketFactory implementation with several extra features:
+ * <ul>
+ * <li>Timeout specification for SSL handshake operations
+ * <li>Optional SSL session caching with {@link SSLSessionCache}
+ * <li>On development devices, "setprop socket.relaxsslcheck yes" bypasses all
+ * SSL certificate checks, for testing with development servers
+ * </ul>
+ * Note that the handshake timeout does not apply to actual connection.
+ * If you want a connection timeout as well, use {@link #createSocket()} and
+ * {@link Socket#connect(SocketAddress, int)}.
  */
 public class SSLCertificateSocketFactory extends SSLSocketFactory {
+    private static final String TAG = "SSLCertificateSocketFactory";
 
-    private static final String LOG_TAG = "SSLCertificateSocketFactory";
-
-    private static final TrustManager[] TRUST_MANAGER = new TrustManager[] {
+    private static final TrustManager[] INSECURE_TRUST_MANAGER = new TrustManager[] {
         new X509TrustManager() {
-            public X509Certificate[] getAcceptedIssuers() {
-                return null;
-            }
-
-            public void checkClientTrusted(X509Certificate[] certs,
-                    String authType) { }
-
-            public void checkServerTrusted(X509Certificate[] certs,
-                    String authType) { }
+            public X509Certificate[] getAcceptedIssuers() { return null; }
+            public void checkClientTrusted(X509Certificate[] certs, String authType) { }
+            public void checkServerTrusted(X509Certificate[] certs, String authType) { }
         }
     };
 
-    private final SSLSocketFactory mFactory;
+    private SSLSocketFactory mInsecureFactory = null;
+    private SSLSocketFactory mSecureFactory = null;
 
-    private final int mSocketReadTimeoutForSslHandshake;
+    private final int mHandshakeTimeoutMillis;
+    private final SSLClientSessionCache mSessionCache;
 
-    /**
-     * Do not use this constructor (will be deprecated).  Use {@link #getDefault(int)} instead.
-     */
-    public SSLCertificateSocketFactory(int socketReadTimeoutForSslHandshake)
-            throws NoSuchAlgorithmException, KeyManagementException {
-        this(socketReadTimeoutForSslHandshake, null /* cache */);
+    /** @deprecated Use {@link #getDefault(int)} instead. */
+    public SSLCertificateSocketFactory(int handshakeTimeoutMillis) {
+        this(handshakeTimeoutMillis, null /* cache */);
     }
 
-    private SSLCertificateSocketFactory(int socketReadTimeoutForSslHandshake,
-            SSLClientSessionCache cache) throws NoSuchAlgorithmException, KeyManagementException {
-        SSLContextImpl sslContext = new SSLContextImpl();
-        sslContext.engineInit(null /* kms */,
-            TRUST_MANAGER, new java.security.SecureRandom(),
-            cache /* client cache */, null /* server cache */);
-        this.mFactory = sslContext.engineGetSocketFactory();
-        this.mSocketReadTimeoutForSslHandshake = socketReadTimeoutForSslHandshake;
+    private SSLCertificateSocketFactory(int handshakeTimeoutMillis, SSLSessionCache cache) {
+        mHandshakeTimeoutMillis = handshakeTimeoutMillis;
+        mSessionCache = cache == null ? null : cache.mSessionCache;
     }
 
     /**
      * Returns a new instance of a socket factory using the specified socket read
      * timeout while connecting with the server/negotiating an ssl session.
      *
-     * @param socketReadTimeoutForSslHandshake the socket read timeout used for performing
-     *        ssl handshake. The socket read timeout is set back to 0 after the handshake.
-     * @return a new SocketFactory, or null on error
+     * @param handshakeTimeoutMillis to use for SSL connection handshake, or 0
+     *         for none.  The socket timeout is reset to 0 after the handshake.
+     * @return a new SocketFactory with the specified parameters
      */
-    public static SocketFactory getDefault(int socketReadTimeoutForSslHandshake) {
-        return getDefault(socketReadTimeoutForSslHandshake, null /* cache */);
+    public static SocketFactory getDefault(int handshakeTimeoutMillis) {
+        return getDefault(handshakeTimeoutMillis, null /* cache */);
     }
 
     /**
-     * Returns a new instance of a socket factory using the specified socket read
-     * timeout while connecting with the server/negotiating an ssl session.
+     * Returns a new instance of a socket factory using the specified socket
+     * read timeout while connecting with the server/negotiating an ssl session
      * Persists ssl sessions using the provided {@link SSLClientSessionCache}.
      *
-     * @param socketReadTimeoutForSslHandshake the socket read timeout used for performing
-     *        ssl handshake. The socket read timeout is set back to 0 after the handshake.
-     * @param cache The {@link SSLClientSessionCache} to use, if any.
-     * @return a new SocketFactory, or null on error
+     * @param handshakeTimeoutMillis to use for SSL connection handshake, or 0
+     *         for none.  The socket timeout is reset to 0 after the handshake.
+     * @param cache The {@link SSLClientSessionCache} to use, or null for no cache.
+     * @return a new SocketFactory with the specified parameters
+     */
+    public static SocketFactory getDefault(int handshakeTimeoutMillis, SSLSessionCache cache) {
+        return new SSLCertificateSocketFactory(handshakeTimeoutMillis, cache);
+    }
+
+    /**
+     * Returns a socket factory (also named SSLSocketFactory, but in a different
+     * namespace) for use with the Apache HTTP stack.
      *
-     * @hide
-    */
-    public static SocketFactory getDefault(int socketReadTimeoutForSslHandshake,
-            SSLClientSessionCache cache) {
+     * @param handshakeTimeoutMillis to use for SSL connection handshake, or 0
+     *         for none.  The socket timeout is reset to 0 after the handshake.
+     * @param cache The {@link SSLClientSessionCache} to use, or null for no cache.
+     * @return a new SocketFactory with the specified parameters
+     */
+    public static org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(
+            int handshakeTimeoutMillis,
+            SSLSessionCache cache) {
+        return new org.apache.http.conn.ssl.SSLSocketFactory(
+                new SSLCertificateSocketFactory(handshakeTimeoutMillis, cache));
+    }
+
+    private SSLSocketFactory makeSocketFactory(TrustManager[] trustManagers) {
         try {
-            return new SSLCertificateSocketFactory(socketReadTimeoutForSslHandshake, cache);
-        } catch (NoSuchAlgorithmException e) {
-            Log.e(LOG_TAG, 
-                    "SSLCertifcateSocketFactory.getDefault" +
-                    " NoSuchAlgorithmException " , e);
-            return null;
+            SSLContextImpl sslContext = new SSLContextImpl();
+            sslContext.engineInit(null, trustManagers, null, mSessionCache, null);
+            return sslContext.engineGetSocketFactory();
         } catch (KeyManagementException e) {
-            Log.e(LOG_TAG, 
-                    "SSLCertifcateSocketFactory.getDefault" +
-                    " KeyManagementException " , e);
-            return null; 
+            Log.wtf(TAG, e);
+            return (SSLSocketFactory) SSLSocketFactory.getDefault();  // Fallback
         }
     }
 
-    private boolean hasValidCertificateChain(Certificate[] certs) 
-            throws IOException {
-        boolean trusted = (certs != null && (certs.length > 0));
-
-        if (trusted) {
-            try {
-                // the authtype we pass in doesn't actually matter
-                SSLParameters.getDefaultTrustManager()
-                        .checkServerTrusted((X509Certificate[]) certs, "RSA");
-            } catch (GeneralSecurityException e) { 
-                String exceptionMessage = e != null ? e.getMessage() : "none";
-                if (Config.LOGD) {
-                    Log.d(LOG_TAG,"hasValidCertificateChain(): sec. exception: "
-                         + exceptionMessage);
-                }
-                trusted = false;
-            }
-        }
-
-        return trusted;
-    }
-
-    private void validateSocket(SSLSocket sslSock, String destHost) 
-            throws IOException
-    {
-        if (Config.LOGV) {
-            Log.v(LOG_TAG,"validateSocket() to host "+destHost);
-        }
-
-        String relaxSslCheck = SystemProperties.get("socket.relaxsslcheck");
-        String secure = SystemProperties.get("ro.secure");
-
+    private synchronized SSLSocketFactory getDelegate() {
         // only allow relaxing the ssl check on non-secure builds where the relaxation is
         // specifically requested.
-        if ("0".equals(secure) && "yes".equals(relaxSslCheck)) {
-            if (Config.LOGD) {
-                Log.d(LOG_TAG,"sys prop socket.relaxsslcheck is set," +
-                        " ignoring invalid certs");
+        if ("0".equals(SystemProperties.get("ro.secure")) &&
+            "yes".equals(SystemProperties.get("socket.relaxsslcheck"))) {
+            if (mInsecureFactory == null) {
+                Log.w(TAG, "*** BYPASSING SSL SECURITY CHECKS (socket.relaxsslcheck=yes) ***");
+                mInsecureFactory = makeSocketFactory(INSECURE_TRUST_MANAGER);
             }
-            return;
-        }
-
-        Certificate[] certs = null;
-        sslSock.setUseClientMode(true);
-        sslSock.startHandshake();
-        certs = sslSock.getSession().getPeerCertificates();
-
-        // check that the root certificate in the chain belongs to
-        // a CA we trust
-        if (certs == null) {
-            Log.e(LOG_TAG, 
-                    "[SSLCertificateSocketFactory] no trusted root CA");
-            throw new IOException("no trusted root CA");
-        }
-
-        if (Config.LOGV) {
-            Log.v(LOG_TAG,"validateSocket # certs = " +certs.length);
-        }
-
-        if (!hasValidCertificateChain(certs)) {
-            if (Config.LOGD) {
-                Log.d(LOG_TAG,"validateSocket(): certificate untrusted!");
+            return mInsecureFactory;
+        } else {
+            if (mSecureFactory == null) {
+                mSecureFactory = makeSocketFactory(null);
             }
-            throw new IOException("Certificate untrusted");
-        }
-
-        X509Certificate lastChainCert = (X509Certificate) certs[0];
-
-        if (!DomainNameValidator.match(lastChainCert, destHost)) {
-            if (Config.LOGD) {
-                Log.d(LOG_TAG,"validateSocket(): domain name check failed");
-            }
-            throw new IOException("Domain Name check failed");
+            return mSecureFactory;
         }
     }
 
-    public Socket createSocket(Socket socket, String s, int i, boolean flag)
-            throws IOException
-    {
-        throw new IOException("Cannot validate certification without a hostname");       
+    @Override
+    public Socket createSocket(Socket k, String host, int port, boolean close) throws IOException {
+        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(k, host, port, close);
+        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
+        return s;
     }
 
-    public Socket createSocket(InetAddress inaddr, int i, InetAddress inaddr2, int j)
-            throws IOException
-    {
-        throw new IOException("Cannot validate certification without a hostname");       
+    @Override
+    public Socket createSocket() throws IOException {
+        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket();
+        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
+        return s;
     }
 
-    public Socket createSocket(InetAddress inaddr, int i) throws IOException {
-        throw new IOException("Cannot validate certification without a hostname");       
+    @Override
+    public Socket createSocket(InetAddress addr, int port, InetAddress localAddr, int localPort)
+            throws IOException {
+        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(
+                addr, port, localAddr, localPort);
+        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
+        return s;
     }
 
-    public Socket createSocket(String s, int i, InetAddress inaddr, int j) throws IOException {
-        SSLSocket sslSock = (SSLSocket) mFactory.createSocket(s, i, inaddr, j);
-
-        if (mSocketReadTimeoutForSslHandshake >= 0) {
-            sslSock.setSoTimeout(mSocketReadTimeoutForSslHandshake);
-        }
-
-        validateSocket(sslSock,s);
-        sslSock.setSoTimeout(0);
-        
-        return sslSock;
+    @Override
+    public Socket createSocket(InetAddress addr, int port) throws IOException {
+        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(addr, port);
+        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
+        return s;
     }
 
-    public Socket createSocket(String s, int i) throws IOException {
-        SSLSocket sslSock = (SSLSocket) mFactory.createSocket(s, i);
-
-        if (mSocketReadTimeoutForSslHandshake >= 0) {
-            sslSock.setSoTimeout(mSocketReadTimeoutForSslHandshake);
-        }
-        
-        validateSocket(sslSock,s);
-        sslSock.setSoTimeout(0);
-
-        return sslSock;
+    @Override
+    public Socket createSocket(String host, int port, InetAddress localAddr, int localPort)
+            throws IOException {
+        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(
+                host, port, localAddr, localPort);
+        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
+        return s;
     }
 
+    @Override
+    public Socket createSocket(String host, int port) throws IOException {
+        OpenSSLSocketImpl s = (OpenSSLSocketImpl) getDelegate().createSocket(host, port);
+        s.setHandshakeTimeout(mHandshakeTimeoutMillis);
+        return s;
+    }
+
+    @Override
     public String[] getDefaultCipherSuites() {
-        return mFactory.getSupportedCipherSuites();
+        return getDelegate().getSupportedCipherSuites();
     }
 
+    @Override
     public String[] getSupportedCipherSuites() {
-        return mFactory.getSupportedCipherSuites();
+        return getDelegate().getSupportedCipherSuites();
     }
 }
-
-
diff --git a/core/java/android/net/SSLSessionCache.java b/core/java/android/net/SSLSessionCache.java
new file mode 100644
index 0000000..4cbeb94
--- /dev/null
+++ b/core/java/android/net/SSLSessionCache.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import org.apache.harmony.xnet.provider.jsse.FileClientSessionCache;
+import org.apache.harmony.xnet.provider.jsse.SSLClientSessionCache;
+
+import android.content.Context;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * File-based cache of established SSL sessions.  When re-establishing a
+ * connection to the same server, using an SSL session cache can save some time,
+ * power, and bandwidth by skipping directly to an encrypted stream.
+ * This is a persistent cache which can span executions of the application.
+ *
+ * @see SSLCertificateSocketFactory
+ */
+public final class SSLSessionCache {
+    private static final String TAG = "SSLSessionCache";
+    /* package */ final SSLClientSessionCache mSessionCache;
+
+    /**
+     * Create a session cache using the specified directory.
+     * Individual session entries will be files within the directory.
+     * Multiple instances for the same directory share data internally.
+     *
+     * @param dir to store session files in (created if necessary)
+     * @throws IOException if the cache can't be opened
+     */
+    public SSLSessionCache(File dir) throws IOException {
+        mSessionCache = FileClientSessionCache.usingDirectory(dir);
+    }
+
+    /**
+     * Create a session cache at the default location for this app.
+     * Multiple instances share data internally.
+     *
+     * @param context for the application
+     */
+    public SSLSessionCache(Context context) {
+        File dir = context.getDir("sslcache", Context.MODE_PRIVATE);
+        SSLClientSessionCache cache = null;
+        try {
+            cache = FileClientSessionCache.usingDirectory(dir);
+        } catch (IOException e) {
+            Log.w(TAG, "Unable to create SSL session cache in " + dir, e);
+        }
+        mSessionCache = cache;
+    }
+}
diff --git a/core/java/android/os/ICheckinService.aidl b/core/java/android/os/ICheckinService.aidl
deleted file mode 100644
index e5609b0..0000000
--- a/core/java/android/os/ICheckinService.aidl
+++ /dev/null
@@ -1,41 +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.
- */
-
-package android.os;
-
-import android.os.IParentalControlCallback;
-
-/**
- * System private API for direct access to the checkin service.
- * Users should use the content provider instead.
- *
- * @see android.provider.Checkin
- * {@hide}
- */
-interface ICheckinService {
-    /** Reboot into the recovery system and wipe all user data. */
-    void masterClear();
-
-    /** Reboot into the recovery system, wipe all user data and enable Encrypted File Systems. */
-    void masterClearAndToggleEFS(boolean efsEnabled);
-
-    /**
-     * Determine if the device is under parental control. Return null if
-     * we are unable to check the parental control status.
-     */
-    void getParentalControlState(IParentalControlCallback p,
-                                 String requestingApp);
-}
diff --git a/core/java/android/os/IParentalControlCallback.aidl b/core/java/android/os/IParentalControlCallback.aidl
deleted file mode 100644
index 2f1a563..0000000
--- a/core/java/android/os/IParentalControlCallback.aidl
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-
-package android.os;
-
-import com.google.android.net.ParentalControlState;
-
-/**
- * This callback interface is used to deliver the parental control state to the calling application.
- * {@hide}
- */
-oneway interface IParentalControlCallback {
-	void onResult(in ParentalControlState state);
-}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 699ddb2..4887783 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -504,6 +504,9 @@
             argsForZygote.add("--runtime-init");
             argsForZygote.add("--setuid=" + uid);
             argsForZygote.add("--setgid=" + gid);
+            if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {
+                argsForZygote.add("--enable-safemode");
+            }
             if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {
                 argsForZygote.add("--enable-debugger");
             }
diff --git a/core/java/android/os/storage/IMountService.aidl b/core/java/android/os/storage/IMountService.aidl
index 84e3f58..3d1ef25 100644
--- a/core/java/android/os/storage/IMountService.aidl
+++ b/core/java/android/os/storage/IMountService.aidl
@@ -109,6 +109,11 @@
     int unmountSecureContainer(String id);
 
     /*
+     * Returns true if the specified container is mounted
+     */
+    boolean isSecureContainerMounted(String id);
+
+    /*
      * Rename an unmounted secure container.
      * Returns an int consistent with MountServiceResultCode
      */
diff --git a/core/java/android/os/storage/StorageResultCode.java b/core/java/android/os/storage/StorageResultCode.java
index 584f160..249bacf 100644
--- a/core/java/android/os/storage/StorageResultCode.java
+++ b/core/java/android/os/storage/StorageResultCode.java
@@ -53,8 +53,15 @@
     public static final int OperationFailedMediaCorrupt      = -4;
 
     /**
-     * Operation failed: Media not mounted.
+     * Operation failed: Storage not mounted.
      * @see android.os.storage.StorageManager
      */
-    public static final int OperationFailedVolumeNotMounted  = -5;
+    public static final int OperationFailedStorageNotMounted  = -5;
+
+    /**
+     * Operation failed: Storage is mounted.
+     * @see android.os.storage.StorageManager
+     */
+    public static final int OperationFailedStorageMounted     = -6;
+
 }
diff --git a/core/java/android/pim/vcard/VCardComposer.java b/core/java/android/pim/vcard/VCardComposer.java
index 389c9f4..5e978f6 100644
--- a/core/java/android/pim/vcard/VCardComposer.java
+++ b/core/java/android/pim/vcard/VCardComposer.java
@@ -25,6 +25,7 @@
 import android.database.sqlite.SQLiteException;
 import android.net.Uri;
 import android.os.RemoteException;
+import android.pim.vcard.exception.VCardException;
 import android.provider.CallLog;
 import android.provider.CallLog.Calls;
 import android.provider.ContactsContract.Contacts;
@@ -54,6 +55,7 @@
 import java.io.OutputStreamWriter;
 import java.io.UnsupportedEncodingException;
 import java.io.Writer;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.nio.charset.UnsupportedCharsetException;
 import java.util.ArrayList;
@@ -199,6 +201,10 @@
                 try {
                     // Create one empty entry.
                     mWriter.write(createOneEntryInternal("-1", null));
+                } catch (VCardException e) {
+                    Log.e(LOG_TAG, "VCardException has been thrown during on Init(): " +
+                            e.getMessage());
+                    return false;
                 } catch (IOException e) {
                     Log.e(LOG_TAG,
                             "IOException occurred during exportOneContactData: "
@@ -455,6 +461,9 @@
                     return true;
                 }
             }
+        } catch (VCardException e) {
+            Log.e(LOG_TAG, "VCardException has been thrown: " + e.getMessage());
+            return false;
         } catch (OutOfMemoryError error) {
             // Maybe some data (e.g. photo) is too big to have in memory. But it
             // should be rare.
@@ -486,27 +495,37 @@
     }
 
     private String createOneEntryInternal(final String contactId,
-            Method getEntityIteratorMethod) {
+            Method getEntityIteratorMethod) throws VCardException {
         final Map<String, List<ContentValues>> contentValuesListMap =
                 new HashMap<String, List<ContentValues>>();
         // The resolver may return the entity iterator with no data. It is possiible.
         // e.g. If all the data in the contact of the given contact id are not exportable ones,
         //      they are hidden from the view of this method, though contact id itself exists.
-        boolean dataExists = false;
         EntityIterator entityIterator = null;
         try {
-
             if (getEntityIteratorMethod != null) {
+                final Uri uri = RawContacts.CONTENT_URI.buildUpon()
+                        .appendQueryParameter(Data.FOR_EXPORT_ONLY, "1")
+                        .build();
+                final String selection = Data.CONTACT_ID + "=?";
+                final String[] selectionArgs = new String[] {contactId};
                 try {
-                    final Uri uri = RawContacts.CONTENT_URI.buildUpon()
-                            .appendQueryParameter(Data.FOR_EXPORT_ONLY, "1")
-                            .build();
-                    final String selection = Data.CONTACT_ID + "=?";
-                    final String[] selectionArgs = new String[] {contactId};
                     entityIterator = (EntityIterator)getEntityIteratorMethod.invoke(null,
                             mContentResolver, uri, selection, selectionArgs, null);
-                } catch (Exception e) {
-                    e.printStackTrace();
+                } catch (IllegalArgumentException e) {
+                    Log.e(LOG_TAG, "IllegalArgumentException has been thrown: " +
+                            e.getMessage());
+                } catch (IllegalAccessException e) {
+                    Log.e(LOG_TAG, "IllegalAccessException has been thrown: " +
+                            e.getMessage());
+                } catch (InvocationTargetException e) {
+                    Log.e(LOG_TAG, "InvocationTargetException has been thrown: ");
+                    StackTraceElement[] stackTraceElements = e.getCause().getStackTrace();
+                    for (StackTraceElement element : stackTraceElements) {
+                        Log.e(LOG_TAG, "    at " + element.toString());
+                    }
+                    throw new VCardException("InvocationTargetException has been thrown: " +
+                            e.getCause().getMessage());
                 }
             } else {
                 final Uri uri = RawContacts.CONTENT_URI.buildUpon()
@@ -523,7 +542,11 @@
                 return "";
             }
 
-            dataExists = entityIterator.hasNext();
+            if (!entityIterator.hasNext()) {
+                Log.w(LOG_TAG, "Data does not exist. contactId: " + contactId);
+                return "";
+            }
+
             while (entityIterator.hasNext()) {
                 Entity entity = entityIterator.next();
                 for (NamedContentValues namedContentValues : entity.getSubValues()) {
@@ -550,10 +573,6 @@
             }
         }
 
-        if (!dataExists) {
-            return "";
-        }
-
         final VCardBuilder builder = new VCardBuilder(mVCardType);
         builder.appendNameProperties(contentValuesListMap.get(StructuredName.CONTENT_ITEM_TYPE))
                 .appendNickNames(contentValuesListMap.get(Nickname.CONTENT_ITEM_TYPE))
diff --git a/core/java/android/pim/vcard/VCardEntry.java b/core/java/android/pim/vcard/VCardEntry.java
index 20eee84..1cf3144 100644
--- a/core/java/android/pim/vcard/VCardEntry.java
+++ b/core/java/android/pim/vcard/VCardEntry.java
@@ -281,6 +281,29 @@
                     isPrimary == organization.isPrimary);
         }
 
+        public String getFormattedString() {
+            final StringBuilder builder = new StringBuilder();
+            if (!TextUtils.isEmpty(companyName)) {
+                builder.append(companyName);
+            }
+
+            if (!TextUtils.isEmpty(departmentName)) {
+                if (builder.length() > 0) {
+                    builder.append(", ");
+                }
+                builder.append(departmentName);
+            }
+
+            if (!TextUtils.isEmpty(titleName)) {
+                if (builder.length() > 0) {
+                    builder.append(", ");
+                }
+                builder.append(titleName);
+            }
+
+            return builder.toString();
+        }
+
         @Override
         public String toString() {
             return String.format(
@@ -1008,6 +1031,8 @@
             mDisplayName = mPhoneList.get(0).data;
         } else if (mPostalList != null && mPostalList.size() > 0) {
             mDisplayName = mPostalList.get(0).getFormattedAddress(mVCardType);
+        } else if (mOrganizationList != null && mOrganizationList.size() > 0) {
+            mDisplayName = mOrganizationList.get(0).getFormattedString();
         }
 
         if (mDisplayName == null) {
diff --git a/core/java/android/provider/Browser.java b/core/java/android/provider/Browser.java
index 36255d0..f7c3148 100644
--- a/core/java/android/provider/Browser.java
+++ b/core/java/android/provider/Browser.java
@@ -120,6 +120,15 @@
     private static final int MAX_HISTORY_COUNT = 250;
 
     /**
+     * URI for writing geolocation permissions. This requires the
+     * {@link android.Manifest.permission#WRITE_GEOLOCATION_PERMISSIONS}.
+     */
+    public static final Uri GEOLOCATION_URI =
+            Uri.parse("content://browser/geolocation");
+
+    private static final String GEOLOCATION_WHERE_CLAUSE = GeolocationColumns.ORIGIN + " = ?";
+
+    /**
      *  Open the AddBookmark activity to save a bookmark.  Launch with
      *  and/or url, which can be edited by the user before saving.
      *  @param c        Context used to launch the AddBookmark activity.
@@ -553,6 +562,42 @@
         }
     }
 
+    /**
+     * Allows geolocation for the specified origin.
+     * This requires the {@link android.Manifest.permission#WRITE_GEOLOCATION_PERMISSIONS}
+     * permission.
+     *
+     * @param origin The origin to allow geolocation for, e.g. "http://www.google.com". The string
+     *        should not include a trailing slash.
+     */
+    public static void allowGeolocation(ContentResolver cr, String origin) {
+        try {
+            ContentValues map = new ContentValues();
+            map.put(GeolocationColumns.ORIGIN, origin);
+            cr.insert(GEOLOCATION_URI, map);
+        } catch (IllegalStateException e) {
+            Log.e(LOGTAG, "allowGeolocation", e);
+            return;
+        }
+    }
+
+    /**
+     * Clears the geolocation permission state for the specified origin.
+     * This requires the {@link android.Manifest.permission#WRITE_GEOLOCATION_PERMISSIONS}
+     * permission.
+     *
+     * @param origin The origin to allow geolocation for, e.g. "http://www.google.com". The string
+     *        should not include a trailing slash.
+     */
+    public static void clearGeolocation(ContentResolver cr, String origin) {
+        try {
+            String[] whereArgs = { origin };
+            cr.delete(GEOLOCATION_URI, GEOLOCATION_WHERE_CLAUSE, whereArgs);
+        } catch (IllegalStateException e) {
+            Log.e(LOGTAG, "clearGeolocation", e);
+        }
+    }
+
     public static class BookmarkColumns implements BaseColumns {
         public static final String URL = "url";
         public static final String VISITS = "visits";
@@ -580,4 +625,8 @@
         public static final String SEARCH = "search";
         public static final String DATE = "date";
     }
+
+    public static class GeolocationColumns {
+        public static final String ORIGIN = "origin";
+    }
 }
diff --git a/core/java/android/provider/Checkin.java b/core/java/android/provider/Checkin.java
deleted file mode 100644
index 75936a1..0000000
--- a/core/java/android/provider/Checkin.java
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.provider;
-
-import org.apache.commons.codec.binary.Base64;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.database.SQLException;
-import android.net.Uri;
-import android.os.SystemClock;
-import android.util.Log;
-
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-
-/**
- * Contract class for the checkin provider, used to store events and
- * statistics that will be uploaded to a checkin server eventually.
- * Describes the exposed database schema, and offers methods to add
- * events and statistics to be uploaded.
- *
- * TODO: Move this to vendor/google when we have a home for it.
- *
- * @hide
- */
-public final class Checkin {
-    public static final String AUTHORITY = "android.server.checkin";
-
-    /**
-     * The events table is a log of important timestamped occurrences.
-     * Each event has a type tag and an optional string value.
-     * If too many events are added before they can be reported, the
-     * content provider will erase older events to limit the table size.
-     */
-    public interface Events extends BaseColumns {
-        public static final String TABLE_NAME = "events";
-        public static final Uri CONTENT_URI =
-            Uri.parse("content://" + AUTHORITY + "/" + TABLE_NAME);
-
-        public static final String TAG = "tag";     // TEXT
-        public static final String VALUE = "value"; // TEXT
-        public static final String DATE = "date";   // INTEGER
-
-        /** Valid tag values.  Extend as necessary for your needs. */
-        public enum Tag {
-            APANIC_CONSOLE,
-            APANIC_THREADS,
-            AUTOTEST_FAILURE,
-            AUTOTEST_SEQUENCE_BEGIN,
-            AUTOTEST_SUITE_BEGIN,
-            AUTOTEST_TCPDUMP_BEGIN,
-            AUTOTEST_TCPDUMP_DATA,
-            AUTOTEST_TCPDUMP_END,
-            AUTOTEST_TEST_BEGIN,
-            AUTOTEST_TEST_FAILURE,
-            AUTOTEST_TEST_SUCCESS,
-            BROWSER_BUG_REPORT,
-            CARRIER_BUG_REPORT,
-            CHECKIN_FAILURE,
-            CHECKIN_SUCCESS,
-            FOTA_BEGIN,
-            FOTA_FAILURE,
-            FOTA_INSTALL,
-            FOTA_PROMPT,
-            FOTA_PROMPT_ACCEPT,
-            FOTA_PROMPT_REJECT,
-            FOTA_PROMPT_SKIPPED,
-            GSERVICES_ERROR,
-            GSERVICES_UPDATE,
-            LOGIN_SERVICE_ACCOUNT_TRIED,
-            LOGIN_SERVICE_ACCOUNT_SAVED,
-            LOGIN_SERVICE_AUTHENTICATE,
-            LOGIN_SERVICE_CAPTCHA_ANSWERED,
-            LOGIN_SERVICE_CAPTCHA_SHOWN,
-            LOGIN_SERVICE_PASSWORD_ENTERED,
-            LOGIN_SERVICE_SWITCH_GOOGLE_MAIL,
-            NETWORK_DOWN,
-            NETWORK_UP,
-            PHONE_UI,
-            RADIO_BUG_REPORT,
-            SETUP_COMPLETED,
-            SETUP_INITIATED,
-            SETUP_IO_ERROR,
-            SETUP_NETWORK_ERROR,
-            SETUP_REQUIRED_CAPTCHA,
-            SETUP_RETRIES_EXHAUSTED,
-            SETUP_SERVER_ERROR,
-            SETUP_SERVER_TIMEOUT,
-            SETUP_NO_DATA_NETWORK,
-            SYSTEM_BOOT,
-            SYSTEM_LAST_KMSG,
-            SYSTEM_RECOVERY_LOG,
-            SYSTEM_RESTART,
-            SYSTEM_SERVICE_LOOPING,
-            SYSTEM_TOMBSTONE,
-            TEST, 
-            BATTERY_DISCHARGE_INFO,
-            MARKET_DOWNLOAD,
-            MARKET_INSTALL,
-            MARKET_REMOVE,
-            MARKET_REFUND,
-            MARKET_UNINSTALL,
-        }
-    }
-
-    /**
-     * The stats table is a list of counter values indexed by a tag name.
-     * Each statistic has a count and sum fields, so it can track averages.
-     * When multiple statistics are inserted with the same tag, the count
-     * and sum fields are added together into a single entry in the database.
-     */
-    public interface Stats extends BaseColumns {
-        public static final String TABLE_NAME = "stats";
-        public static final Uri CONTENT_URI =
-            Uri.parse("content://" + AUTHORITY + "/" + TABLE_NAME);
-
-        public static final String TAG = "tag";      // TEXT UNIQUE
-        public static final String COUNT = "count";  // INTEGER
-        public static final String SUM = "sum";      // REAL
-
-        /** Valid tag values.  Extend as necessary for your needs. */
-        public enum Tag {
-            BROWSER_SNAP_CENTER,
-            BROWSER_TEXT_SIZE_CHANGE,
-            BROWSER_ZOOM_OVERVIEW,
-
-            CRASHES_REPORTED,
-            CRASHES_TRUNCATED,
-            ELAPSED_REALTIME_SEC,
-            ELAPSED_UPTIME_SEC,
-            HTTP_REQUEST,
-            HTTP_REUSED,
-            HTTP_STATUS,
-            PHONE_GSM_REGISTERED,
-            PHONE_GPRS_ATTEMPTED,
-            PHONE_GPRS_CONNECTED,
-            PHONE_RADIO_RESETS,
-            TEST,
-            NETWORK_RX_MOBILE,
-            NETWORK_TX_MOBILE,
-            PHONE_CDMA_REGISTERED,
-            PHONE_CDMA_DATA_ATTEMPTED,
-            PHONE_CDMA_DATA_CONNECTED,
-        }
-    }
-
-    /**
-     * The properties table is a set of tagged values sent with every checkin.
-     * Unlike statistics or events, they are not cleared after being uploaded.
-     * Multiple properties inserted with the same tag overwrite each other.
-     */
-    public interface Properties extends BaseColumns {
-        public static final String TABLE_NAME = "properties";
-        public static final Uri CONTENT_URI =
-            Uri.parse("content://" + AUTHORITY + "/" + TABLE_NAME);
-
-        public static final String TAG = "tag";      // TEXT UNIQUE
-        public static final String VALUE = "value";  // TEXT
-
-        /** Valid tag values, to be extended as necessary. */
-        public enum Tag {
-            DESIRED_BUILD,
-            MARKET_CHECKIN,
-        }
-    }
-
-    /**
-     * The crashes table is a log of crash reports, kept separate from the
-     * general event log because crashes are large, important, and bursty.
-     * Like the events table, the crashes table is pruned on insert.
-     */
-    public interface Crashes extends BaseColumns {
-        public static final String TABLE_NAME = "crashes";
-        public static final Uri CONTENT_URI =
-            Uri.parse("content://" + AUTHORITY + "/" + TABLE_NAME);
-
-        // TODO: one or both of these should be a file attachment, not a column
-        public static final String DATA = "data";    // TEXT
-        public static final String LOGS = "logs";    // TEXT
-    }
-
-    /**
-     * Intents with this action cause a checkin attempt.  Normally triggered by
-     * a periodic alarm, these may be sent directly to force immediate checkin.
-     */
-    public interface TriggerIntent {
-        public static final String ACTION = "android.server.checkin.CHECKIN";
-
-        // The category is used for GTalk service messages
-        public static final String CATEGORY = "android.server.checkin.CHECKIN";
-        
-        // If true indicates that the checkin should only transfer market related data
-        public static final String EXTRA_MARKET_ONLY = "market_only";
-    }
-
-    private static final String TAG = "Checkin";
-
-    /**
-     * Helper function to log an event to the database.
-     *
-     * @param resolver from {@link android.content.Context#getContentResolver}
-     * @param tag identifying the type of event being recorded
-     * @param value associated with event, if any
-     * @return URI of the event that was added
-     */
-    static public Uri logEvent(ContentResolver resolver,
-            Events.Tag tag, String value) {
-        try {
-            // Don't specify the date column; the content provider will add that.
-            ContentValues values = new ContentValues();
-            values.put(Events.TAG, tag.toString());
-            if (value != null) values.put(Events.VALUE, value);
-            return resolver.insert(Events.CONTENT_URI, values);
-        } catch (IllegalArgumentException e) {  // thrown when provider is unavailable.
-            Log.w(TAG, "Can't log event " + tag + ": " + e);
-            return null;
-        } catch (SQLException e) {
-            Log.e(TAG, "Can't log event " + tag, e);  // Database errors are not fatal.
-            return null;
-        }
-    }
-
-    /**
-     * Helper function to update statistics in the database.
-     * Note that multiple updates to the same tag will be combined.
-     *
-     * @param tag identifying what is being observed
-     * @param count of occurrences
-     * @param sum of some value over these occurrences
-     * @return URI of the statistic that was returned
-     */
-    static public Uri updateStats(ContentResolver resolver,
-            Stats.Tag tag, int count, double sum) {
-        try {
-            ContentValues values = new ContentValues();
-            values.put(Stats.TAG, tag.toString());
-            if (count != 0) values.put(Stats.COUNT, count);
-            if (sum != 0.0) values.put(Stats.SUM, sum);
-            return resolver.insert(Stats.CONTENT_URI, values);
-        } catch (IllegalArgumentException e) {  // thrown when provider is unavailable.
-            Log.w(TAG, "Can't update stat " + tag + ": " + e);
-            return null;
-        } catch (SQLException e) {
-            Log.e(TAG, "Can't update stat " + tag, e);  // Database errors are not fatal.
-            return null;
-        }
-    }
-
-    /** Minimum time to wait after a crash failure before trying again. */
-    static private final long MIN_CRASH_FAILURE_RETRY = 10000;  // 10 seconds
-
-    /** {@link SystemClock#elapsedRealtime} of the last time a crash report failed. */
-    static private volatile long sLastCrashFailureRealtime = -MIN_CRASH_FAILURE_RETRY;
-}
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 211bc0a..74a03da 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -383,10 +383,10 @@
                     if (isVideo) {
                         bitmap = ThumbnailUtils.createVideoThumbnail(filePath);
                         if (kind == MICRO_KIND && bitmap != null) {
-                            bitmap = ThumbnailUtils.extractMiniThumb(bitmap,
-                                    ThumbnailUtils.MINI_THUMB_TARGET_SIZE,
-                                    ThumbnailUtils.MINI_THUMB_TARGET_SIZE,
-                                    ThumbnailUtils.RECYCLE_INPUT);
+                            bitmap = ThumbnailUtils.extractThumbnail(bitmap,
+                                    ThumbnailUtils.TARGET_SIZE_MICRO_THUMBNAIL,
+                                    ThumbnailUtils.TARGET_SIZE_MICRO_THUMBNAIL,
+                                    ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
                         }
                     } else {
                         bitmap = ThumbnailUtils.createImageThumbnail(cr, filePath, uri, origId,
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index bacaf43..7b52f7f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -22,6 +22,7 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.content.ComponentName;
 import android.content.ContentQueryMap;
 import android.content.ContentResolver;
 import android.content.ContentValues;
@@ -1473,6 +1474,89 @@
         public static final String NOTIFICATION_LIGHT_PULSE = "notification_light_pulse";
 
         /**
+         * Let user pick default install location.
+         * @hide
+         */
+        public static final String SET_INSTALL_LOCATION = "set_install_location";
+
+        /**
+         * Default install location value.
+         * 0 = auto, let system decide
+         * 1 = internal
+         * 2 = sdcard
+         * @hide
+         */
+        public static final String DEFAULT_INSTALL_LOCATION = "default_install_location";
+
+        /**
+         * Show pointer location on screen?
+         * 0 = no
+         * 1 = yes
+         * @hide
+         */
+        public static final String POINTER_LOCATION = "pointer_location";
+
+        /**
+         * Whether to play a sound for low-battery alerts.
+         * @hide
+         */
+        public static final String POWER_SOUNDS_ENABLED = "power_sounds_enabled";
+
+        /**
+         * Whether to play a sound for dock events.
+         * @hide
+         */
+        public static final String DOCK_SOUNDS_ENABLED = "dock_sounds_enabled";
+
+        /**
+         * Whether to play sounds when the keyguard is shown and dismissed.
+         * @hide
+         */
+        public static final String LOCKSCREEN_SOUNDS_ENABLED = "lockscreen_sounds_enabled";
+
+        /**
+         * URI for the low battery sound file.
+         * @hide
+         */
+        public static final String LOW_BATTERY_SOUND = "low_battery_sound";
+
+        /**
+         * URI for the desk dock "in" event sound.
+         * @hide
+         */
+        public static final String DESK_DOCK_SOUND = "desk_dock_sound";
+
+        /**
+         * URI for the desk dock "out" event sound.
+         * @hide
+         */
+        public static final String DESK_UNDOCK_SOUND = "desk_undock_sound";
+
+        /**
+         * URI for the car dock "in" event sound.
+         * @hide
+         */
+        public static final String CAR_DOCK_SOUND = "car_dock_sound";
+
+        /**
+         * URI for the car dock "out" event sound.
+         * @hide
+         */
+        public static final String CAR_UNDOCK_SOUND = "car_undock_sound";
+
+        /**
+         * URI for the "device locked" (keyguard shown) sound.
+         * @hide
+         */
+        public static final String LOCK_SOUND = "lock_sound";
+
+        /**
+         * URI for the "device unlocked" (keyguard dismissed) sound.
+         * @hide
+         */
+        public static final String UNLOCK_SOUND = "unlock_sound";
+
+        /**
          * Settings to backup. This is here so that it's in the same place as the settings
          * keys and easy to update.
          * @hide
@@ -2126,14 +2210,17 @@
         public static final String NETWORK_PREFERENCE = "network_preference";
 
         /**
+         * No longer supported.
          */
         public static final String PARENTAL_CONTROL_ENABLED = "parental_control_enabled";
 
         /**
+         * No longer supported.
          */
         public static final String PARENTAL_CONTROL_LAST_UPDATE = "parental_control_last_update";
 
         /**
+         * No longer supported.
          */
         public static final String PARENTAL_CONTROL_REDIRECT_URL = "parental_control_redirect_url";
 
@@ -2799,22 +2886,6 @@
                 "sms_outgoing_check_max_count";
 
         /**
-         * Enable use of ssl session caching.
-         * 'db' - save each session in a (per process) database
-         * 'file' - save each session in a (per process) file
-         * not set or any other value - normal java in-memory caching
-         * @hide
-         */
-        public static final String SSL_SESSION_CACHE = "ssl_session_cache";
-
-        /**
-         * How many bytes long a message has to be, in order to be gzipped.
-         * @hide
-         */
-        public static final String SYNC_MIN_GZIP_BYTES =
-                "sync_min_gzip_bytes";
-
-        /**
          * The number of promoted sources in GlobalSearch.
          * @hide
          */
@@ -2956,6 +3027,14 @@
          * @hide
          */
         public static final String ANR_SHOW_BACKGROUND = "anr_show_background";
+        
+        /**
+         * The {@link ComponentName} string of the service to be used as the voice recognition
+         * service.
+         * 
+         * @hide
+         */
+        public static final String VOICE_RECOGNITION_SERVICE = "voice_recognition_service";
 
         /**
          * @hide
diff --git a/core/java/android/speech/RecognitionListener.java b/core/java/android/speech/RecognitionListener.java
index 5434887..2f5bcc3 100644
--- a/core/java/android/speech/RecognitionListener.java
+++ b/core/java/android/speech/RecognitionListener.java
@@ -79,7 +79,8 @@
      * time between {@link #onBeginningOfSpeech()} and {@link #onResults(Bundle)} when partial
      * results are ready. This method may be called zero, one or multiple times for each call to
      * {@link RecognitionManager#startListening(Intent)}, depending on the speech recognition
-     * service implementation.
+     * service implementation.  To request partial results, use
+     * {@link RecognizerIntent#EXTRA_PARTIAL_RESULTS}
      * 
      * @param partialResults the returned results. To retrieve the results in
      *        ArrayList&lt;String&gt; format use {@link Bundle#getStringArrayList(String)} with
diff --git a/core/java/android/speech/RecognitionManager.java b/core/java/android/speech/RecognitionManager.java
index 7915208..7f55ad6 100644
--- a/core/java/android/speech/RecognitionManager.java
+++ b/core/java/android/speech/RecognitionManager.java
@@ -27,6 +27,8 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
+import android.provider.Settings;
+import android.text.TextUtils;
 import android.util.Log;
 
 import java.util.LinkedList;
@@ -169,7 +171,7 @@
      */
     public static boolean isRecognitionAvailable(final Context context) {
         final List<ResolveInfo> list = context.getPackageManager().queryIntentServices(
-                new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);
+                new Intent(RecognitionService.SERVICE_INTERFACE), 0);
         return list != null && list.size() != 0;
     }
 
@@ -218,8 +220,20 @@
         checkIsCalledFromMainThread();
         if (mConnection == null) { // first time connection
             mConnection = new Connection();
-            if (!mContext.bindService(new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH),
-                    mConnection, Context.BIND_AUTO_CREATE)) {
+            
+            Intent serviceIntent = new Intent(RecognitionService.SERVICE_INTERFACE);
+            String serviceComponent = Settings.Secure.getString(mContext.getContentResolver(),
+                    Settings.Secure.VOICE_RECOGNITION_SERVICE);
+            
+            if (TextUtils.isEmpty(serviceComponent)) {
+                Log.e(TAG, "no selected voice recognition service");
+                mListener.onError(ERROR_CLIENT);
+                return;
+            }
+            
+            serviceIntent.setComponent(ComponentName.unflattenFromString(serviceComponent));
+            
+            if (!mContext.bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE)) {
                 Log.e(TAG, "bind to recognition service failed");
                 mConnection = null;
                 mService = null;
diff --git a/core/java/android/speech/RecognitionService.java b/core/java/android/speech/RecognitionService.java
index 0d74960..941b70c 100644
--- a/core/java/android/speech/RecognitionService.java
+++ b/core/java/android/speech/RecognitionService.java
@@ -16,6 +16,8 @@
 
 package android.speech;
 
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
 import android.app.Service;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -28,10 +30,22 @@
 
 /**
  * This class provides a base class for recognition service implementations. This class should be
- * extended only in case you wish to implement a new speech recognizer. Please not that the
- * implementation of this service is state-less.
+ * extended only in case you wish to implement a new speech recognizer. Please note that the
+ * implementation of this service is stateless.
  */
 public abstract class RecognitionService extends Service {
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     */
+    @SdkConstant(SdkConstantType.SERVICE_ACTION)
+    public static final String SERVICE_INTERFACE = "android.speech.RecognitionService";
+    
+    /**
+     * Name under which a RecognitionService component publishes information about itself.
+     * This meta-data should reference an XML resource containing a
+     * <code>&lt;{@link android.R.styleable#RecognitionService recognition-service}&gt;</code> tag.
+     */
+    public static final String SERVICE_META_DATA = "android.speech";
 
     /** Log messages identifier */
     private static final String TAG = "RecognitionService";
diff --git a/core/java/android/speech/RecognizerIntent.java b/core/java/android/speech/RecognizerIntent.java
index 334b049..241a8b0 100644
--- a/core/java/android/speech/RecognizerIntent.java
+++ b/core/java/android/speech/RecognizerIntent.java
@@ -77,6 +77,7 @@
      *   <li>{@link #EXTRA_PROMPT}
      *   <li>{@link #EXTRA_LANGUAGE}
      *   <li>{@link #EXTRA_MAX_RESULTS}
+     *   <li>{@link #EXTRA_PARTIAL_RESULTS}
      * </ul>
      * 
      * <p> Result extras (returned in the result, not to be specified in the request):
@@ -166,6 +167,13 @@
     public static final String EXTRA_MAX_RESULTS = "android.speech.extra.MAX_RESULTS";
 
     /**
+     * Optional boolean to indicate whether partial results should be returned by the recognizer
+     * as the user speaks (default is false).  The server may ignore a request for partial
+     * results in some or all cases.
+     */
+    public static final String EXTRA_PARTIAL_RESULTS = "android.speech.extra.PARTIAL_RESULTS";
+
+    /**
      * When the intent is {@link #ACTION_RECOGNIZE_SPEECH}, the speech input activity will
      * return results to you via the activity results mechanism.  Alternatively, if you use this
      * extra to supply a PendingIntent, the results will be added to its bundle and the 
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index bbbeb3f..0db2198 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -256,6 +256,31 @@
          * the TextToSpeech engine specifies the locale associated with each resource file.
          */
         public static final String EXTRA_VOICE_DATA_FILES_INFO = "dataFilesInfo";
+        /**
+         * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where
+         * the TextToSpeech engine returns an ArrayList<String> of all the available voices.
+         * The format of each voice is: lang-COUNTRY-variant where COUNTRY and variant are
+         * optional (ie, "eng" or "eng-USA" or "eng-USA-FEMALE").
+         * {@hide}
+         */
+        public static final String EXTRA_AVAILABLE_VOICES = "availableVoices";
+        /**
+         * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where
+         * the TextToSpeech engine returns an ArrayList<String> of all the unavailable voices.
+         * The format of each voice is: lang-COUNTRY-variant where COUNTRY and variant are
+         * optional (ie, "eng" or "eng-USA" or "eng-USA-FEMALE").
+         * {@hide}
+         */
+        public static final String EXTRA_UNAVAILABLE_VOICES = "unavailableVoices";
+        /**
+         * Extra information sent with the {@link #ACTION_CHECK_TTS_DATA} intent where the
+         * caller indicates to the TextToSpeech engine which specific sets of voice data to
+         * check for by sending an ArrayList<String> of the voices that are of interest.
+         * The format of each voice is: lang-COUNTRY-variant where COUNTRY and variant are
+         * optional (ie, "eng" or "eng-USA" or "eng-USA-FEMALE").
+         * {@hide}
+         */
+        public static final String EXTRA_CHECK_VOICE_DATA_FOR = "checkVoiceDataFor";
 
         // extras for a TTS engine's data installation
         /**
diff --git a/core/java/android/util/base64/Base64.java b/core/java/android/util/base64/Base64.java
new file mode 100644
index 0000000..f6d3905
--- /dev/null
+++ b/core/java/android/util/base64/Base64.java
@@ -0,0 +1,741 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util.base64;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Utilities for encoding and decoding the Base64 representation of
+ * binary data.  See RFCs <a
+ * href="http://www.ietf.org/rfc/rfc2045.txt">2045</a> and <a
+ * href="http://www.ietf.org/rfc/rfc3548.txt">3548</a>.
+ */
+public class Base64 {
+    /**
+     * Default values for encoder/decoder flags.
+     */
+    public static final int DEFAULT = 0;
+
+    /**
+     * Encoder flag bit to omit the padding '=' characters at the end
+     * of the output (if any).
+     */
+    public static final int NO_PADDING = 1;
+
+    /**
+     * Encoder flag bit to omit all line terminators (i.e., the output
+     * will be on one long line).
+     */
+    public static final int NO_WRAP = 2;
+
+    /**
+     * Encoder flag bit to indicate lines should be terminated with a
+     * CRLF pair instead of just an LF.  Has no effect if {@code
+     * NO_WRAP} is specified as well.
+     */
+    public static final int CRLF = 4;
+
+    /**
+     * Encoder/decoder flag bit to indicate using the "URL and
+     * filename safe" variant of Base64 (see RFC 3548 section 4) where
+     * {@code -} and {@code _} are used in place of {@code +} and
+     * {@code /}.
+     */
+    public static final int URL_SAFE = 8;
+
+    /**
+     * Flag to pass to {@link Base64OutputStream} to indicate that it
+     * should not close the output stream it is wrapping when it
+     * itself is closed.
+     */
+    public static final int NO_CLOSE = 16;
+
+    //  --------------------------------------------------------
+    //  shared code
+    //  --------------------------------------------------------
+
+    /* package */ static abstract class Coder {
+        public byte[] output;
+        public int op;
+
+        /**
+         * Encode/decode another block of input data.  this.output is
+         * provided by the caller, and must be big enough to hold all
+         * the coded data.  On exit, this.opwill be set to the length
+         * of the coded data.
+         *
+         * @param finish true if this is the final call to process for
+         *        this object.  Will finalize the coder state and
+         *        include any final bytes in the output.
+         *
+         * @return true if the input so far is good; false if some
+         *         error has been detected in the input stream..
+         */
+        public abstract boolean process(byte[] input, int offset, int len, boolean finish);
+
+        /**
+         * @return the maximum number of bytes a call to process()
+         * could produce for the given number of input bytes.  This may
+         * be an overestimate.
+         */
+        public abstract int maxOutputSize(int len);
+    }
+
+    //  --------------------------------------------------------
+    //  decoding
+    //  --------------------------------------------------------
+
+    /**
+     * Decode the Base64-encoded data in input and return the data in
+     * a new byte array.
+     *
+     * <p>The padding '=' characters at the end are considered optional, but
+     * if any are present, there must be the correct number of them.
+     *
+     * @param str    the input String to decode, which is converted to
+     *               bytes using the default charset
+     * @param flags  controls certain features of the decoded output.
+     *               Pass {@code DEFAULT} to decode standard Base64.
+     *
+     * @throws IllegalArgumentException if the input contains
+     * incorrect padding
+     */
+    public static byte[] decode(String str, int flags) {
+        return decode(str.getBytes(), flags);
+    }
+
+    /**
+     * Decode the Base64-encoded data in input and return the data in
+     * a new byte array.
+     *
+     * <p>The padding '=' characters at the end are considered optional, but
+     * if any are present, there must be the correct number of them.
+     *
+     * @param input the input array to decode
+     * @param flags  controls certain features of the decoded output.
+     *               Pass {@code DEFAULT} to decode standard Base64.
+     *
+     * @throws IllegalArgumentException if the input contains
+     * incorrect padding
+     */
+    public static byte[] decode(byte[] input, int flags) {
+        return decode(input, 0, input.length, flags);
+    }
+
+    /**
+     * Decode the Base64-encoded data in input and return the data in
+     * a new byte array.
+     *
+     * <p>The padding '=' characters at the end are considered optional, but
+     * if any are present, there must be the correct number of them.
+     *
+     * @param input  the data to decode
+     * @param offset the position within the input array at which to start
+     * @param len    the number of bytes of input to decode
+     * @param flags  controls certain features of the decoded output.
+     *               Pass {@code DEFAULT} to decode standard Base64.
+     *
+     * @throws IllegalArgumentException if the input contains
+     * incorrect padding
+     */
+    public static byte[] decode(byte[] input, int offset, int len, int flags) {
+        // Allocate space for the most data the input could represent.
+        // (It could contain less if it contains whitespace, etc.)
+        Decoder decoder = new Decoder(flags, new byte[len*3/4]);
+
+        if (!decoder.process(input, offset, len, true)) {
+            throw new IllegalArgumentException("bad base-64");
+        }
+
+        // Maybe we got lucky and allocated exactly enough output space.
+        if (decoder.op == decoder.output.length) {
+            return decoder.output;
+        }
+
+        // Need to shorten the array, so allocate a new one of the
+        // right size and copy.
+        byte[] temp = new byte[decoder.op];
+        System.arraycopy(decoder.output, 0, temp, 0, decoder.op);
+        return temp;
+    }
+
+    /* package */ static class Decoder extends Coder {
+        /**
+         * Lookup table for turning bytes into their position in the
+         * Base64 alphabet.
+         */
+        private static final int DECODE[] = {
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
+            52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
+            -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
+            15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
+            -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+            41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        };
+
+        /**
+         * Decode lookup table for the "web safe" variant (RFC 3548
+         * sec. 4) where - and _ replace + and /.
+         */
+        private static final int DECODE_WEBSAFE[] = {
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1,
+            52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
+            -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
+            15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63,
+            -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+            41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        };
+
+        /** Non-data values in the DECODE arrays. */
+        private static final int SKIP = -1;
+        private static final int EQUALS = -2;
+
+        /**
+         * States 0-3 are reading through the next input tuple.
+         * State 4 is having read one '=' and expecting exactly
+         * one more.
+         * State 5 is expecting no more data or padding characters
+         * in the input.
+         * State 6 is the error state; an error has been detected
+         * in the input and no future input can "fix" it.
+         */
+        private int state;   // state number (0 to 6)
+        private int value;
+
+        final private int[] alphabet;
+
+        public Decoder(int flags, byte[] output) {
+            this.output = output;
+
+            alphabet = ((flags & URL_SAFE) == 0) ? DECODE : DECODE_WEBSAFE;
+            state = 0;
+            value = 0;
+        }
+
+        /**
+         * @return an overestimate for the number of bytes {@code
+         * len} bytes could decode to.
+         */
+        public int maxOutputSize(int len) {
+            return len * 3/4 + 10;
+        }
+
+        /**
+         * Decode another block of input data.
+         *
+         * @return true if the state machine is still healthy.  false if
+         *         bad base-64 data has been detected in the input stream.
+         */
+        public boolean process(byte[] input, int offset, int len, boolean finish) {
+            if (this.state == 6) return false;
+
+            int p = offset;
+            len += offset;
+
+            // Using local variables makes the decoder about 12%
+            // faster than if we manipulate the member variables in
+            // the loop.  (Even alphabet makes a measurable
+            // difference, which is somewhat surprising to me since
+            // the member variable is final.)
+            int state = this.state;
+            int value = this.value;
+            int op = 0;
+            final byte[] output = this.output;
+            final int[] alphabet = this.alphabet;
+
+            while (p < len) {
+                // Try the fast path:  we're starting a new tuple and the
+                // next four bytes of the input stream are all data
+                // bytes.  This corresponds to going through states
+                // 0-1-2-3-0.  We expect to use this method for most of
+                // the data.
+                //
+                // If any of the next four bytes of input are non-data
+                // (whitespace, etc.), value will end up negative.  (All
+                // the non-data values in decode are small negative
+                // numbers, so shifting any of them up and or'ing them
+                // together will result in a value with its top bit set.)
+                //
+                // You can remove this whole block and the output should
+                // be the same, just slower.
+                if (state == 0) {
+                    while (p+4 <= len &&
+                           (value = ((alphabet[input[p] & 0xff] << 18) |
+                                     (alphabet[input[p+1] & 0xff] << 12) |
+                                     (alphabet[input[p+2] & 0xff] << 6) |
+                                     (alphabet[input[p+3] & 0xff]))) >= 0) {
+                        output[op+2] = (byte) value;
+                        output[op+1] = (byte) (value >> 8);
+                        output[op] = (byte) (value >> 16);
+                        op += 3;
+                        p += 4;
+                    }
+                    if (p >= len) break;
+                }
+
+                // The fast path isn't available -- either we've read a
+                // partial tuple, or the next four input bytes aren't all
+                // data, or whatever.  Fall back to the slower state
+                // machine implementation.
+
+                int d = alphabet[input[p++] & 0xff];
+
+                switch (state) {
+                case 0:
+                    if (d >= 0) {
+                        value = d;
+                        ++state;
+                    } else if (d != SKIP) {
+                        this.state = 6;
+                        return false;
+                    }
+                    break;
+
+                case 1:
+                    if (d >= 0) {
+                        value = (value << 6) | d;
+                        ++state;
+                    } else if (d != SKIP) {
+                        this.state = 6;
+                        return false;
+                    }
+                    break;
+
+                case 2:
+                    if (d >= 0) {
+                        value = (value << 6) | d;
+                        ++state;
+                    } else if (d == EQUALS) {
+                        // Emit the last (partial) output tuple;
+                        // expect exactly one more padding character.
+                        output[op++] = (byte) (value >> 4);
+                        state = 4;
+                    } else if (d != SKIP) {
+                        this.state = 6;
+                        return false;
+                    }
+                    break;
+
+                case 3:
+                    if (d >= 0) {
+                        // Emit the output triple and return to state 0.
+                        value = (value << 6) | d;
+                        output[op+2] = (byte) value;
+                        output[op+1] = (byte) (value >> 8);
+                        output[op] = (byte) (value >> 16);
+                        op += 3;
+                        state = 0;
+                    } else if (d == EQUALS) {
+                        // Emit the last (partial) output tuple;
+                        // expect no further data or padding characters.
+                        output[op+1] = (byte) (value >> 2);
+                        output[op] = (byte) (value >> 10);
+                        op += 2;
+                        state = 5;
+                    } else if (d != SKIP) {
+                        this.state = 6;
+                        return false;
+                    }
+                    break;
+
+                case 4:
+                    if (d == EQUALS) {
+                        ++state;
+                    } else if (d != SKIP) {
+                        this.state = 6;
+                        return false;
+                    }
+                    break;
+
+                case 5:
+                    if (d != SKIP) {
+                        this.state = 6;
+                        return false;
+                    }
+                    break;
+                }
+            }
+
+            if (!finish) {
+                // We're out of input, but a future call could provide
+                // more.
+                this.state = state;
+                this.value = value;
+                this.op = op;
+                return true;
+            }
+
+            // Done reading input.  Now figure out where we are left in
+            // the state machine and finish up.
+
+            switch (state) {
+            case 0:
+                // Output length is a multiple of three.  Fine.
+                break;
+            case 1:
+                // Read one extra input byte, which isn't enough to
+                // make another output byte.  Illegal.
+                this.state = 6;
+                return false;
+            case 2:
+                // Read two extra input bytes, enough to emit 1 more
+                // output byte.  Fine.
+                output[op++] = (byte) (value >> 4);
+                break;
+            case 3:
+                // Read three extra input bytes, enough to emit 2 more
+                // output bytes.  Fine.
+                output[op++] = (byte) (value >> 10);
+                output[op++] = (byte) (value >> 2);
+                break;
+            case 4:
+                // Read one padding '=' when we expected 2.  Illegal.
+                this.state = 6;
+                return false;
+            case 5:
+                // Read all the padding '='s we expected and no more.
+                // Fine.
+                break;
+            }
+
+            this.state = state;
+            this.op = op;
+            return true;
+        }
+    }
+
+    //  --------------------------------------------------------
+    //  encoding
+    //  --------------------------------------------------------
+
+    /**
+     * Base64-encode the given data and return a newly allocated
+     * String with the result.
+     *
+     * @param input  the data to encode
+     * @param flags  controls certain features of the encoded output.
+     *               Passing {@code DEFAULT} results in output that
+     *               adheres to RFC 2045.
+     */
+    public static String encodeToString(byte[] input, int flags) {
+        try {
+            return new String(encode(input, flags), "US-ASCII");
+        } catch (UnsupportedEncodingException e) {
+            // US-ASCII is guaranteed to be available.
+            throw new AssertionError(e);
+        }
+    }
+
+    /**
+     * Base64-encode the given data and return a newly allocated
+     * String with the result.
+     *
+     * @param input  the data to encode
+     * @param offset the position within the input array at which to
+     *               start
+     * @param len    the number of bytes of input to encode
+     * @param flags  controls certain features of the encoded output.
+     *               Passing {@code DEFAULT} results in output that
+     *               adheres to RFC 2045.
+     */
+    public static String encodeToString(byte[] input, int offset, int len, int flags) {
+        try {
+            return new String(encode(input, offset, len, flags), "US-ASCII");
+        } catch (UnsupportedEncodingException e) {
+            // US-ASCII is guaranteed to be available.
+            throw new AssertionError(e);
+        }
+    }
+
+    /**
+     * Base64-encode the given data and return a newly allocated
+     * byte[] with the result.
+     *
+     * @param input  the data to encode
+     * @param flags  controls certain features of the encoded output.
+     *               Passing {@code DEFAULT} results in output that
+     *               adheres to RFC 2045.
+     */
+    public static byte[] encode(byte[] input, int flags) {
+        return encode(input, 0, input.length, flags);
+    }
+
+    /**
+     * Base64-encode the given data and return a newly allocated
+     * byte[] with the result.
+     *
+     * @param input  the data to encode
+     * @param offset the position within the input array at which to
+     *               start
+     * @param len    the number of bytes of input to encode
+     * @param flags  controls certain features of the encoded output.
+     *               Passing {@code DEFAULT} results in output that
+     *               adheres to RFC 2045.
+     */
+    public static byte[] encode(byte[] input, int offset, int len, int flags) {
+        Encoder encoder = new Encoder(flags, null);
+
+        // Compute the exact length of the array we will produce.
+        int output_len = len / 3 * 4;
+
+        // Account for the tail of the data and the padding bytes, if any.
+        if (encoder.do_padding) {
+            if (len % 3 > 0) {
+                output_len += 4;
+            }
+        } else {
+            switch (len % 3) {
+                case 0: break;
+                case 1: output_len += 2; break;
+                case 2: output_len += 3; break;
+            }
+        }
+
+        // Account for the newlines, if any.
+        if (encoder.do_newline && len > 0) {
+            output_len += (((len-1) / (3 * Encoder.LINE_GROUPS)) + 1) *
+                (encoder.do_cr ? 2 : 1);
+        }
+
+        encoder.output = new byte[output_len];
+        encoder.process(input, offset, len, true);
+
+        assert encoder.op == output_len;
+
+        return encoder.output;
+    }
+
+    /* package */ static class Encoder extends Coder {
+        /**
+         * Emit a new line every this many output tuples.  Corresponds to
+         * a 76-character line length (the maximum allowable according to
+         * <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>).
+         */
+        public static final int LINE_GROUPS = 19;
+
+        /**
+         * Lookup table for turning Base64 alphabet positions (6 bits)
+         * into output bytes.
+         */
+        private static final byte ENCODE[] = {
+            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+            'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+            'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+            'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/',
+        };
+
+        /**
+         * Lookup table for turning Base64 alphabet positions (6 bits)
+         * into output bytes.
+         */
+        private static final byte ENCODE_WEBSAFE[] = {
+            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+            'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+            'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+            'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_',
+        };
+
+        final private byte[] tail;
+        /* package */ int tailLen;
+        private int count;
+
+        final public boolean do_padding;
+        final public boolean do_newline;
+        final public boolean do_cr;
+        final private byte[] alphabet;
+
+        public Encoder(int flags, byte[] output) {
+            this.output = output;
+
+            do_padding = (flags & NO_PADDING) == 0;
+            do_newline = (flags & NO_WRAP) == 0;
+            do_cr = (flags & CRLF) != 0;
+            alphabet = ((flags & URL_SAFE) == 0) ? ENCODE : ENCODE_WEBSAFE;
+
+            tail = new byte[2];
+            tailLen = 0;
+
+            count = do_newline ? LINE_GROUPS : -1;
+        }
+
+        /**
+         * @return an overestimate for the number of bytes {@code
+         * len} bytes could encode to.
+         */
+        public int maxOutputSize(int len) {
+            return len * 8/5 + 10;
+        }
+
+        public boolean process(byte[] input, int offset, int len, boolean finish) {
+            // Using local variables makes the encoder about 9% faster.
+            final byte[] alphabet = this.alphabet;
+            final byte[] output = this.output;
+            int op = 0;
+            int count = this.count;
+
+            int p = offset;
+            len += offset;
+            int v = -1;
+
+            // First we need to concatenate the tail of the previous call
+            // with any input bytes available now and see if we can empty
+            // the tail.
+
+            switch (tailLen) {
+                case 0:
+                    // There was no tail.
+                    break;
+
+                case 1:
+                    if (p+2 <= len) {
+                        // A 1-byte tail with at least 2 bytes of
+                        // input available now.
+                        v = ((tail[0] & 0xff) << 16) |
+                            ((input[p++] & 0xff) << 8) |
+                            (input[p++] & 0xff);
+                        tailLen = 0;
+                    };
+                    break;
+
+                case 2:
+                    if (p+1 <= len) {
+                        // A 2-byte tail with at least 1 byte of input.
+                        v = ((tail[0] & 0xff) << 16) |
+                            ((tail[1] & 0xff) << 8) |
+                            (input[p++] & 0xff);
+                        tailLen = 0;
+                    }
+                    break;
+            }
+
+            if (v != -1) {
+                output[op++] = alphabet[(v >> 18) & 0x3f];
+                output[op++] = alphabet[(v >> 12) & 0x3f];
+                output[op++] = alphabet[(v >> 6) & 0x3f];
+                output[op++] = alphabet[v & 0x3f];
+                if (--count == 0) {
+                    if (do_cr) output[op++] = '\r';
+                    output[op++] = '\n';
+                    count = LINE_GROUPS;
+                }
+            }
+
+            // At this point either there is no tail, or there are fewer
+            // than 3 bytes of input available.
+
+            // The main loop, turning 3 input bytes into 4 output bytes on
+            // each iteration.
+            while (p+3 <= len) {
+                v = ((input[p] & 0xff) << 16) |
+                    ((input[p+1] & 0xff) << 8) |
+                    (input[p+2] & 0xff);
+                output[op] = alphabet[(v >> 18) & 0x3f];
+                output[op+1] = alphabet[(v >> 12) & 0x3f];
+                output[op+2] = alphabet[(v >> 6) & 0x3f];
+                output[op+3] = alphabet[v & 0x3f];
+                p += 3;
+                op += 4;
+                if (--count == 0) {
+                    if (do_cr) output[op++] = '\r';
+                    output[op++] = '\n';
+                    count = LINE_GROUPS;
+                }
+            }
+
+            if (finish) {
+                // Finish up the tail of the input.  Note that we need to
+                // consume any bytes in tail before any bytes
+                // remaining in input; there should be at most two bytes
+                // total.
+
+                if (p-tailLen == len-1) {
+                    int t = 0;
+                    v = ((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 4;
+                    tailLen -= t;
+                    output[op++] = alphabet[(v >> 6) & 0x3f];
+                    output[op++] = alphabet[v & 0x3f];
+                    if (do_padding) {
+                        output[op++] = '=';
+                        output[op++] = '=';
+                    }
+                    if (do_newline) {
+                        if (do_cr) output[op++] = '\r';
+                        output[op++] = '\n';
+                    }
+                } else if (p-tailLen == len-2) {
+                    int t = 0;
+                    v = (((tailLen > 1 ? tail[t++] : input[p++]) & 0xff) << 10) |
+                        (((tailLen > 0 ? tail[t++] : input[p++]) & 0xff) << 2);
+                    tailLen -= t;
+                    output[op++] = alphabet[(v >> 12) & 0x3f];
+                    output[op++] = alphabet[(v >> 6) & 0x3f];
+                    output[op++] = alphabet[v & 0x3f];
+                    if (do_padding) {
+                        output[op++] = '=';
+                    }
+                    if (do_newline) {
+                        if (do_cr) output[op++] = '\r';
+                        output[op++] = '\n';
+                    }
+                } else if (do_newline && op > 0 && count != LINE_GROUPS) {
+                    if (do_cr) output[op++] = '\r';
+                    output[op++] = '\n';
+                }
+
+                assert tailLen == 0;
+                assert p == len;
+            } else {
+                // Save the leftovers in tail to be consumed on the next
+                // call to encodeInternal.
+
+                if (p == len-1) {
+                    tail[tailLen++] = input[p];
+                } else if (p == len-2) {
+                    tail[tailLen++] = input[p];
+                    tail[tailLen++] = input[p+1];
+                }
+            }
+
+            this.op = op;
+            this.count = count;
+
+            return true;
+        }
+    }
+
+    private Base64() { }   // don't instantiate
+}
diff --git a/core/java/android/util/base64/Base64InputStream.java b/core/java/android/util/base64/Base64InputStream.java
new file mode 100644
index 0000000..935939e
--- /dev/null
+++ b/core/java/android/util/base64/Base64InputStream.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util.base64;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * An InputStream that does Base64 decoding on the data read through
+ * it.
+ */
+public class Base64InputStream extends FilterInputStream {
+    private final Base64.Coder coder;
+
+    private static byte[] EMPTY = new byte[0];
+
+    private static final int BUFFER_SIZE = 2048;
+    private boolean eof;
+    private byte[] inputBuffer;
+    private int outputStart;
+    private int outputEnd;
+
+    /**
+     * An InputStream that performs Base64 decoding on the data read
+     * from the wrapped stream.
+     *
+     * @param in the InputStream to read the source data from
+     * @param flags bit flags for controlling the decoder; see the
+     *        constants in {@link Base64}
+     */
+    public Base64InputStream(InputStream in, int flags) {
+        this(in, flags, false);
+    }
+
+    /**
+     * Performs Base64 encoding or decoding on the data read from the
+     * wrapped InputStream.
+     *
+     * @param in the InputStream to read the source data from
+     * @param flags bit flags for controlling the decoder; see the
+     *        constants in {@link Base64}
+     * @param encode true to encode, false to decode
+     *
+     * @hide
+     */
+    public Base64InputStream(InputStream in, int flags, boolean encode) {
+        super(in);
+        eof = false;
+        inputBuffer = new byte[BUFFER_SIZE];
+        if (encode) {
+            coder = new Base64.Encoder(flags, null);
+        } else {
+            coder = new Base64.Decoder(flags, null);
+        }
+        coder.output = new byte[coder.maxOutputSize(BUFFER_SIZE)];
+        outputStart = 0;
+        outputEnd = 0;
+    }
+
+    public boolean markSupported() {
+        return false;
+    }
+
+    public void mark(int readlimit) {
+        throw new UnsupportedOperationException();
+    }
+
+    public void reset() {
+        throw new UnsupportedOperationException();
+    }
+
+    public void close() throws IOException {
+        in.close();
+        inputBuffer = null;
+    }
+
+    public int available() {
+        return outputEnd - outputStart;
+    }
+
+    public long skip(long n) throws IOException {
+        if (outputStart >= outputEnd) {
+            refill();
+        }
+        if (outputStart >= outputEnd) {
+            return 0;
+        }
+        long bytes = Math.min(n, outputEnd-outputStart);
+        outputStart += bytes;
+        return bytes;
+    }
+
+    public int read() throws IOException {
+        if (outputStart >= outputEnd) {
+            refill();
+        }
+        if (outputStart >= outputEnd) {
+            return -1;
+        } else {
+            return coder.output[outputStart++];
+        }
+    }
+
+    public int read(byte[] b, int off, int len) throws IOException {
+        if (outputStart >= outputEnd) {
+            refill();
+        }
+        if (outputStart >= outputEnd) {
+            return -1;
+        }
+        int bytes = Math.min(len, outputEnd-outputStart);
+        System.arraycopy(coder.output, outputStart, b, off, bytes);
+        outputStart += bytes;
+        return bytes;
+    }
+
+    /**
+     * Read data from the input stream into inputBuffer, then
+     * decode/encode it into the empty coder.output, and reset the
+     * outputStart and outputEnd pointers.
+     */
+    private void refill() throws IOException {
+        if (eof) return;
+        int bytesRead = in.read(inputBuffer);
+        boolean success;
+        if (bytesRead == -1) {
+            eof = true;
+            success = coder.process(EMPTY, 0, 0, true);
+        } else {
+            success = coder.process(inputBuffer, 0, bytesRead, false);
+        }
+        if (!success) {
+            throw new IOException("bad base-64");
+        }
+        outputEnd = coder.op;
+        outputStart = 0;
+    }
+}
diff --git a/core/java/android/util/base64/Base64OutputStream.java b/core/java/android/util/base64/Base64OutputStream.java
new file mode 100644
index 0000000..35e9a2b
--- /dev/null
+++ b/core/java/android/util/base64/Base64OutputStream.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util.base64;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * An OutputStream that does Base64 encoding on the data written to
+ * it, writing the resulting data to another OutputStream.
+ */
+public class Base64OutputStream extends FilterOutputStream {
+    private final Base64.Coder coder;
+    private final int flags;
+
+    private byte[] buffer = null;
+    private int bpos = 0;
+
+    private static byte[] EMPTY = new byte[0];
+
+    /**
+     * Performs Base64 encoding on the data written to the stream,
+     * writing the encoded data to another OutputStream.
+     *
+     * @param out the OutputStream to write the encoded data to
+     * @param flags bit flags for controlling the encoder; see the
+     *        constants in {@link Base64}
+     */
+    public Base64OutputStream(OutputStream out, int flags) {
+        this(out, flags, true);
+    }
+
+    /**
+     * Performs Base64 encoding or decoding on the data written to the
+     * stream, writing the encoded/decoded data to another
+     * OutputStream.
+     *
+     * @param out the OutputStream to write the encoded data to
+     * @param flags bit flags for controlling the encoder; see the
+     *        constants in {@link Base64}
+     * @param encode true to encode, false to decode
+     *
+     * @hide
+     */
+    public Base64OutputStream(OutputStream out, int flags, boolean encode) {
+        super(out);
+        this.flags = flags;
+        if (encode) {
+            coder = new Base64.Encoder(flags, null);
+        } else {
+            coder = new Base64.Decoder(flags, null);
+        }
+    }
+
+    public void write(int b) throws IOException {
+        // To avoid invoking the encoder/decoder routines for single
+        // bytes, we buffer up calls to write(int) in an internal
+        // byte array to transform them into writes of decently-sized
+        // arrays.
+
+        if (buffer == null) {
+            buffer = new byte[1024];
+        }
+        if (bpos >= buffer.length) {
+            // internal buffer full; write it out.
+            internalWrite(buffer, 0, bpos, false);
+            bpos = 0;
+        }
+        buffer[bpos++] = (byte) b;
+    }
+
+    /**
+     * Flush any buffered data from calls to write(int).  Needed
+     * before doing a write(byte[], int, int) or a close().
+     */
+    private void flushBuffer() throws IOException {
+        if (bpos > 0) {
+            internalWrite(buffer, 0, bpos, false);
+            bpos = 0;
+        }
+    }
+
+    public void write(byte[] b, int off, int len) throws IOException {
+        if (len <= 0) return;
+        flushBuffer();
+        internalWrite(b, off, len, false);
+    }
+
+    public void close() throws IOException {
+        IOException thrown = null;
+        try {
+            flushBuffer();
+            internalWrite(EMPTY, 0, 0, true);
+        } catch (IOException e) {
+            thrown = e;
+        }
+
+        try {
+            if ((flags & Base64.NO_CLOSE) == 0) {
+                out.close();
+            } else {
+                out.flush();
+            }
+        } catch (IOException e) {
+            if (thrown != null) {
+                thrown = e;
+            }
+        }
+
+        if (thrown != null) {
+            throw thrown;
+        }
+    }
+
+    /**
+     * Write the given bytes to the encoder/decoder.
+     *
+     * @param finish true if this is the last batch of input, to cause
+     *        encoder/decoder state to be finalized.
+     */
+    private void internalWrite(byte[] b, int off, int len, boolean finish) throws IOException {
+        coder.output = embiggen(coder.output, coder.maxOutputSize(len));
+        if (!coder.process(b, off, len, finish)) {
+            throw new IOException("bad base-64");
+        }
+        out.write(coder.output, 0, coder.op);
+    }
+
+    /**
+     * If b.length is at least len, return b.  Otherwise return a new
+     * byte array of length len.
+     */
+    private byte[] embiggen(byte[] b, int len) {
+        if (b == null || b.length < len) {
+            return new byte[len];
+        } else {
+            return b;
+        }
+    }
+}
diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java
index 3c79200..58f998e 100644
--- a/core/java/android/view/GestureDetector.java
+++ b/core/java/android/view/GestureDetector.java
@@ -465,10 +465,10 @@
         case MotionEvent.ACTION_POINTER_UP:
             // Ending a multitouch gesture and going back to 1 finger
             if (mIgnoreMultitouch && ev.getPointerCount() == 2) {
-                int id = (((action & MotionEvent.ACTION_POINTER_ID_MASK)
-                        >> MotionEvent.ACTION_POINTER_ID_SHIFT) == 0) ? 1 : 0;
-                mLastMotionX = ev.getX(id);
-                mLastMotionY = ev.getY(id);
+                int index = (((action & MotionEvent.ACTION_POINTER_INDEX_MASK)
+                        >> MotionEvent.ACTION_POINTER_INDEX_SHIFT) == 0) ? 1 : 0;
+                mLastMotionX = ev.getX(index);
+                mLastMotionY = ev.getY(index);
                 mVelocityTracker.recycle();
                 mVelocityTracker = VelocityTracker.obtain();
             }
diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java
index e1f2823..d31c8dc 100644
--- a/core/java/android/view/HapticFeedbackConstants.java
+++ b/core/java/android/view/HapticFeedbackConstants.java
@@ -34,8 +34,18 @@
      * The user has pressed on a virtual on-screen key.
      */
     public static final int VIRTUAL_KEY = 1;
+
+    /**
+     * The user has hit the barrier point while scrolling a view.
+     */
+    public static final int SCROLL_BARRIER = 2;
     
     /**
+     * The user has pressed a soft keyboard key.
+     */
+    public static final int KEYBOARD_TAP = 3;
+
+    /**
      * This is a private constant.  Feel free to renumber as desired.
      * @hide
      */
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index ca907af..d648e96 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -76,61 +76,81 @@
     public static final int ACTION_POINTER_DOWN     = 5;
     
     /**
-     * Synonym for {@link #ACTION_POINTER_DOWN} with
-     * {@link #ACTION_POINTER_ID_MASK} of 0: the primary pointer has gone done.
-     */
-    public static final int ACTION_POINTER_1_DOWN   = ACTION_POINTER_DOWN | 0x0000;
-    
-    /**
-     * Synonym for {@link #ACTION_POINTER_DOWN} with
-     * {@link #ACTION_POINTER_ID_MASK} of 1: the secondary pointer has gone done.
-     */
-    public static final int ACTION_POINTER_2_DOWN   = ACTION_POINTER_DOWN | 0x0100;
-    
-    /**
-     * Synonym for {@link #ACTION_POINTER_DOWN} with
-     * {@link #ACTION_POINTER_ID_MASK} of 2: the tertiary pointer has gone done.
-     */
-    public static final int ACTION_POINTER_3_DOWN   = ACTION_POINTER_DOWN | 0x0200;
-    
-    /**
      * A non-primary pointer has gone up.  The bits in
      * {@link #ACTION_POINTER_ID_MASK} indicate which pointer changed.
      */
     public static final int ACTION_POINTER_UP       = 6;
     
     /**
-     * Synonym for {@link #ACTION_POINTER_UP} with
-     * {@link #ACTION_POINTER_ID_MASK} of 0: the primary pointer has gone up.
+     * Bits in the action code that represent a pointer index, used with
+     * {@link #ACTION_POINTER_DOWN} and {@link #ACTION_POINTER_UP}.  Shifting
+     * down by {@link #ACTION_POINTER_INDEX_SHIFT} provides the actual pointer
+     * index where the data for the pointer going up or down can be found; you can
+     * get its identifier with {@link #getPointerId(int)} and the actual
+     * data with {@link #getX(int)} etc.
      */
+    public static final int ACTION_POINTER_INDEX_MASK  = 0xff00;
+    
+    /**
+     * Bit shift for the action bits holding the pointer index as
+     * defined by {@link #ACTION_POINTER_INDEX_MASK}.
+     */
+    public static final int ACTION_POINTER_INDEX_SHIFT = 8;
+    
+    /**
+     * @deprecated Use {@link #ACTION_POINTER_INDEX_MASK} to retrieve the
+     * data index associated with {@link #ACTION_POINTER_DOWN}.
+     */
+    @Deprecated
+    public static final int ACTION_POINTER_1_DOWN   = ACTION_POINTER_DOWN | 0x0000;
+    
+    /**
+     * @deprecated Use {@link #ACTION_POINTER_INDEX_MASK} to retrieve the
+     * data index associated with {@link #ACTION_POINTER_DOWN}.
+     */
+    @Deprecated
+    public static final int ACTION_POINTER_2_DOWN   = ACTION_POINTER_DOWN | 0x0100;
+    
+    /**
+     * @deprecated Use {@link #ACTION_POINTER_INDEX_MASK} to retrieve the
+     * data index associated with {@link #ACTION_POINTER_DOWN}.
+     */
+    @Deprecated
+    public static final int ACTION_POINTER_3_DOWN   = ACTION_POINTER_DOWN | 0x0200;
+    
+    /**
+     * @deprecated Use {@link #ACTION_POINTER_INDEX_MASK} to retrieve the
+     * data index associated with {@link #ACTION_POINTER_UP}.
+     */
+    @Deprecated
     public static final int ACTION_POINTER_1_UP     = ACTION_POINTER_UP | 0x0000;
     
     /**
-     * Synonym for {@link #ACTION_POINTER_UP} with
-     * {@link #ACTION_POINTER_ID_MASK} of 1: the secondary pointer has gone up.
+     * @deprecated Use {@link #ACTION_POINTER_INDEX_MASK} to retrieve the
+     * data index associated with {@link #ACTION_POINTER_UP}.
      */
+    @Deprecated
     public static final int ACTION_POINTER_2_UP     = ACTION_POINTER_UP | 0x0100;
     
     /**
-     * Synonym for {@link #ACTION_POINTER_UP} with
-     * {@link #ACTION_POINTER_ID_MASK} of 2: the tertiary pointer has gone up.
+     * @deprecated Use {@link #ACTION_POINTER_INDEX_MASK} to retrieve the
+     * data index associated with {@link #ACTION_POINTER_UP}.
      */
+    @Deprecated
     public static final int ACTION_POINTER_3_UP     = ACTION_POINTER_UP | 0x0200;
     
     /**
-     * Bits in the action code that represent a pointer ID, used with
-     * {@link #ACTION_POINTER_DOWN} and {@link #ACTION_POINTER_UP}.  Pointer IDs
-     * start at 0, with 0 being the primary (first) pointer in the motion.  Note
-     * that this not <em>not</em> an index into the array of pointer values,
-     * which is compacted to only contain pointers that are down; the pointer
-     * ID for a particular index can be found with {@link #findPointerIndex}.
+     * @deprecated Renamed to {@link #ACTION_POINTER_INDEX_MASK} to match
+     * the actual data contained in these bits.
      */
+    @Deprecated
     public static final int ACTION_POINTER_ID_MASK  = 0xff00;
     
     /**
-     * Bit shift for the action bits holding the pointer identifier as
-     * defined by {@link #ACTION_POINTER_ID_MASK}.
+     * @deprecated Renamed to {@link #ACTION_POINTER_INDEX_SHIFT} to match
+     * the actual data contained in these bits.
      */
+    @Deprecated
     public static final int ACTION_POINTER_ID_SHIFT = 8;
     
     private static final boolean TRACK_RECYCLED_LOCATION = false;
@@ -618,13 +638,39 @@
     /**
      * Return the kind of action being performed -- one of either
      * {@link #ACTION_DOWN}, {@link #ACTION_MOVE}, {@link #ACTION_UP}, or
-     * {@link #ACTION_CANCEL}.
+     * {@link #ACTION_CANCEL}.  Consider using {@link #getActionMasked}
+     * and {@link #getActionIndex} to retrieve the separate masked action
+     * and pointer index.
      */
     public final int getAction() {
         return mAction;
     }
 
     /**
+     * Return the masked action being performed, without pointer index
+     * information.  May be any of the actions: {@link #ACTION_DOWN},
+     * {@link #ACTION_MOVE}, {@link #ACTION_UP}, {@link #ACTION_CANCEL},
+     * {@link #ACTION_POINTER_DOWN}, or {@link #ACTION_POINTER_UP}.
+     * Use {@link #getActionIndex} to return the index associated with
+     * pointer actions.
+     */
+    public final int getActionMasked() {
+        return mAction & ACTION_MASK;
+    }
+
+    /**
+     * For {@link #ACTION_POINTER_DOWN} or {@link #ACTION_POINTER_UP}
+     * as returned by {@link #getActionMasked}, this returns the associated
+     * pointer index.  The index may be used with {@link #getPointerId(int)},
+     * {@link #getX(int)}, {@link #getY(int)}, {@link #getPressure(int)},
+     * and {@link #getSize(int)} to get information about the pointer that has
+     * gone down or up.
+     */
+    public final int getActionIndex() {
+        return (mAction & ACTION_POINTER_INDEX_MASK) >> ACTION_POINTER_INDEX_SHIFT;
+    }
+
+    /**
      * Returns the time (in ms) when the user originally pressed down to start
      * a stream of position events.
      */
diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java
index 9581080..91fd6f1 100644
--- a/core/java/android/view/VelocityTracker.java
+++ b/core/java/android/view/VelocityTracker.java
@@ -61,6 +61,7 @@
 
     float mYVelocity[] = new float[MotionEvent.BASE_AVAIL_POINTERS];
     float mXVelocity[] = new float[MotionEvent.BASE_AVAIL_POINTERS];
+    int mLastTouch;
 
     private VelocityTracker mNext;
 
@@ -105,8 +106,11 @@
      * Reset the velocity tracker back to its initial state.
      */
     public void clear() {
-        for (int i = 0; i < MotionEvent.BASE_AVAIL_POINTERS; i++) {
-            mPastTime[i][0] = 0;
+        final long[][] pastTime = mPastTime;
+        for (int p = 0; p < MotionEvent.BASE_AVAIL_POINTERS; p++) {
+            for (int i = 0; i < NUM_PAST; i++) {
+                pastTime[p][i] = 0;
+            }
         }
     }
     
@@ -120,55 +124,37 @@
      * @param ev The MotionEvent you received and would like to track.
      */
     public void addMovement(MotionEvent ev) {
-        long time = ev.getEventTime();
         final int N = ev.getHistorySize();
         final int pointerCount = ev.getPointerCount();
-        for (int p = 0; p < pointerCount; p++) {
-            for (int i=0; i<N; i++) {
-                addPoint(p, ev.getHistoricalX(p, i), ev.getHistoricalY(p, i),
-                        ev.getHistoricalEventTime(i));
+        int touchIndex = (mLastTouch + 1) % NUM_PAST;
+        for (int i=0; i<N; i++) {
+            for (int id = 0; id < MotionEvent.BASE_AVAIL_POINTERS; id++) {
+                mPastTime[id][touchIndex] = 0;
             }
-            addPoint(p, ev.getX(p), ev.getY(p), time);
-        }
-    }
+            for (int p = 0; p < pointerCount; p++) {
+                int id = ev.getPointerId(p);
+                mPastX[id][touchIndex] = ev.getHistoricalX(p, i);
+                mPastY[id][touchIndex] = ev.getHistoricalY(p, i);
+                mPastTime[id][touchIndex] = ev.getHistoricalEventTime(i);
+            }
 
-    private void addPoint(int pos, float x, float y, long time) {
-        int drop = -1;
-        int i;
-        if (localLOGV) Log.v(TAG, "Adding past y=" + y + " time=" + time);
-        final long[] pastTime = mPastTime[pos];
-        for (i=0; i<NUM_PAST; i++) {
-            if (pastTime[i] == 0) {
-                break;
-            } else if (pastTime[i] < time-LONGEST_PAST_TIME) {
-                if (localLOGV) Log.v(TAG, "Dropping past too old at "
-                        + i + " time=" + pastTime[i]);
-                drop = i;
-            }
+            touchIndex = (touchIndex + 1) % NUM_PAST;
         }
-        if (localLOGV) Log.v(TAG, "Add index: " + i);
-        if (i == NUM_PAST && drop < 0) {
-            drop = 0;
+
+        // During calculation any pointer values with a time of 0 are treated
+        // as a break in input. Initialize all to 0 for each new touch index.
+        for (int id = 0; id < MotionEvent.BASE_AVAIL_POINTERS; id++) {
+            mPastTime[id][touchIndex] = 0;
         }
-        if (drop == i) drop--;
-        final float[] pastX = mPastX[pos];
-        final float[] pastY = mPastY[pos];
-        if (drop >= 0) {
-            if (localLOGV) Log.v(TAG, "Dropping up to #" + drop);
-            final int start = drop+1;
-            final int count = NUM_PAST-drop-1;
-            System.arraycopy(pastX, start, pastX, 0, count);
-            System.arraycopy(pastY, start, pastY, 0, count);
-            System.arraycopy(pastTime, start, pastTime, 0, count);
-            i -= (drop+1);
+        final long time = ev.getEventTime();
+        for (int p = 0; p < pointerCount; p++) {
+            int id = ev.getPointerId(p);
+            mPastX[id][touchIndex] = ev.getX(p);
+            mPastY[id][touchIndex] = ev.getY(p);
+            mPastTime[id][touchIndex] = time;
         }
-        pastX[i] = x;
-        pastY[i] = y;
-        pastTime[i] = time;
-        i++;
-        if (i < NUM_PAST) {
-            pastTime[i] = 0;
-        }
+
+        mLastTouch = touchIndex;
     }
 
     /**
@@ -199,36 +185,43 @@
             final float[] pastX = mPastX[pos];
             final float[] pastY = mPastY[pos];
             final long[] pastTime = mPastTime[pos];
-
+            final int lastTouch = mLastTouch;
+        
+            // find oldest acceptable time
+            int oldestTouch = lastTouch;
+            if (pastTime[lastTouch] > 0) { // cleared ?
+                final float acceptableTime = pastTime[lastTouch] - LONGEST_PAST_TIME;
+                int nextOldestTouch = (NUM_PAST + oldestTouch - 1) % NUM_PAST;
+                while (pastTime[nextOldestTouch] >= acceptableTime &&
+                        nextOldestTouch != lastTouch) {
+                    oldestTouch = nextOldestTouch;
+                    nextOldestTouch = (NUM_PAST + oldestTouch - 1) % NUM_PAST;
+                }
+            }
+        
             // Kind-of stupid.
-            final float oldestX = pastX[0];
-            final float oldestY = pastY[0];
-            final long oldestTime = pastTime[0];
+            final float oldestX = pastX[oldestTouch];
+            final float oldestY = pastY[oldestTouch];
+            final long oldestTime = pastTime[oldestTouch];
             float accumX = 0;
             float accumY = 0;
-            int N=0;
-            while (N < NUM_PAST) {
-                if (pastTime[N] == 0) {
-                    break;
-                }
-                N++;
-            }
+            float N = (lastTouch - oldestTouch + NUM_PAST) % NUM_PAST + 1;
             // Skip the last received event, since it is probably pretty noisy.
             if (N > 3) N--;
 
             for (int i=1; i < N; i++) {
-                final int dur = (int)(pastTime[i] - oldestTime);
+                final int j = (oldestTouch + i) % NUM_PAST;
+                final int dur = (int)(pastTime[j] - oldestTime);
                 if (dur == 0) continue;
-                float dist = pastX[i] - oldestX;
+                float dist = pastX[j] - oldestX;
                 float vel = (dist/dur) * units;   // pixels/frame.
-                if (accumX == 0) accumX = vel;
-                else accumX = (accumX + vel) * .5f;
-
-                dist = pastY[i] - oldestY;
+                accumX = (accumX == 0) ? vel : (accumX + vel) * .5f;
+            
+                dist = pastY[j] - oldestY;
                 vel = (dist/dur) * units;   // pixels/frame.
-                if (accumY == 0) accumY = vel;
-                else accumY = (accumY + vel) * .5f;
+                accumY = (accumY == 0) ? vel : (accumY + vel) * .5f;
             }
+            
             mXVelocity[pos] = accumX < 0.0f ? Math.max(accumX, -maxVelocity)
                     : Math.min(accumX, maxVelocity);
             mYVelocity[pos] = accumY < 0.0f ? Math.max(accumY, -maxVelocity)
@@ -263,25 +256,25 @@
      * Retrieve the last computed X velocity.  You must first call
      * {@link #computeCurrentVelocity(int)} before calling this function.
      * 
-     * @param pos Which pointer's velocity to return.
+     * @param id Which pointer's velocity to return.
      * @return The previously computed X velocity.
      * 
      * @hide Pending API approval
      */
-    public float getXVelocity(int pos) {
-        return mXVelocity[pos];
+    public float getXVelocity(int id) {
+        return mXVelocity[id];
     }
     
     /**
      * Retrieve the last computed Y velocity.  You must first call
      * {@link #computeCurrentVelocity(int)} before calling this function.
      * 
-     * @param pos Which pointer's velocity to return.
+     * @param id Which pointer's velocity to return.
      * @return The previously computed Y velocity.
      * 
      * @hide Pending API approval
      */
-    public float getYVelocity(int pos) {
-        return mYVelocity[pos];
+    public float getYVelocity(int id) {
+        return mYVelocity[id];
     }
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 889985a..57fdd8b 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8282,7 +8282,7 @@
      */
     public void clearAnimation() {
         if (mCurrentAnimation != null) {
-            mCurrentAnimation.cancel();
+            mCurrentAnimation.detach();
         }
         mCurrentAnimation = null;
     }
@@ -8547,7 +8547,119 @@
         LayoutInflater factory = LayoutInflater.from(context);
         return factory.inflate(resource, root);
     }
+    
+    /**
+     * Scroll the view with standard behavior for scrolling beyond the normal
+     * content boundaries. Views that call this method should override
+     * {@link #onOverscrolled(int, int, boolean, boolean)} to respond to the
+     * results of an overscroll operation.
+     * 
+     * Views can use this method to handle any touch or fling-based scrolling.
+     * 
+     * @param deltaX Change in X in pixels 
+     * @param deltaY Change in Y in pixels
+     * @param scrollX Current X scroll value in pixels before applying deltaX
+     * @param scrollY Current Y scroll value in pixels before applying deltaY
+     * @param scrollRangeX Maximum content scroll range along the X axis
+     * @param scrollRangeY Maximum content scroll range along the Y axis
+     * @param maxOverscrollX Number of pixels to overscroll by in either direction
+     *          along the X axis.
+     * @param maxOverscrollY Number of pixels to overscroll by in either direction
+     *          along the Y axis.
+     * @return true if scrolling was clamped to an overscroll boundary along either
+     *          axis, false otherwise.
+     */
+    protected boolean overscrollBy(int deltaX, int deltaY,
+            int scrollX, int scrollY,
+            int scrollRangeX, int scrollRangeY,
+            int maxOverscrollX, int maxOverscrollY) {
+        // Scale the scroll amount if we're in the dropoff zone
+        final int dropoffX = maxOverscrollX / 2;
+        final int dropoffLeft = -dropoffX;
+        final int dropoffRight = dropoffX + scrollRangeX;
+        int newScrollX;
+        if ((scrollX < dropoffLeft && deltaX < 0) ||
+                (scrollX > dropoffRight && deltaX > 0)) {
+            newScrollX = scrollX + deltaX / 2;
+        } else {
+            newScrollX = scrollX + deltaX;
+            if (newScrollX > dropoffRight && deltaX > 0) {
+                int extra = newScrollX - dropoffRight;
+                newScrollX = dropoffRight + extra / 2;
+            } else if (newScrollX < dropoffLeft && deltaX < 0) {
+                int extra = newScrollX - dropoffLeft;
+                newScrollX = dropoffLeft + extra / 2;
+            }
+        }
+        
+        final int dropoffY = maxOverscrollY / 2;
+        final int dropoffTop = -dropoffY;
+        final int dropoffBottom = dropoffY + scrollRangeY;
+        int newScrollY;
+        if ((scrollY < dropoffTop && deltaY < 0) ||
+                (scrollY > dropoffBottom && deltaY > 0)) {
+            newScrollY = scrollY + deltaY / 2;
+        } else {
+            newScrollY = scrollY + deltaY;
+            if (newScrollY > dropoffBottom && deltaY > 0) {
+                int extra = newScrollY - dropoffBottom;
+                newScrollY = dropoffBottom + extra / 2;
+            } else if (newScrollY < dropoffTop && deltaY < 0) {
+                int extra = newScrollY - dropoffTop;
+                newScrollY = dropoffTop + extra / 2;
+            }
+        }
 
+        // Clamp values if at the limits and record
+        final int left = -maxOverscrollX;
+        final int right = maxOverscrollX + scrollRangeX;
+        final int top = -maxOverscrollY;
+        final int bottom = maxOverscrollY + scrollRangeY;
+
+        boolean clampedX = false;
+        if (newScrollX > right) {
+            newScrollX = right;
+            clampedX = true;
+        } else if (newScrollX < left) {
+            newScrollX = left;
+            clampedX = true;
+        }
+        
+        boolean clampedY = false;
+        if (newScrollY > bottom) {
+            newScrollY = bottom;
+            clampedY = true;
+        } else if (newScrollY < top) {
+            newScrollY = top;
+            clampedY = true;
+        }
+        
+        // Bump the device with some haptic feedback if we're at the edge
+        // and didn't start there.
+        if ((clampedX && scrollX != left && scrollX != right) ||
+                (clampedY && scrollY != top && scrollY != bottom)) {
+            performHapticFeedback(HapticFeedbackConstants.SCROLL_BARRIER);
+        }
+
+        onOverscrolled(newScrollX, newScrollY, clampedX, clampedY);
+        
+        return clampedX || clampedY;
+    }
+    
+    /**
+     * Called by {@link #overscrollBy(int, int, int, int, int, int, int, int)} to
+     * respond to the results of an overscroll operation.
+     * 
+     * @param scrollX New X scroll value in pixels
+     * @param scrollY New Y scroll value in pixels
+     * @param clampedX True if scrollX was clamped to an overscroll boundary
+     * @param clampedY True if scrollY was clamped to an overscroll boundary
+     */
+    protected void onOverscrolled(int scrollX, int scrollY,
+            boolean clampedX, boolean clampedY) {
+        // Intentionally empty.
+    }
+    
     /**
      * A MeasureSpec encapsulates the layout requirements passed from parent to child.
      * Each MeasureSpec represents a requirement for either the width or the height.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index cdf9eb0..2ed623d 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3398,7 +3398,7 @@
 
         /**
          * Special value for the height or width requested by a View.
-         * MATCH_PARENT means that the view wants to be as bigas its parent,
+         * MATCH_PARENT means that the view wants to be as big as its parent,
          * minus the parent's padding, if any.
          */
         public static final int MATCH_PARENT = -1;
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 7bc5cce..ab3260e 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -851,6 +851,11 @@
      */
     public boolean isCheekPressedAgainstScreen(MotionEvent ev);
     
+    /**
+     * Called every time the window manager is dispatching a pointer event.
+     */
+    public void dispatchedPointerEventLw(MotionEvent ev, int targetX, int targetY);
+    
     public void setCurrentOrientationLw(int newOrientation);
     
     /**
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index ad98259..349b7e5 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -277,6 +277,16 @@
     }
 
     /**
+     * @hide
+     */
+    public void detach() {
+        if (mStarted && !mEnded) {
+            mEnded = true;
+            if (mListener != null) mListener.onAnimationEnd(this);
+        }
+    }
+
+    /**
      * Whether or not the animation has been initialized.
      *
      * @return Has this animation been initialized.
@@ -766,10 +776,10 @@
         if (expired) {
             if (mRepeatCount == mRepeated) {
                 if (!mEnded) {
+                    mEnded = true;
                     if (mListener != null) {
                         mListener.onAnimationEnd(this);
                     }
-                    mEnded = true;
                 }
             } else {
                 if (mRepeatCount > 0) {
diff --git a/core/java/android/webkit/EventLogTags.logtags b/core/java/android/webkit/EventLogTags.logtags
new file mode 100644
index 0000000..082a437
--- /dev/null
+++ b/core/java/android/webkit/EventLogTags.logtags
@@ -0,0 +1,11 @@
+# See system/core/logcat/event.logtags for a description of the format of this file.
+
+option java_package android.webkit;
+
+# browser stats for diary study
+70101 browser_zoom_level_change (start level|1|5),(end level|1|5),(time|2|3)
+70102 browser_double_tap_duration (duration|1|3),(time|2|3)
+# 70103- used by the browser app itself
+
+70150 browser_snap_center
+70151 browser_text_size_change (oldSize|1|5), (newSize|1|5)
diff --git a/core/java/android/webkit/GoogleLocationSettingManager.java b/core/java/android/webkit/GoogleLocationSettingManager.java
deleted file mode 100644
index ecac70a..0000000
--- a/core/java/android/webkit/GoogleLocationSettingManager.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * 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.webkit;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
-import android.database.ContentObserver;
-import android.os.Handler;
-import android.preference.PreferenceManager;
-import android.provider.Settings;
-
-import java.util.HashSet;
-
-/**
- * A class to manage the interaction between the system setting 'Location &
- * Security - Share with Google' and the browser. When this setting is set
- * to true, we allow Geolocation for Google origins. When this setting is
- * set to false, we clear Geolocation permissions for Google origins.
- */
-class GoogleLocationSettingManager {
-    // The observer used to listen to the system setting.
-    private GoogleLocationSettingObserver mSettingObserver;
-
-    // The value of the system setting that indicates true.
-    private final static int sSystemSettingTrue = 1;
-    // The value of the system setting that indicates false.
-    private final static int sSystemSettingFalse = 0;
-    // The value of the USE_LOCATION_FOR_SERVICES system setting last read
-    // by the browser.
-    private final static String LAST_READ_USE_LOCATION_FOR_SERVICES =
-            "lastReadUseLocationForServices";
-    // The Browser package name.
-    private static final String BROWSER_PACKAGE_NAME = "com.android.browser";
-    // The Google origins we consider.
-    private static HashSet<String> sGoogleOrigins;
-    static {
-        sGoogleOrigins = new HashSet<String>();
-        // NOTE: DO NOT ADD A "/" AT THE END!
-        sGoogleOrigins.add("http://www.google.com");
-        sGoogleOrigins.add("http://www.google.co.uk");
-    }
-
-    private static GoogleLocationSettingManager sGoogleLocationSettingManager = null;
-    private static int sRefCount = 0;
-
-    static GoogleLocationSettingManager getInstance() {
-        if (sGoogleLocationSettingManager == null) {
-            sGoogleLocationSettingManager = new GoogleLocationSettingManager();
-        }
-        return sGoogleLocationSettingManager;
-    }
-
-    private GoogleLocationSettingManager() {}
-
-    /**
-     * Starts the manager. Checks whether the setting has changed and
-     * installs an observer to listen for future changes.
-     */
-    public void start(Context context) {
-        // Are we running in the browser?
-        if (context == null || !BROWSER_PACKAGE_NAME.equals(context.getPackageName())) {
-            return;
-        }
-        // Increase the refCount
-        sRefCount++;
-        // Are we already registered?
-        if (mSettingObserver != null) {
-            return;
-        }
-        // Read and apply the settings if needed.
-        maybeApplySetting(context);
-        // Register to receive notifications when the system settings change.
-        mSettingObserver = new GoogleLocationSettingObserver();
-        mSettingObserver.observe(context);
-    }
-
-    /**
-     * Stops the manager.
-     */
-    public void stop() {
-        // Are we already registered?
-        if (mSettingObserver == null) {
-            return;
-        }
-        if (--sRefCount == 0) {
-            mSettingObserver.doNotObserve();
-            mSettingObserver = null;
-        }
-    }
-    /**
-     * Checks to see if the system setting has changed and if so,
-     * updates the Geolocation permissions accordingly.
-     * @param the Application context
-     */
-    private void maybeApplySetting(Context context) {
-        int setting = getSystemSetting(context);
-        if (settingChanged(setting, context)) {
-            applySetting(setting);
-        }
-    }
-
-    /**
-     * Gets the current system setting for 'Use location for Google services'.
-     * @param the Application context
-     * @return The system setting.
-     */
-    private int getSystemSetting(Context context) {
-        return Settings.Secure.getInt(context.getContentResolver(),
-                                      Settings.Secure.USE_LOCATION_FOR_SERVICES,
-                                      sSystemSettingFalse);
-    }
-
-    /**
-     * Determines whether the supplied setting has changed from the last
-     * value read by the browser.
-     * @param setting The setting.
-     * @param the Application context
-     * @return Whether the setting has changed from the last value read
-     *     by the browser.
-     */
-    private boolean settingChanged(int setting, Context context) {
-        SharedPreferences preferences =
-                PreferenceManager.getDefaultSharedPreferences(context);
-        // Default to false. If the system setting is false the first time it is ever read by the
-        // browser, there's nothing to do.
-        int lastReadSetting = sSystemSettingFalse;
-        lastReadSetting = preferences.getInt(LAST_READ_USE_LOCATION_FOR_SERVICES,
-                                             lastReadSetting);
-
-        if (lastReadSetting == setting) {
-            return false;
-        }
-
-        Editor editor = preferences.edit();
-        editor.putInt(LAST_READ_USE_LOCATION_FOR_SERVICES, setting);
-        editor.commit();
-        return true;
-    }
-
-    /**
-     * Applies the supplied setting to the Geolocation permissions.
-     * @param setting The setting.
-     */
-    private void applySetting(int setting) {
-        for (String origin : sGoogleOrigins) {
-            if (setting == sSystemSettingTrue) {
-                GeolocationPermissions.getInstance().allow(origin);
-            } else {
-                GeolocationPermissions.getInstance().clear(origin);
-            }
-        }
-    }
-
-    /**
-     * This class implements an observer to listen for changes to the
-     * system setting.
-     */
-    private class GoogleLocationSettingObserver extends ContentObserver {
-        private Context mContext;
-
-        GoogleLocationSettingObserver() {
-            super(new Handler());
-        }
-
-        void observe(Context context) {
-            if (mContext != null) {
-                return;
-            }
-            ContentResolver resolver = context.getContentResolver();
-            resolver.registerContentObserver(Settings.Secure.getUriFor(
-                Settings.Secure.USE_LOCATION_FOR_SERVICES), false, this);
-            mContext = context;
-        }
-
-        void doNotObserve() {
-            if (mContext == null) {
-                return;
-            }
-            ContentResolver resolver = mContext.getContentResolver();
-            resolver.unregisterContentObserver(this);
-            mContext = null;
-        }
-
-        @Override
-        public void onChange(boolean selfChange) {
-            // This may come after the call to doNotObserve() above,
-            // so mContext may be null.
-            if (mContext != null) {
-                maybeApplySetting(mContext);
-            }
-        }
-    }
-}
diff --git a/core/java/android/webkit/JWebCoreJavaBridge.java b/core/java/android/webkit/JWebCoreJavaBridge.java
index e496d97..9dc7079 100644
--- a/core/java/android/webkit/JWebCoreJavaBridge.java
+++ b/core/java/android/webkit/JWebCoreJavaBridge.java
@@ -21,6 +21,8 @@
 import android.os.Message;
 import android.util.Log;
 
+import java.util.Set;
+
 final class JWebCoreJavaBridge extends Handler {
     // Identifier for the timer message.
     private static final int TIMER_MESSAGE = 1;
@@ -248,4 +250,7 @@
             boolean reload);
     public native void setNetworkOnLine(boolean online);
     public native void setNetworkType(String type, String subtype);
+    public native void addPackageNames(Set<String> packageNames);
+    public native void addPackageName(String packageName);
+    public native void removePackageName(String packageName);
 }
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 35f1ac6..39e5275 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -22,7 +22,7 @@
 import android.os.Build;
 import android.os.Handler;
 import android.os.Message;
-import android.provider.Checkin;
+import android.util.EventLog;
 import java.lang.SecurityException;
 import java.util.Locale;
 
@@ -501,8 +501,8 @@
      */
     public synchronized void setTextSize(TextSize t) {
         if (WebView.mLogEvent && mTextSize != t ) {
-            Checkin.updateStats(mContext.getContentResolver(),
-                    Checkin.Stats.Tag.BROWSER_TEXT_SIZE_CHANGE, 1, 0.0);
+            EventLog.writeEvent(EventLogTags.BROWSER_TEXT_SIZE_CHANGE,
+                    mTextSize.value, t.value);
         }
         mTextSize = t;
         postSync();
@@ -1355,8 +1355,6 @@
             junit.framework.Assert.assertTrue(frame.mNativeFrame != 0);
         }
 
-        GoogleLocationSettingManager.getInstance().start(mContext);
-
         SharedPreferences sp = mContext.getSharedPreferences(PREF_FILE,
                 Context.MODE_PRIVATE);
         if (mDoubleTapToastCount > 0) {
@@ -1373,7 +1371,6 @@
      */
     /*package*/
     synchronized void onDestroyed() {
-        GoogleLocationSettingManager.getInstance().stop();
     }
 
     private int pin(int size) {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 8fa8f09..ae6c666 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -38,7 +38,6 @@
 import android.os.Message;
 import android.os.ServiceManager;
 import android.os.SystemClock;
-import android.provider.Checkin;
 import android.text.IClipboard;
 import android.text.Selection;
 import android.text.Spannable;
@@ -87,6 +86,7 @@
 import java.util.List;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 
 import junit.framework.Assert;
 
@@ -214,8 +214,6 @@
     // true means redraw the screen all-the-time. Only with AUTO_REDRAW_HACK
     private boolean mAutoRedraw;
     private int mRootLayer; // C++ pointer to the root layer
-    private boolean mLayersHaveAnimations;
-    private EvaluateLayersAnimations mEvaluateThread;
 
     static final String LOGTAG = "webview";
 
@@ -623,8 +621,6 @@
     private boolean mGotKeyDown;
 
     /* package */ static boolean mLogEvent = true;
-    private static final int EVENT_LOG_ZOOM_LEVEL_CHANGE = 70101;
-    private static final int EVENT_LOG_DOUBLE_TAP_DURATION = 70102;
 
     // for event log
     private long mLastTouchUpTime = 0;
@@ -2907,6 +2903,45 @@
         return mWebViewCore.getSettings();
     }
 
+    /**
+     * Use this method to inform the webview about packages that are installed
+     * in the system. This information will be used by the
+     * navigator.isApplicationInstalled() API.
+     * @param packageNames is a set of package names that are known to be
+     * installed in the system.
+     *
+     * @hide not a public API
+     */
+    public void addPackageNames(Set<String> packageNames) {
+        mWebViewCore.sendMessage(EventHub.ADD_PACKAGE_NAMES, packageNames);
+    }
+
+    /**
+     * Use this method to inform the webview about single packages that are
+     * installed in the system. This information will be used by the
+     * navigator.isApplicationInstalled() API.
+     * @param packageName is the name of a package that is known to be
+     * installed in the system.
+     *
+     * @hide not a public API
+     */
+    public void addPackageName(String packageName) {
+        mWebViewCore.sendMessage(EventHub.ADD_PACKAGE_NAME, packageName);
+    }
+
+    /**
+     * Use this method to inform the webview about packages that are uninstalled
+     * in the system. This information will be used by the
+     * navigator.isApplicationInstalled() API.
+     * @param packageName is the name of a package that has been uninstalled in
+     * the system.
+     *
+     * @hide not a public API
+     */
+    public void removePackageName(String packageName) {
+        mWebViewCore.sendMessage(EventHub.REMOVE_PACKAGE_NAME, packageName);
+    }
+
    /**
     * Return the list of currently loaded plugins.
     * @return The list of currently loaded plugins.
@@ -3075,6 +3110,15 @@
             int scrollY = computeVerticalScrollOffset();
             int viewHeight = getHeight() - getVisibleTitleHeight();
 
+            // Currently for each draw we compute the animation values;
+            // We may in the future decide to do that independently.
+            if (nativeEvaluateLayersAnimations(mRootLayer)) {
+                // If we have unfinished (or unstarted) animations,
+                // we ask for a repaint.
+                invalidate();
+            }
+
+            // We can now draw the layers.
             nativeDrawLayers(mRootLayer, mScrollX, scrollY,
                              getWidth(), viewHeight,
                              mActualScale, canvas);
@@ -3418,40 +3462,6 @@
     }
 
     /*
-     * This class runs the layers animations in their own thread,
-     * so that we do not slow down the UI.
-     */
-    private class EvaluateLayersAnimations extends Thread {
-        boolean mRunning = true;
-        // delay corresponds to 40fps, no need to go faster.
-        int mDelay = 25; // in ms
-        public void run() {
-            while (mRunning) {
-                if (mLayersHaveAnimations && mRootLayer != 0) {
-                    // updates is a C++ pointer to a Vector of AnimationValues
-                    int updates = nativeEvaluateLayersAnimations(mRootLayer);
-                    if (updates == 0) {
-                        mRunning = false;
-                    }
-                    Message.obtain(mPrivateHandler,
-                          WebView.IMMEDIATE_REPAINT_MSG_ID,
-                          updates, 0).sendToTarget();
-                } else {
-                    mRunning = false;
-                }
-                try {
-                    Thread.currentThread().sleep(mDelay);
-                } catch (InterruptedException e) {
-                    mRunning = false;
-                }
-            }
-        }
-        public void cancel() {
-            mRunning = false;
-        }
-    }
-
-    /*
      * This class requests an Adapter for the WebTextView which shows past
      * entries stored in the database.  It is a Runnable so that it can be done
      * in its own thread, without slowing down the UI.
@@ -4453,7 +4463,7 @@
                     mWebViewCore.sendMessage(
                             EventHub.UPDATE_FRAME_CACHE_IF_LOADING);
                     if (mLogEvent && eventTime - mLastTouchUpTime < 1000) {
-                        EventLog.writeEvent(EVENT_LOG_DOUBLE_TAP_DURATION,
+                        EventLog.writeEvent(EventLogTags.BROWSER_DOUBLE_TAP_DURATION,
                                 (eventTime - mLastTouchUpTime), eventTime);
                     }
                 }
@@ -5389,11 +5399,8 @@
     }
 
     private void doMotionUp(int contentX, int contentY) {
-        if (nativeMotionUp(contentX, contentY, mNavSlop)) {
-            if (mLogEvent) {
-                Checkin.updateStats(mContext.getContentResolver(),
-                        Checkin.Stats.Tag.BROWSER_SNAP_CENTER, 1, 0.0);
-            }
+        if (mLogEvent && nativeMotionUp(contentX, contentY, mNavSlop)) {
+            EventLog.writeEvent(EventLogTags.BROWSER_SNAP_CENTER);
         }
         if (nativeHasCursorNode() && !nativeCursorIsTextInput()) {
             playSoundEffect(SoundEffectConstants.CLICK);
@@ -5886,6 +5893,10 @@
                     }
                     break;
                 case UPDATE_TEXT_SELECTION_MSG_ID:
+                    // If no textfield was in focus, and the user touched one,
+                    // causing it to send this message, then WebTextView has not
+                    // been set up yet.  Rebuild it so it can set its selection.
+                    rebuildWebTextView();
                     if (inEditingMode()
                             && mWebTextView.isSameTextField(msg.arg1)
                             && msg.arg2 == mTextGeneration) {
@@ -5935,13 +5946,6 @@
                     break;
                 }
                 case IMMEDIATE_REPAINT_MSG_ID: {
-                    int updates = msg.arg1;
-                    if (updates != 0) {
-                        // updates is a C++ pointer to a Vector of
-                        // AnimationValues that we apply to the layers.
-                        // The Vector is deallocated in nativeUpdateLayers().
-                        nativeUpdateLayers(updates);
-                    }
                     invalidate();
                     break;
                 }
@@ -5951,18 +5955,6 @@
                     if (oldLayer > 0) {
                         nativeDestroyLayer(oldLayer);
                     }
-                    if (mRootLayer == 0) {
-                        mLayersHaveAnimations = false;
-                    }
-                    if (mEvaluateThread != null) {
-                        mEvaluateThread.cancel();
-                        mEvaluateThread = null;
-                    }
-                    if (nativeLayersHaveAnimations(mRootLayer)) {
-                        mLayersHaveAnimations = true;
-                        mEvaluateThread = new EvaluateLayersAnimations();
-                        mEvaluateThread.start();
-                    }
                     invalidate();
                     break;
                 }
@@ -6735,9 +6727,7 @@
     private native void     nativeDestroy();
     private native void     nativeDrawCursorRing(Canvas content);
     private native void     nativeDestroyLayer(int layer);
-    private native int      nativeEvaluateLayersAnimations(int layer);
-    private native boolean  nativeLayersHaveAnimations(int layer);
-    private native void     nativeUpdateLayers(int updates);
+    private native boolean  nativeEvaluateLayersAnimations(int layer);
     private native void     nativeDrawLayers(int layer,
                                              int scrollX, int scrollY,
                                              int width, int height,
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 9c91919..3a3e445 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -892,6 +892,11 @@
 
         static final int SET_NETWORK_TYPE = 183;
 
+        // navigator.isApplicationInstalled()
+        static final int ADD_PACKAGE_NAMES = 184;
+        static final int ADD_PACKAGE_NAME = 185;
+        static final int REMOVE_PACKAGE_NAME = 186;
+
         // private message ids
         private static final int DESTROY =     200;
 
@@ -1363,6 +1368,33 @@
                         case HIDE_FULLSCREEN:
                             nativeFullScreenPluginHidden(msg.arg1);
                             break;
+
+                        case ADD_PACKAGE_NAMES:
+                            if (BrowserFrame.sJavaBridge == null) {
+                                throw new IllegalStateException("No WebView " +
+                                        "has been created in this process!");
+                            }
+                            BrowserFrame.sJavaBridge.addPackageNames(
+                                    (Set<String>) msg.obj);
+                            break;
+
+                        case ADD_PACKAGE_NAME:
+                            if (BrowserFrame.sJavaBridge == null) {
+                                throw new IllegalStateException("No WebView " +
+                                        "has been created in this process!");
+                            }
+                            BrowserFrame.sJavaBridge.addPackageName(
+                                    (String) msg.obj);
+                            break;
+
+                        case REMOVE_PACKAGE_NAME:
+                            if (BrowserFrame.sJavaBridge == null) {
+                                throw new IllegalStateException("No WebView " +
+                                        "has been created in this process!");
+                            }
+                            BrowserFrame.sJavaBridge.removePackageName(
+                                    (String) msg.obj);
+                            break;
                     }
                 }
             };
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 2f96aef..4c77bdc 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -377,6 +377,16 @@
     int mResurrectToPosition = INVALID_POSITION;
 
     private ContextMenuInfo mContextMenuInfo = null;
+    
+    /**
+     * Maximum distance to overscroll by
+     */
+    private int mOverscrollMax;
+    
+    /**
+     * Content height divided by this is the overscroll limit.
+     */
+    private static final int OVERSCROLL_LIMIT_DIVISOR = 3;
 
     /**
      * Used to request a layout when we changed touch mode
@@ -1048,7 +1058,8 @@
                 final int top = view.getTop();
                 int height = view.getHeight();
                 if (height > 0) {
-                    return Math.max(firstPosition * 100 - (top * 100) / height, 0);
+                    return Math.max(firstPosition * 100 - (top * 100) / height +
+                            (int)((float)mScrollY / getHeight() * mItemCount * 100), 0);
                 }
             } else {
                 int index;
@@ -1068,7 +1079,17 @@
 
     @Override
     protected int computeVerticalScrollRange() {
-        return mSmoothScrollbarEnabled ? Math.max(mItemCount * 100, 0) : mItemCount;
+        int result;
+        if (mSmoothScrollbarEnabled) {
+            result = Math.max(mItemCount * 100, 0);
+            if (mScrollY != 0) {
+                // Compensate for overscroll
+                result += Math.abs((int) ((float) mScrollY / getHeight() * mItemCount * 100));
+            }
+        } else {
+            result = mItemCount;
+        }
+        return result;
     }
 
     @Override
@@ -1129,6 +1150,8 @@
         mInLayout = true;
         layoutChildren();
         mInLayout = false;
+        
+        mOverscrollMax = (b - t) / OVERSCROLL_LIMIT_DIVISOR;
     }
 
     /**
@@ -2078,11 +2101,13 @@
                         // Check if the top of the motion view is where it is
                         // supposed to be
                         final int motionViewRealTop = motionView.getTop();
-                        final int motionViewNewTop = mMotionViewNewTop;
                         if (atEdge) {
                             // Apply overscroll
                             
-                            mScrollY -= incrementalDeltaY - (motionViewRealTop - motionViewPrevTop);
+                            int overscroll = -incrementalDeltaY - 
+                                    (motionViewRealTop - motionViewPrevTop);
+                            overscrollBy(0, overscroll, 0, mScrollY, 0, 0,
+                                    0, getOverscrollMax());
                             mTouchMode = TOUCH_MODE_OVERSCROLL;
                             invalidate();
                         }
@@ -2126,7 +2151,8 @@
                             mMotionPosition = motionPosition;
                         }
                     } else {
-                        mScrollY -= incrementalDeltaY;
+                        overscrollBy(0, -incrementalDeltaY, 0, mScrollY, 0, 0,
+                                0, getOverscrollMax());
                         invalidate();
                     }
                     mLastY = y;
@@ -2311,6 +2337,28 @@
 
         return true;
     }
+    
+    @Override
+    protected void onOverscrolled(int scrollX, int scrollY,
+            boolean clampedX, boolean clampedY) {
+        mScrollY = scrollY;
+        if (clampedY) {
+            // Velocity is broken by hitting the limit; don't start a fling off of this.
+            if (mVelocityTracker != null) {
+                mVelocityTracker.clear();
+            }
+        }
+    }
+    
+    private int getOverscrollMax() {
+        final int childCount = getChildCount();
+        if (childCount > 0) {
+            return Math.min(mOverscrollMax,
+                    getChildAt(childCount - 1).getBottom() / OVERSCROLL_LIMIT_DIVISOR);
+        } else {
+            return mOverscrollMax;
+        }
+    }
 
     @Override
     public void draw(Canvas canvas) {
@@ -2532,22 +2580,23 @@
                     delta = Math.max(-(getHeight() - mPaddingBottom - mPaddingTop - 1), delta);
                 }
 
-                // Do something different on overscroll - offsetChildrenTopAndBottom()
-                trackMotionScroll(delta, delta);
-
                 // Check to see if we have bumped into the scroll limit
                 View motionView = getChildAt(mMotionPosition - mFirstPosition);
+                int oldTop = 0;
                 if (motionView != null) {
-                    // Check if the top of the motion view is where it is
-                    // supposed to be
-                    if (motionView.getTop() != mMotionViewNewTop) {
-                       float vel = scroller.getCurrVelocity();
-                       if (delta > 0) {
-                           vel = -vel;
-                       }
-                       startOverfling(Math.round(vel));
-                       break;
+                    oldTop = motionView.getTop();
+                }
+                if (trackMotionScroll(delta, delta)) {
+                    if (motionView != null) {
+                        // Tweak the scroll for how far we overshot
+                        mScrollY -= delta - (motionView.getTop() - oldTop);
                     }
+                    float vel = scroller.getCurrVelocity();
+                    if (delta > 0) {
+                        vel = -vel;
+                    }
+                    startOverfling(Math.round(vel));
+                    break;
                 }
 
                 if (more) {
@@ -2570,9 +2619,14 @@
             case TOUCH_MODE_OVERFLING: {
                 final OverScroller scroller = mScroller;
                 if (scroller.computeScrollOffset()) {
-                    mScrollY = scroller.getCurrY();
-                    invalidate();
-                    post(this);
+                    final int scrollY = mScrollY;
+                    final int deltaY = scroller.getCurrY() - scrollY;
+                    if (overscrollBy(0, deltaY, 0, scrollY, 0, 0, 0, getOverscrollMax())) {
+                        startSpringback();
+                    } else {
+                        invalidate();
+                        post(this);
+                    }
                 } else {
                     endFling();
                 }
@@ -2702,6 +2756,10 @@
             case MOVE_DOWN_POS: {
                 final int lastViewIndex = getChildCount() - 1;
                 final int lastPos = firstPos + lastViewIndex;
+                
+                if (lastViewIndex < 0) {
+                    return;
+                }
 
                 if (lastPos == mLastSeenPos) {
                     // No new views, let things keep going.
@@ -2764,6 +2822,9 @@
                 }
 
                 final View firstView = getChildAt(0);
+                if (firstView == null) {
+                    return;
+                }
                 final int firstViewTop = firstView.getTop();
 
                 smoothScrollBy(firstViewTop - mExtraScroll, mScrollDuration);
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 299ed8a..9ef5e0b 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -103,6 +103,18 @@
         mMonthPicker.setFormatter(NumberPicker.TWO_DIGIT_FORMATTER);
         DateFormatSymbols dfs = new DateFormatSymbols();
         String[] months = dfs.getShortMonths();
+
+        /*
+         * If the user is in a locale where the month names are numeric,
+         * use just the number instead of the "month" character for
+         * consistency with the other fields.
+         */
+        if (months[0].startsWith("1")) {
+            for (int i = 0; i < months.length; i++) {
+                months[i] = String.valueOf(i + 1);
+            }
+        }
+
         mMonthPicker.setRange(1, 12, months);
         mMonthPicker.setSpeed(200);
         mMonthPicker.setOnChangeListener(new OnChangedListener() {
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index 57aca24..1532db1 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -16,9 +16,13 @@
 
 package android.widget;
 
-import android.text.*;
-import android.text.method.*;
 import android.content.Context;
+import android.text.Editable;
+import android.text.Selection;
+import android.text.Spannable;
+import android.text.TextUtils;
+import android.text.method.ArrowKeyMovementMethod;
+import android.text.method.MovementMethod;
 import android.util.AttributeSet;
 
 
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index 30a38df..b9acf5e 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -1856,8 +1856,11 @@
             final int top = view.getTop();
             int height = view.getHeight();
             if (height > 0) {
-                final int whichRow = mFirstPosition / mNumColumns;
-                return Math.max(whichRow * 100 - (top * 100) / height, 0);
+                final int numColumns = mNumColumns;
+                final int whichRow = mFirstPosition / numColumns;
+                final int rowCount = (mItemCount + numColumns - 1) / numColumns;
+                return Math.max(whichRow * 100 - (top * 100) / height +
+                        (int) ((float) mScrollY / getHeight() * rowCount * 100), 0);
             }
         }
         return 0;
@@ -1868,7 +1871,12 @@
         // TODO: Account for vertical spacing too
         final int numColumns = mNumColumns;
         final int rowCount = (mItemCount + numColumns - 1) / numColumns;
-        return Math.max(rowCount * 100, 0);
+        int result = Math.max(rowCount * 100, 0);
+        if (mScrollY != 0) {
+            // Compensate for overscroll
+            result += Math.abs((int) ((float) mScrollY / getHeight() * rowCount * 100));
+        }
+        return result;
     }
 }
 
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 0078fec..c62724c 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -461,7 +461,8 @@
                 final int deltaX = (int) (mLastMotionX - x);
                 mLastMotionX = x;
 
-                super.scrollTo(mScrollX + deltaX, mScrollY);
+                overscrollBy(deltaX, 0, mScrollX, 0, getScrollRange(), 0,
+                        getOverscrollMax(), 0);
                 break;
             case MotionEvent.ACTION_UP:
                 final VelocityTracker velocityTracker = mVelocityTracker;
@@ -472,8 +473,7 @@
                     if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
                         fling(-initialVelocity);
                     } else {
-                        final int right = Math.max(0, getChildAt(0).getHeight() - 
-                                (getHeight() - mPaddingRight - mPaddingLeft));
+                        final int right = getScrollRange();
                         if (mScroller.springback(mScrollX, mScrollY, 0, 0, right, 0)) {
                             invalidate();
                         }
@@ -487,6 +487,41 @@
         }
         return true;
     }
+    
+    @Override
+    protected void onOverscrolled(int scrollX, int scrollY,
+            boolean clampedX, boolean clampedY) {
+        // Treat animating scrolls differently; see #computeScroll() for why.
+        if (!mScroller.isFinished()) {
+            mScrollX = scrollX;
+            mScrollY = scrollY;
+            if (clampedX) {
+                mScroller.springback(mScrollX, mScrollY, 0, getScrollRange(), 0, 0);
+            }
+        } else {
+            super.scrollTo(scrollX, scrollY);
+        }
+    }
+    
+    private int getOverscrollMax() {
+        int childCount = getChildCount();
+        int containerOverscroll = (getWidth() - mPaddingLeft - mPaddingRight) / 3;
+        if (childCount > 0) {
+            return Math.min(containerOverscroll, getChildAt(0).getWidth() / 3);
+        } else {
+            return containerOverscroll;
+        }
+    }
+    
+    private int getScrollRange() {
+        int scrollRange = 0;
+        if (getChildCount() > 0) {
+            View child = getChildAt(0);
+            scrollRange = Math.max(0,
+                    child.getWidth() - getWidth() - mPaddingLeft - mPaddingRight);
+        }
+        return scrollRange;
+    }
 
     /**
      * <p>
@@ -856,9 +891,26 @@
     @Override
     protected int computeHorizontalScrollRange() {
         int count = getChildCount();
-        return count == 0 ? getWidth() : getChildAt(0).getRight();
+        if (count == 0) {
+            return getWidth();
+        }
+        
+        int scrollRange = getChildAt(0).getRight();
+        int scrollX = mScrollX;
+        int overscrollRight = scrollRange - getWidth() - mPaddingLeft - mPaddingRight;
+        if (scrollX < 0) {
+            scrollRange -= scrollX;
+        } else if (scrollX > overscrollRight) {
+            scrollRange += scrollX - overscrollRight;
+        }
+        
+        return scrollRange;
     }
-
+    
+    @Override
+    protected int computeHorizontalScrollOffset() {
+        return Math.max(0, super.computeHorizontalScrollOffset());
+    }
 
     @Override
     protected void measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) {
@@ -913,10 +965,9 @@
             int x = mScroller.getCurrX();
             int y = mScroller.getCurrY();
 
-            mScrollX = x;
-            mScrollY = y;
-
-            if (oldX != mScrollX || oldY != mScrollY) {
+            if (oldX != x || oldY != y) {
+                overscrollBy(x - oldX, y - oldY, oldX, oldY, getScrollRange(), 0,
+                        getOverscrollMax(), 0);
                 onScrollChanged(mScrollX, mScrollY, oldX, oldY);
             }
 
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index ea5841a..9fcb829 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -16,6 +16,8 @@
 
 package android.widget;
 
+import com.android.internal.R;
+
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
@@ -25,8 +27,6 @@
 import android.view.ViewGroup;
 import android.widget.RemoteViews.RemoteView;
 
-import com.android.internal.R;
-
 
 /**
  * A Layout that arranges its children in a single column or a single row. The direction of 
@@ -366,14 +366,15 @@
                 int oldHeight = Integer.MIN_VALUE;
 
                 if (lp.height == 0 && lp.weight > 0) {
-                   // heightMode is either UNSPECIFIED OR AT_MOST, and this child
-                   // wanted to stretch to fill available space. Translate that to
-                   // WRAP_CONTENT so that it does not end up with a height of 0
-                   oldHeight = 0;
-                   lp.height = LayoutParams.WRAP_CONTENT;
+                    // heightMode is either UNSPECIFIED or AT_MOST, and this
+                    // child wanted to stretch to fill available space.
+                    // Translate that to WRAP_CONTENT so that it does not end up
+                    // with a height of 0
+                    oldHeight = 0;
+                    lp.height = LayoutParams.WRAP_CONTENT;
                 }
 
-                // Determine how big this child would like to.  If this or
+                // Determine how big this child would like to be. If this or
                 // previous children have given a weight, then we allow it to
                 // use all available space (and we will shrink things later
                 // if needed).
@@ -673,7 +674,8 @@
                 int oldWidth = Integer.MIN_VALUE;
 
                 if (lp.width == 0 && lp.weight > 0) {
-                    // widthMode is either UNSPECIFIED OR AT_MOST, and this child
+                    // widthMode is either UNSPECIFIED or AT_MOST, and this
+                    // child
                     // wanted to stretch to fill available space. Translate that to
                     // WRAP_CONTENT so that it does not end up with a width of 0
                     oldWidth = 0;
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 401e7ff..c428dc0 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -2916,7 +2916,14 @@
 
             if (!mStackFromBottom) {
                 int bottom;
-                int listBottom = mBottom - mTop - mListPadding.bottom;
+                int listBottom = mBottom - mTop - mListPadding.bottom + mScrollY;
+                
+                // Draw top divider for overscroll
+                if (count > 0 && mScrollY < 0) {
+                    bounds.bottom = 0;
+                    bounds.top = -dividerHeight;
+                    drawDivider(canvas, bounds, -1);
+                }
 
                 for (int i = 0; i < count; i++) {
                     if ((headerDividers || first + i >= headerCount) &&
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 4a1d871..2ee7ad5 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -459,7 +459,8 @@
                 final int deltaY = (int) (mLastMotionY - y);
                 mLastMotionY = y;
 
-                super.scrollTo(mScrollX, mScrollY + deltaY);
+                overscrollBy(0, deltaY, 0, mScrollY, 0, getScrollRange(),
+                        0, getOverscrollMax());
                 break;
             case MotionEvent.ACTION_UP:
                 final VelocityTracker velocityTracker = mVelocityTracker;
@@ -470,8 +471,7 @@
                     if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
                         fling(-initialVelocity);
                     } else {
-                        final int bottom = Math.max(0, getChildAt(0).getHeight() - 
-                                (getHeight() - mPaddingBottom - mPaddingTop));
+                        final int bottom = getScrollRange();
                         if (mScroller.springback(mScrollX, mScrollY, 0, 0, 0, bottom)) {
                             invalidate();
                         }
@@ -485,6 +485,41 @@
         }
         return true;
     }
+    
+    @Override
+    protected void onOverscrolled(int scrollX, int scrollY,
+            boolean clampedX, boolean clampedY) {
+        // Treat animating scrolls differently; see #computeScroll() for why.
+        if (!mScroller.isFinished()) {
+            mScrollX = scrollX;
+            mScrollY = scrollY;
+            if (clampedY) {
+                mScroller.springback(mScrollX, mScrollY, 0, 0, 0, getScrollRange());
+            }
+        } else {
+            super.scrollTo(scrollX, scrollY);
+        }
+    }
+    
+    private int getOverscrollMax() {
+        int childCount = getChildCount();
+        int containerOverscroll = (getHeight() - mPaddingBottom - mPaddingTop) / 3;
+        if (childCount > 0) {
+            return Math.min(containerOverscroll, getChildAt(0).getHeight() / 3);
+        } else {
+            return containerOverscroll;
+        }
+    }
+    
+    private int getScrollRange() {
+        int scrollRange = 0;
+        if (getChildCount() > 0) {
+            View child = getChildAt(0);
+            scrollRange = Math.max(0,
+                    child.getHeight() - getHeight() - mPaddingBottom - mPaddingTop);
+        }
+        return scrollRange;
+    }
 
     /**
      * <p>
@@ -858,9 +893,26 @@
     @Override
     protected int computeVerticalScrollRange() {
         int count = getChildCount();
-        return count == 0 ? getHeight() : (getChildAt(0)).getBottom();
+        if (count == 0) {
+            return getHeight();
+        }
+        
+        int scrollRange = getChildAt(0).getBottom();
+        int scrollY = mScrollY;
+        int overscrollBottom = scrollRange - getHeight() - mPaddingBottom - mPaddingTop;
+        if (scrollY < 0) {
+            scrollRange -= scrollY;
+        } else if (scrollY > overscrollBottom) {
+            scrollRange += scrollY - overscrollBottom;
+        }
+        
+        return scrollRange;
     }
 
+    @Override
+    protected int computeVerticalScrollOffset() {
+        return Math.max(0, super.computeVerticalScrollOffset());
+    }
 
     @Override
     protected void measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) {
@@ -915,10 +967,9 @@
             int x = mScroller.getCurrX();
             int y = mScroller.getCurrY();
 
-            mScrollX = x;
-            mScrollY = y;
-
-            if (oldX != mScrollX || oldY != mScrollY) {
+            if (oldX != x || oldY != y) {
+                overscrollBy(x - oldX, y - oldY, oldX, oldY, 0, getScrollRange(),
+                        0, getOverscrollMax());
                 onScrollChanged(mScrollX, mScrollY, oldX, oldY);
             }
             
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index 78e2fee..d4d9063 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -16,6 +16,8 @@
 
 package android.widget;
 
+import com.android.internal.R;
+
 import android.app.LocalActivityManager;
 import android.content.Context;
 import android.content.Intent;
@@ -33,8 +35,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import com.android.internal.R;
-
 /**
  * Container for a tabbed window view. This object holds two children: a set of tab labels that the
  * user clicks to select a specific tab, and a FrameLayout object that displays the contents of that
@@ -624,7 +624,7 @@
         }
 
         public void tabClosed() {
-            mTabContent.setVisibility(View.INVISIBLE);
+            mTabContent.setVisibility(View.GONE);
         }
     }
 
diff --git a/core/java/android/widget/TableLayout.java b/core/java/android/widget/TableLayout.java
index 66500a3..73760ac 100644
--- a/core/java/android/widget/TableLayout.java
+++ b/core/java/android/widget/TableLayout.java
@@ -575,6 +575,16 @@
         final int totalExtraSpace = size - totalWidth;
         int extraSpace = totalExtraSpace / count;
 
+        // Column's widths are changed: force child table rows to re-measure.
+        // (done by super.measureVertical after shrinkAndStretchColumns.)
+        final int nbChildren = getChildCount();
+        for (int i = 0; i < nbChildren; i++) {
+            View child = getChildAt(i);
+            if (child instanceof TableRow) {
+                child.forceLayout();
+            }
+        }
+
         if (!allColumns) {
             for (int i = 0; i < count; i++) {
                 int column = columns.keyAt(i);
diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java
index abf08bf..48d12df 100644
--- a/core/java/android/widget/TableRow.java
+++ b/core/java/android/widget/TableRow.java
@@ -22,8 +22,8 @@
 import android.util.SparseIntArray;
 import android.view.Gravity;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.ViewDebug;
+import android.view.ViewGroup;
 
 
 /**
diff --git a/core/java/com/android/internal/app/IMediaContainerService.aidl b/core/java/com/android/internal/app/IMediaContainerService.aidl
index 726e28f..c0e9587 100755
--- a/core/java/com/android/internal/app/IMediaContainerService.aidl
+++ b/core/java/com/android/internal/app/IMediaContainerService.aidl
@@ -25,4 +25,5 @@
                 String key, String resFileName);
     boolean copyResource(in Uri packageURI,
                 in ParcelFileDescriptor outStream);
+    int getRecommendedInstallLocation(in Uri fileUri);
 }
\ No newline at end of file
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
new file mode 100644
index 0000000..4d7d2d1
--- /dev/null
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -0,0 +1,28 @@
+/*
+ * 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 com.android.internal.content;
+
+/**
+ * Constants used internally between the PackageManager
+ * and media container service transports.
+ */
+public class PackageHelper {
+    public static final int RECOMMEND_INSTALL_INTERNAL = 1;
+    public static final int RECOMMEND_INSTALL_EXTERNAL = 2;
+    public static final int RECOMMEND_FAILED_INSUFFICIENT_STORAGE = -1;
+    public static final int RECOMMEND_FAILED_INVALID_APK = -2;
+}
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 57a28e6..c134d88 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -22,7 +22,6 @@
 import android.os.Build;
 import android.os.Debug;
 import android.os.IBinder;
-import android.os.ICheckinService;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 631e7d8..da0c5a2 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -295,7 +295,10 @@
         /** from --peer-wait */
         boolean peerWait;
 
-        /** from --enable-debugger, --enable-checkjni, --enable-assert */
+        /**
+         * From --enable-debugger, --enable-checkjni, --enable-assert, and
+         * --enable-safemode
+         */
         int debugFlags;
 
         /** from --classpath */
@@ -363,6 +366,8 @@
                             arg.substring(arg.indexOf('=') + 1));
                 } else if (arg.equals("--enable-debugger")) {
                     debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
+                } else if (arg.equals("--enable-safemode")) {
+                    debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
                 } else if (arg.equals("--enable-checkjni")) {
                     debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
                 } else if (arg.equals("--enable-assert")) {
diff --git a/core/java/com/android/internal/widget/PasswordEntryKeyboard.java b/core/java/com/android/internal/widget/PasswordEntryKeyboard.java
index 51f7f69..e1a6737 100644
--- a/core/java/com/android/internal/widget/PasswordEntryKeyboard.java
+++ b/core/java/com/android/internal/widget/PasswordEntryKeyboard.java
@@ -93,7 +93,7 @@
         LatinKey key = new LatinKey(res, parent, x, y, parser);
         final int code = key.codes[0];
         if (code >=0 && code != '\n' && (code < 32 || code > 127)) {
-            Log.w(TAG, "Key code for " + key.label + " is not latin-1");
+            // Log.w(TAG, "Key code for " + key.label + " is not latin-1");
             key.label = " ";
             key.setEnabled(false);
         }
@@ -216,61 +216,6 @@
         }
     }
 
-    /**
-     * Sets keyboard extension. Keyboard extension is shown when input is detected above keyboard
-     * while keyboard has focus.
-     *
-     * @param resId
-     */
-    public void setExtension(int resId) {
-        mExtensionResId = resId;
-    }
-
-    /**
-     * Get current extesion resource id.
-     *
-     * @return resource id, 0 if not set.
-     */
-    public int getExtension() {
-        return mExtensionResId;
-    }
-
-    private void updateSpaceBarForLocale() {
-        if (mLocale != null) {
-            // Create the graphic for spacebar
-            Bitmap buffer = Bitmap.createBitmap(mSpaceKey.width, mSpaceIcon.getIntrinsicHeight(),
-                    Bitmap.Config.ARGB_8888);
-            Canvas canvas = new Canvas(buffer);
-            canvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
-            Paint paint = new Paint();
-            paint.setAntiAlias(true);
-            // TODO: Make the text size a customizable attribute
-            paint.setTextSize(22);
-            paint.setTextAlign(Align.CENTER);
-            // Draw a drop shadow for the text
-            paint.setShadowLayer(1f, 0, 0, 0xFF000000);
-            paint.setColor(0x80C0C0C0);
-            canvas.drawText(mLocale.getDisplayLanguage(mLocale),
-                    buffer.getWidth() / 2, - paint.ascent() + 2, paint);
-            int x = (buffer.getWidth() - mSpaceIcon.getIntrinsicWidth()) / 2;
-            int y = buffer.getHeight() - mSpaceIcon.getIntrinsicHeight();
-            mSpaceIcon.setBounds(x, y,
-                    x + mSpaceIcon.getIntrinsicWidth(), y + mSpaceIcon.getIntrinsicHeight());
-            mSpaceIcon.draw(canvas);
-            mSpaceKey.icon = new BitmapDrawable(mRes, buffer);
-            mSpaceKey.repeatable = false;
-        } else {
-            mSpaceKey.icon = mRes.getDrawable(R.drawable.sym_keyboard_space);
-            mSpaceKey.repeatable = true;
-        }
-    }
-
-    public void setLanguage(Locale locale) {
-        if (mLocale != null && mLocale.equals(locale)) return;
-        mLocale = locale;
-        updateSpaceBarForLocale();
-    }
-
     static class LatinKey extends Keyboard.Key {
         private boolean mShiftLockEnabled;
         private boolean mEnabled = true;
diff --git a/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java b/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java
index b809afc..c2862b0 100644
--- a/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java
+++ b/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java
@@ -22,15 +22,11 @@
 import android.inputmethodservice.KeyboardView.OnKeyboardActionListener;
 import android.os.Handler;
 import android.os.SystemClock;
-import android.text.Editable;
-import android.text.Selection;
-import android.util.Log;
+import android.provider.Settings;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewRoot;
-import android.view.inputmethod.InputConnection;
-import android.widget.EditText;
 import com.android.internal.R;
 
 public class PasswordEntryKeyboardHelper implements OnKeyboardActionListener {
@@ -40,7 +36,6 @@
     private static final int KEYBOARD_STATE_NORMAL = 0;
     private static final int KEYBOARD_STATE_SHIFTED = 1;
     private static final int KEYBOARD_STATE_CAPSLOCK = 2;
-    private static final String TAG = "PasswordEntryKeyboardHelper";
     private int mKeyboardMode = KEYBOARD_MODE_ALPHA;
     private int mKeyboardState = KEYBOARD_STATE_NORMAL;
     private PasswordEntryKeyboard mQwertyKeyboard;
@@ -90,10 +85,15 @@
             case KEYBOARD_MODE_ALPHA:
                 mKeyboardView.setKeyboard(mQwertyKeyboard);
                 mKeyboardState = KEYBOARD_STATE_NORMAL;
+                final boolean visiblePassword = Settings.System.getInt(
+                        mContext.getContentResolver(),
+                        Settings.System.TEXT_SHOW_PASSWORD, 1) != 0;
+                mKeyboardView.setPreviewEnabled(visiblePassword);
                 break;
             case KEYBOARD_MODE_NUMERIC:
                 mKeyboardView.setKeyboard(mNumericKeyboard);
                 mKeyboardState = KEYBOARD_STATE_NORMAL;
+                mKeyboardView.setPreviewEnabled(false); // never show popup for numeric keypad
                 break;
         }
         mKeyboardMode = mode;
@@ -122,7 +122,6 @@
     }
 
     public void onKey(int primaryCode, int[] keyCodes) {
-        Log.v(TAG, "Key code = " + Integer.toHexString(primaryCode));
         if (primaryCode == Keyboard.KEYCODE_DELETE) {
             handleBackspace();
         } else if (primaryCode == Keyboard.KEYCODE_SHIFT) {
@@ -201,7 +200,7 @@
     }
 
     public void onPress(int primaryCode) {
-
+        // TODO: vibration support.
     }
 
     public void onRelease(int primaryCode) {
diff --git a/core/java/com/android/internal/widget/PasswordEntryKeyboardView.java b/core/java/com/android/internal/widget/PasswordEntryKeyboardView.java
index 9b93fc2..3e6f6f3 100644
--- a/core/java/com/android/internal/widget/PasswordEntryKeyboardView.java
+++ b/core/java/com/android/internal/widget/PasswordEntryKeyboardView.java
@@ -17,27 +17,17 @@
 package com.android.internal.widget;
 
 import android.content.Context;
-import android.inputmethodservice.Keyboard;
 import android.inputmethodservice.KeyboardView;
 import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.widget.PopupWindow;
-import com.android.internal.R;
 
 public class PasswordEntryKeyboardView extends KeyboardView {
 
-    public static final int KEYCODE_OPTIONS = -100;
+    static final int KEYCODE_OPTIONS = -100;
     static final int KEYCODE_SHIFT_LONGPRESS = -101;
     static final int KEYCODE_VOICE = -102;
     static final int KEYCODE_F1 = -103;
     static final int KEYCODE_NEXT_LANGUAGE = -104;
 
-    private boolean mExtensionVisible;
-    private PasswordEntryKeyboardView mExtension;
-    private PopupWindow mExtensionPopup;
-    private boolean mFirstEvent;
-
     public PasswordEntryKeyboardView(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
@@ -46,107 +36,4 @@
         super(context, attrs, defStyle);
     }
 
-    @Override
-    public boolean onTouchEvent(MotionEvent me) {
-        if (((PasswordEntryKeyboard) getKeyboard()).getExtension() == 0) {
-            return super.onTouchEvent(me);
-        }
-        if (me.getY() < 0) {
-            if (mExtensionVisible) {
-                int action = me.getAction();
-                if (mFirstEvent) action = MotionEvent.ACTION_DOWN;
-                mFirstEvent = false;
-                MotionEvent translated = MotionEvent.obtain(me.getEventTime(), me.getEventTime(),
-                        action,
-                        me.getX(), me.getY() + mExtension.getHeight(), me.getMetaState());
-                boolean result = mExtension.onTouchEvent(translated);
-                translated.recycle();
-                if (me.getAction() == MotionEvent.ACTION_UP
-                        || me.getAction() == MotionEvent.ACTION_CANCEL) {
-                    closeExtension();
-                }
-                return result;
-            } else {
-                if (openExtension()) {
-                    MotionEvent cancel = MotionEvent.obtain(me.getDownTime(), me.getEventTime(),
-                            MotionEvent.ACTION_CANCEL, me.getX() - 100, me.getY() - 100, 0);
-                    super.onTouchEvent(cancel);
-                    cancel.recycle();
-                    if (mExtension.getHeight() > 0) {
-                        MotionEvent translated = MotionEvent.obtain(me.getEventTime(),
-                                me.getEventTime(),
-                                MotionEvent.ACTION_DOWN,
-                                me.getX(), me.getY() + mExtension.getHeight(),
-                                me.getMetaState());
-                        mExtension.onTouchEvent(translated);
-                        translated.recycle();
-                    } else {
-                        mFirstEvent = true;
-                    }
-                }
-                return true;
-            }
-        } else if (mExtensionVisible) {
-            closeExtension();
-            // Send a down event into the main keyboard first
-            MotionEvent down = MotionEvent.obtain(me.getEventTime(), me.getEventTime(),
-                    MotionEvent.ACTION_DOWN, me.getX(), me.getY(), me.getMetaState());
-            super.onTouchEvent(down);
-            down.recycle();
-            // Send the actual event
-            return super.onTouchEvent(me);
-        } else {
-            return super.onTouchEvent(me);
-        }
-    }
-
-    private boolean openExtension() {
-        if (((PasswordEntryKeyboard) getKeyboard()).getExtension() == 0) return false;
-        makePopupWindow();
-        mExtensionVisible = true;
-        return true;
-    }
-
-    private void makePopupWindow() {
-        if (mExtensionPopup == null) {
-            int[] windowLocation = new int[2];
-            mExtensionPopup = new PopupWindow(getContext());
-            mExtensionPopup.setBackgroundDrawable(null);
-            LayoutInflater li = (LayoutInflater) getContext().getSystemService(
-                    Context.LAYOUT_INFLATER_SERVICE);
-            mExtension = (PasswordEntryKeyboardView) li.inflate(
-                    R.layout.password_keyboard_input, null);
-            mExtension.setOnKeyboardActionListener(getOnKeyboardActionListener());
-            mExtension.setPopupParent(this);
-            mExtension.setPopupOffset(0, -windowLocation[1]);
-            Keyboard keyboard;
-            mExtension.setKeyboard(keyboard = new PasswordEntryKeyboard(getContext(),
-                    ((PasswordEntryKeyboard) getKeyboard()).getExtension()));
-            mExtensionPopup.setContentView(mExtension);
-            mExtensionPopup.setWidth(getWidth());
-            mExtensionPopup.setHeight(keyboard.getHeight());
-            getLocationInWindow(windowLocation);
-            // TODO: Fix the "- 30".
-            mExtension.setPopupOffset(0, -windowLocation[1] - 30);
-            mExtensionPopup.showAtLocation(this, 0, 0, -keyboard.getHeight()
-                    + windowLocation[1]);
-        } else {
-            mExtension.setVisibility(VISIBLE);
-        }
-    }
-
-    @Override
-    public void closing() {
-        super.closing();
-        if (mExtensionPopup != null && mExtensionPopup.isShowing()) {
-            mExtensionPopup.dismiss();
-            mExtensionPopup = null;
-        }
-    }
-
-    private void closeExtension() {
-        mExtension.setVisibility(INVISIBLE);
-        mExtension.closing();
-        mExtensionVisible = false;
-    }
 }
diff --git a/core/java/com/google/android/net/ParentalControl.java b/core/java/com/google/android/net/ParentalControl.java
deleted file mode 100644
index 71a3958..0000000
--- a/core/java/com/google/android/net/ParentalControl.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-package com.google.android.net;
-
-import android.os.ICheckinService;
-import android.os.IParentalControlCallback;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.util.Log;
-
-public class ParentalControl {
-    /**
-     * Strings to identify your app. To enable parental control checking for
-     * new apps, please add it here, and configure GServices accordingly.
-     */
-    public static final String VENDING = "vending";
-    public static final String YOUTUBE = "youtube";
-
-    /**
-     * This interface is supplied to getParentalControlState and is callback upon with
-     * the state of parental control.
-     */
-    public interface Callback {
-        /**
-         * This method will be called when the state of parental control is known. If state is
-         * null, then the state of parental control is unknown.
-         * @param state The state of parental control.
-         */
-        void onResult(ParentalControlState state);
-    }
-
-    private static class RemoteCallback extends IParentalControlCallback.Stub {
-        private Callback mCallback;
-
-        public RemoteCallback(Callback callback) {
-            mCallback = callback;
-        }
-
-        public void onResult(ParentalControlState state) {
-            if (mCallback != null) {
-                mCallback.onResult(state);
-            }
-        }
-    };
-
-    public static void getParentalControlState(Callback callback,
-                                               String requestingApp) {
-        ICheckinService service =
-          ICheckinService.Stub.asInterface(ServiceManager.getService("checkin"));
-
-        RemoteCallback remoteCallback = new RemoteCallback(callback);
-        try {
-            service.getParentalControlState(remoteCallback, requestingApp);
-        } catch (RemoteException e) {
-            // This should never happen.
-            Log.e("ParentalControl", "Failed to talk to the checkin service.");
-        }
-    }
-}
diff --git a/core/java/com/google/android/net/ParentalControlState.aidl b/core/java/com/google/android/net/ParentalControlState.aidl
deleted file mode 100644
index ed1326a..0000000
--- a/core/java/com/google/android/net/ParentalControlState.aidl
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * Copyright (c) 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.
- */
-
-package com.google.android.net;
-parcelable ParentalControlState;
diff --git a/core/java/com/google/android/net/ParentalControlState.java b/core/java/com/google/android/net/ParentalControlState.java
deleted file mode 100644
index 162a1f6..0000000
--- a/core/java/com/google/android/net/ParentalControlState.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-package com.google.android.net;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-public class ParentalControlState implements Parcelable {
-    public boolean isEnabled;
-    public String redirectUrl;
-
-    /**
-     * Used to read a ParentalControlStatus from a Parcel.
-     */
-    public static final Parcelable.Creator<ParentalControlState> CREATOR =
-        new Parcelable.Creator<ParentalControlState>() {
-              public ParentalControlState createFromParcel(Parcel source) {
-                    ParentalControlState status = new ParentalControlState();
-                    status.isEnabled = (source.readInt() == 1);
-                    status.redirectUrl = source.readString();
-                    return status;
-              }
-
-              public ParentalControlState[] newArray(int size) {
-                  return new ParentalControlState[size];
-              }
-        };
-
-    public int describeContents() {
-        return 0;
-    }
-
-    public void writeToParcel(Parcel dest, int flags) {
-      dest.writeInt(isEnabled ? 1 : 0);
-      dest.writeString(redirectUrl);
-    }
-
-    @Override
-    public String toString() {
-        return isEnabled + ", " + redirectUrl;
-    }
-};
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 1ffd265..e8749ed 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -159,6 +159,8 @@
 	libbinder \
 	libnetutils \
 	libui \
+	libsurfaceflinger_client \
+	libcamera_client \
 	libskiagl \
 	libskia \
 	libsqlite \
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 03107a4..9c0e282 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -25,8 +25,8 @@
 
 #include <utils/Vector.h>
 
-#include <ui/Surface.h>
-#include <ui/Camera.h>
+#include <surfaceflinger/Surface.h>
+#include <camera/Camera.h>
 #include <binder/IMemory.h>
 
 using namespace android;
diff --git a/core/jni/android_text_AndroidCharacter.cpp b/core/jni/android_text_AndroidCharacter.cpp
index 450cee2..05d7b73 100644
--- a/core/jni/android_text_AndroidCharacter.cpp
+++ b/core/jni/android_text_AndroidCharacter.cpp
@@ -20,8 +20,32 @@
 #include <jni.h>
 #include <android_runtime/AndroidRuntime.h>
 #include "utils/misc.h"
-#include "utils/AndroidUnicode.h"
 #include "utils/Log.h"
+#include "unicode/uchar.h"
+
+#define DIRECTIONALITY_UNDEFINED (-1)
+// ICU => JDK mapping
+static int directionality_map[U_CHAR_DIRECTION_COUNT] = {
+    0, // U_LEFT_TO_RIGHT (0) => DIRECTIONALITY_LEFT_TO_RIGHT (0)
+    1, // U_RIGHT_TO_LEFT (1) => DIRECTIONALITY_RIGHT_TO_LEFT (1)
+    3, // U_EUROPEAN_NUMBER (2) => DIRECTIONALITY_EUROPEAN_NUMBER (3)
+    4, // U_EUROPEAN_NUMBER_SEPARATOR (3) => DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR (4)
+    5, // U_EUROPEAN_NUMBER_TERMINATOR (4) => DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR (5)
+    6, // U_ARABIC_NUMBER (5) => DIRECTIONALITY_ARABIC_NUMBER (6)
+    7, // U_COMMON_NUMBER_SEPARATOR (6) => DIRECTIONALITY_COMMON_NUMBER_SEPARATOR (7)
+    10, // U_BLOCK_SEPARATOR (7) => DIRECTIONALITY_PARAGRAPH_SEPARATOR (10)
+    11, // U_SEGMENT_SEPARATOR (8) => DIRECTIONALITY_SEGMENT_SEPARATOR (11)
+    12, // U_WHITE_SPACE_NEUTRAL (9) => DIRECTIONALITY_WHITESPACE (12)
+    13, // U_OTHER_NEUTRAL (10) => DIRECTIONALITY_OTHER_NEUTRALS (13)
+    14, // U_LEFT_TO_RIGHT_EMBEDDING (11) => DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING (14)
+    15, // U_LEFT_TO_RIGHT_OVERRIDE (12) => DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE (15)
+    2, // U_RIGHT_TO_LEFT_ARABIC (13) => DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC (2)
+    16, // U_RIGHT_TO_LEFT_EMBEDDING (14) => DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING (16)
+    17, // U_RIGHT_TO_LEFT_OVERRIDE (15) => DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE (17)
+    18, // U_POP_DIRECTIONAL_FORMAT (16) => DIRECTIONALITY_POP_DIRECTIONAL_FORMAT (18)
+    8, // U_DIR_NON_SPACING_MARK (17) => DIRECTIONALITY_NONSPACING_MARK (8)
+    9, // U_BOUNDARY_NEUTRAL (18) => DIRECTIONALITY_BOUNDARY_NEUTRAL (9)
+};
 
 namespace android {
     
@@ -53,15 +77,21 @@
             src[i + 1] >= 0xDC00 && src[i + 1] <= 0xDFFF) {
             int c = 0x00010000 + ((src[i] - 0xD800) << 10) +
                                  (src[i + 1] & 0x3FF);
-            int dir = android::Unicode::getDirectionality(c);
+            int dir = u_charDirection(c);
+            if (dir < 0 || dir >= U_CHAR_DIRECTION_COUNT)
+                dir = DIRECTIONALITY_UNDEFINED;
+            else
+                dir = directionality_map[dir];
 
             dest[i++] = dir;
             dest[i] = dir;
         } else {
             int c = src[i];
-            int dir = android::Unicode::getDirectionality(c);
-
-            dest[i] = dir;
+            int dir = u_charDirection(c);
+            if (dir < 0 || dir >= U_CHAR_DIRECTION_COUNT)
+                dest[i] = DIRECTIONALITY_UNDEFINED;
+            else
+                dest[i] = directionality_map[dir];
         }
     }
     
@@ -89,7 +119,7 @@
         // XXX this thinks it knows that surrogates are never mirrored
 
         int c1 = data[i];
-        int c2 = android::Unicode::toMirror(c1);
+        int c2 = u_charMirror(c1);
 
         if (c1 != c2) {
             data[i] = c2;
@@ -104,7 +134,7 @@
 
 static jchar getMirror(JNIEnv* env, jobject obj, jchar c)
 {   
-    return android::Unicode::toMirror(c);
+    return u_charMirror(c);
 }
 
 static JNINativeMethod gMethods[] = {
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 2fff727..a82a21e 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -537,7 +537,8 @@
                                                           jint keyboard, jint keyboardHidden,
                                                           jint navigation,
                                                           jint screenWidth, jint screenHeight,
-                                                          jint screenLayout, jint sdkVersion)
+                                                          jint screenLayout, jint uiMode,
+                                                          jint sdkVersion)
 {
     AssetManager* am = assetManagerForJavaObject(env, clazz);
     if (am == NULL) {
@@ -560,6 +561,7 @@
     config.screenWidth = (uint16_t)screenWidth;
     config.screenHeight = (uint16_t)screenHeight;
     config.screenLayout = (uint8_t)screenLayout;
+    config.uiMode = (uint8_t)uiMode;
     config.sdkVersion = (uint16_t)sdkVersion;
     config.minorVersion = 0;
     am->setConfiguration(config, locale8);
@@ -1614,7 +1616,7 @@
         (void*) android_content_AssetManager_setLocale },
     { "getLocales",      "()[Ljava/lang/String;",
         (void*) android_content_AssetManager_getLocales },
-    { "setConfiguration", "(IILjava/lang/String;IIIIIIIIII)V",
+    { "setConfiguration", "(IILjava/lang/String;IIIIIIIIIII)V",
         (void*) android_content_AssetManager_setConfiguration },
     { "getResourceIdentifier","(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
         (void*) android_content_AssetManager_getResourceIdentifier },
diff --git a/core/jni/android_view_Display.cpp b/core/jni/android_view_Display.cpp
index bb7b5ef..2e160ae 100644
--- a/core/jni/android_view_Display.cpp
+++ b/core/jni/android_view_Display.cpp
@@ -17,7 +17,7 @@
 #include <stdio.h>
 #include <assert.h>
 
-#include <ui/SurfaceComposerClient.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
 #include <ui/PixelFormat.h>
 #include <ui/DisplayInfo.h>
 
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 40c8aa0..723205a 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -18,7 +18,7 @@
 
 #include "android_util_Binder.h"
 
-#include <ui/SurfaceComposerClient.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
 #include <ui/Region.h>
 #include <ui/Rect.h>
 
diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
index 974fc0b..6a8c4b9 100644
--- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
@@ -21,7 +21,7 @@
 #include <EGL/egl.h>
 #include <GLES/gl.h>
 
-#include <ui/Surface.h>
+#include <surfaceflinger/Surface.h>
 #include <SkBitmap.h>
 #include <SkPixelRef.h>
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 713e7258..8273dbf 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -244,6 +244,14 @@
         android:description="@string/permdesc_writeHistoryBookmarks"
         android:protectionLevel="dangerous" />
 
+    <!-- Allows an application to write to (but not read) the user's
+         geolocation permissions.. -->
+    <permission android:name="com.android.browser.permission.WRITE_GEOLOCATION_PERMISSIONS"
+        android:permissionGroup="android.permission-group.LOCATION"
+        android:label="@string/permlab_writeGeolocationPermissions"
+        android:description="@string/permdesc_writeGeolocationPermissions"
+        android:protectionLevel="signatureOrSystem" />
+
     <!-- ======================================= -->
     <!-- Permissions for accessing location info -->
     <!-- ======================================= -->
@@ -556,6 +564,14 @@
         android:label="@string/permlab_changeConfiguration"
         android:description="@string/permdesc_changeConfiguration" />
 
+    <!-- Allows an application to enable the car mode.
+         @hide -->
+    <permission android:name="android.permission.ENABLE_CAR_MODE"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="signature"
+        android:label="@string/permlab_enableCarMode"
+        android:description="@string/permdesc_enableCarMode" />
+
     <!-- @deprecated The {@link android.app.ActivityManager#restartPackage}
         API is no longer supported. -->
     <permission android:name="android.permission.RESTART_PACKAGES"
@@ -1145,13 +1161,6 @@
         android:description="@string/permdesc_backup"
         android:protectionLevel="signatureOrSystem" />
 
-    <!-- Allows an application to participate in the backup and restore process
-         @hide -->
-    <permission android:name="android.permission.BACKUP_DATA"
-        android:label="@string/permlab_backup_data"
-        android:description="@string/permdesc_backup_data"
-        android:protectionLevel="signatureOrSystem" />
-
     <!-- Allows an application to tell the AppWidget service which application
          can access AppWidget's data.  The normal user flow is that a user
          picks an AppWidget to go into a particular host, thereby giving that
@@ -1249,11 +1258,7 @@
                 android:theme="@style/Theme.Dialog.Alert"
                 android:excludeFromRecents="true">
         </activity>
-        <activity android:name="com.android.internal.app.UsbStorageActivity"
-                android:excludeFromRecents="true">
-        </activity>
-        <activity android:name="com.android.internal.app.UsbStorageStopActivity"
-                android:theme="@style/Theme.Dialog.Alert"
+        <activity android:name="com.android.server.status.UsbStorageActivity"
                 android:excludeFromRecents="true">
         </activity>
         <activity android:name="com.android.internal.app.ExternalMediaFormatActivity"
@@ -1300,6 +1305,10 @@
         <receiver android:name="com.android.server.MasterClearReceiver"
             android:permission="android.permission.MASTER_CLEAR" >
             <intent-filter>
+                <!-- For Checkin, Settings, etc.: action=MASTER_CLEAR -->
+                <action android:name="android.intent.action.MASTER_CLEAR" />
+
+                <!-- MCS always uses REMOTE_INTENT: category=MASTER_CLEAR -->
                 <action android:name="android.intent.action.REMOTE_INTENT" />
                 <category android:name="android.intent.category.MASTER_CLEAR" />
             </intent-filter>
diff --git a/core/res/res/anim/cycle_interpolator.xml b/core/res/res/anim/cycle_interpolator.xml
new file mode 100644
index 0000000..70ebcb1
--- /dev/null
+++ b/core/res/res/anim/cycle_interpolator.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<cycleInterpolator />
diff --git a/core/res/res/layout/keyguard_screen_password_landscape.xml b/core/res/res/layout/keyguard_screen_password_landscape.xml
index b089df6..ab675c7 100644
--- a/core/res/res/layout/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_password_landscape.xml
@@ -37,7 +37,7 @@
             android:layout_marginLeft="6dip"
             android:layout_marginTop="10dip"
             android:layout_marginBottom="10dip"
-            android:gravity="center"
+            android:gravity="left"
             android:ellipsize="marquee"
             android:text="@android:string/keyguard_password_enter_password_code"
             android:textAppearance="?android:attr/textAppearanceLarge"
@@ -53,7 +53,7 @@
             android:inputType="textPassword"
             android:gravity="center"
             android:layout_gravity="center"
-            android:textSize="32sp"
+            android:textSize="24sp"
             android:textAppearance="?android:attr/textAppearanceLarge"
             android:background="@drawable/password_field_default"
             android:textColor="#ffffffff"
diff --git a/core/res/res/layout/password_keyboard_input.xml b/core/res/res/layout/password_keyboard_input.xml
deleted file mode 100755
index e40b69e..0000000
--- a/core/res/res/layout/password_keyboard_input.xml
+++ /dev/null
@@ -1,29 +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.
-*/
--->
-
-<com.android.passwordunlockdemo.LatinKeyboardView
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@android:id/keyboardView"
-        android:layout_alignParentBottom="true"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:background="#00000000"
-        android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
-        />
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 794a9f0..ff8cdc9 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1452,7 +1452,7 @@
          included in that tag. -->
     <declare-styleable name="InputMethod">
         <!-- Component name of an activity that allows the user to modify
-             the settings for this input method. -->
+             the settings for this service. -->
         <attr name="settingsActivity" format="string" />
         <!-- Set to true in all of the configurations for which this input
              method should be considered an option as the default. -->
@@ -3494,8 +3494,6 @@
          meta-data entry.  Described here are the attributes that can be
          included in that tag. -->
     <declare-styleable name="Wallpaper">
-        <!-- Component name of an activity that allows the user to modify
-             the current settings for this wallpaper. -->
         <attr name="settingsActivity" />
 
         <!-- Reference to a the wallpaper's thumbnail bitmap. -->
@@ -3586,5 +3584,13 @@
         <!-- Use "horizontal" for a row, "vertical" for a column.  The default is horizontal. -->
         <attr name="orientation" />
     </declare-styleable>
+    
+    <!-- Use <code>recognition-service</code> as the root tag of the XML resource that
+         describes a {@link android.speech.RecognitionService}, which is reference from
+         its {@link android.speech.RecognitionService#SERVICE_META_DATA} meta-data entry.
+         Described here are the attributes that can be included in that tag. -->
+    <declare-styleable name="RecognitionService">
+        <attr name="settingsActivity" />
+    </declare-styleable>
 
 </resources>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 54781e3..70bc000 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -215,6 +215,10 @@
          running on a device that is running in user mode. -->
     <attr name="debuggable" format="boolean" />
     
+    <!-- Flag indicating whether the application requests the VM to operate in
+         the safe mode.  -->
+    <attr name="safeMode" format="boolean" />
+
     <!-- Flag indicating whether the given application component is available
          to other applications.  If false, it can only be accessed by
          applications with its same user id (which usually means only by
@@ -600,6 +604,20 @@
          Application class to avoid interference with application logic. -->
     <attr name="restoreNeedsApplication" format="boolean" />
 
+    <!-- The default install location defined by an application. -->
+    <attr name="installLocation">
+        <!-- Let the system decide ideal install location -->
+        <enum name="auto" value="0" />
+        <!-- Explicitly request to be installed on internal phone storate
+             only. -->
+        <enum name="internalOnly" value="1" />
+        <!-- Prefer to be installed on sdcard. There is no guarantee that
+             the system will honour this request. The application might end
+             up being installed on internal storage if external media
+             is unavailable or too full. -->
+        <enum name="preferExternal" value="2" />
+    </attr>
+
     <!-- The <code>manifest</code> tag is the root of an
          <code>AndroidManifest.xml</code> file,
          describing the contents of an Android package (.apk) file.  One
@@ -624,6 +642,7 @@
         <attr name="versionName" />
         <attr name="sharedUserId" />
         <attr name="sharedUserLabel" />
+        <attr name="installLocation" />
     </declare-styleable>
     
     <!-- The <code>application</code> tag describes application-level components
@@ -670,6 +689,7 @@
              override the component specific values). -->
         <attr name="enabled" />
         <attr name="debuggable" />
+        <attr name="safeMode" />
         <!-- Name of activity to be launched for managing the application's space on the device. -->
         <attr name="manageSpaceActivity" />
         <attr name="allowClearUserData" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 46d6352..40c78f7 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -138,6 +138,11 @@
         <item>30</item>
     </integer-array>
 
+    <!-- Vibrator pattern for a very short but reliable vibration for soft keyboard tap -->
+    <integer-array name="config_keyboardTapVibePattern">
+        <item>40</item>
+    </integer-array>
+
     <!-- Vibrator pattern for feedback about booting with safe mode disabled -->
     <integer-array name="config_safeModeDisabledVibePattern">
         <item>0</item>
@@ -156,6 +161,14 @@
         <item>600</item>
     </integer-array>
 
+    <!-- Vibrator pattern for feedback about hitting a scroll barrier -->
+    <integer-array name="config_scrollBarrierVibePattern">
+        <item>0</item>
+        <item>15</item>
+        <item>10</item>
+        <item>10</item>
+    </integer-array>
+
     <bool name="config_use_strict_phone_number_comparation">false</bool>
 
     <!-- Display low battery warning when battery level dips to this value -->
@@ -237,8 +250,4 @@
 
     <!-- Component name of the service providing geocoder API support. -->
     <string name="config_geocodeProvider">@null</string>
-
-    <!-- Flag indicating whether headset events are used by kernel to indicate
-    TTY mode changes. -->
-    <bool name="tty_mode_uses_headset_events">false</bool>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index bd4a3eb..3c6338e 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1224,9 +1224,13 @@
   <public type="attr" name="expandableListViewWhiteStyle" id="0x010102b6" />
 
 <!-- ===============================================================
-     Resources proposed for Flan.
+     Resources proposed for Froyo.
      =============================================================== -->
   <eat-comment />
   <public type="attr" name="neverEncrypt" id="0x010102b7" />
+  <public type="attr" name="installLocation" id="0x010102b8" />
+  <public type="attr" name="safeMode" id="0x010102b9" />
+
+  <public type="anim" name="cycle_interpolator" id="0x010a000c" />
     
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 89cbd08..6f34b4f 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -462,6 +462,12 @@
         size.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_enableCarMode">enable car mode</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_enableCarMode">Allows an application to
+        enable the car mode.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_killBackgroundProcesses">kill background processes</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_killBackgroundProcesses">Allows an application to
@@ -559,11 +565,6 @@
     <string name="permdesc_backup">Allows the application to control the system\'s backup and restore mechanism.  Not for use by normal applications.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permlab_backup_data">back up and restore the application\'s data</string>
-    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permdesc_backup_data">Allows the application to participate in the system\'s backup and restore mechanism.</string>
-
-    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_internalSystemWindow">display unauthorized windows</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_internalSystemWindow">Allows the creation of
@@ -1212,16 +1213,11 @@
     <string name="policydesc_resetPassword">Force your password
         to a new value, requiring the administrator give it to you
         before you can log in.</string>
-    <!-- Title of policy access to limiting the user's unlock timeout -->
-    <string name="policylab_limitUnlock">Limit lock timeout</string>
-    <!-- Description of policy access to limiting the user's unlock timeout -->
-    <string name="policydesc_limitUnlock">Restrict the unlock timeout
-        durations you can select.</string>
     <!-- Title of policy access to force lock the device -->
     <string name="policylab_forceLock">Force lock</string>
     <!-- Description of policy access to limiting the user's password choices -->
-    <string name="policydesc_forceLock">Force the device to immediately lock,
-        requiring that you re-enter its password.</string>
+    <string name="policydesc_forceLock">Control when device locks,
+        requiring you re-enter its password.</string>
     <!-- Title of policy access to wipe the user's data -->
     <string name="policylab_wipeData">Erase all data</string>
     <!-- Description of policy access to wipe the user's data -->
@@ -1634,6 +1630,15 @@
         Browser\'s history or bookmarks stored on your phone. Malicious applications
         can use this to erase or modify your Browser\'s data.</string>
 
+    <!-- Title of an application permission, listed so the user can choose whether
+        they want to allow the application to do this. -->
+    <string name="permlab_writeGeolocationPermissions">Modify Browser geolocation permissions</string>
+    <!-- Description of an application permission, listed so the user can choose whether
+        they want to allow the application to do this. -->
+    <string name="permdesc_writeGeolocationPermissions">Allows an application to modify the
+        Browser\'s geolocation permissions. Malicious applications
+        can use this to allow sending location information to arbitrary web sites.</string>
+
     <!-- If the user enters a password in a form on a website, a dialog will come up asking if they want to save the password. Text in the save password dialog, asking if the browser should remember a password. -->
     <string name="save_password_message">Do you want the browser to remember this password?</string>
     <!-- If the user enters a password in a form on a website, a dialog will come up asking if they want to save the password. Button in the save password dialog, saying not to remember this password. -->
diff --git a/core/res/res/xml-land/password_kbd_qwerty.xml b/core/res/res/xml-land/password_kbd_qwerty.xml
index a3d4e88..700c527 100755
--- a/core/res/res/xml-land/password_kbd_qwerty.xml
+++ b/core/res/res/xml-land/password_kbd_qwerty.xml
@@ -26,29 +26,28 @@
     >
 
     <Row>
-        <Key android:codes="113" android:keyLabel="q" android:keyEdgeFlags="left"/>
-        <Key android:codes="119" android:keyLabel="w"/>
-        <Key android:codes="101" android:keyLabel="e"/>
-        <Key android:codes="114" android:keyLabel="r"/>
-        <Key android:codes="116" android:keyLabel="t"/>
-        <Key android:codes="121" android:keyLabel="y"/>
-        <Key android:codes="117" android:keyLabel="u"/>
-        <Key android:codes="105" android:keyLabel="i"/>
-        <Key android:codes="111" android:keyLabel="o"/>
-        <Key android:codes="112" android:keyLabel="p" android:keyEdgeFlags="right"/>
+        <Key android:keyLabel="q" android:keyEdgeFlags="left"/>
+        <Key android:keyLabel="w"/>
+        <Key android:keyLabel="e"/>
+        <Key android:keyLabel="r"/>
+        <Key android:keyLabel="t"/>
+        <Key android:keyLabel="y"/>
+        <Key android:keyLabel="u"/>
+        <Key android:keyLabel="i"/>
+        <Key android:keyLabel="o"/>
+        <Key android:keyLabel="p" android:keyEdgeFlags="right"/>
     </Row>
 
     <Row>
-        <Key android:codes="97" android:keyLabel="a" android:horizontalGap="5%p"
-            android:keyEdgeFlags="left"/>
-        <Key android:codes="115" android:keyLabel="s"/>
-        <Key android:codes="100" android:keyLabel="d"/>
-        <Key android:codes="102" android:keyLabel="f"/>
-        <Key android:codes="103" android:keyLabel="g"/>
-        <Key android:codes="104" android:keyLabel="h"/>
-        <Key android:codes="106" android:keyLabel="j"/>
-        <Key android:codes="107" android:keyLabel="k"/>
-        <Key android:codes="108" android:keyLabel="l" android:keyEdgeFlags="right"/>
+        <Key android:keyLabel="a" android:horizontalGap="5%p" android:keyEdgeFlags="left"/>
+        <Key android:keyLabel="s"/>
+        <Key android:keyLabel="d"/>
+        <Key android:keyLabel="f"/>
+        <Key android:keyLabel="g"/>
+        <Key android:keyLabel="h"/>
+        <Key android:keyLabel="j"/>
+        <Key android:keyLabel="k"/>
+        <Key android:keyLabel="l" android:keyEdgeFlags="right"/>
     </Row>
 
     <Row>
@@ -56,13 +55,13 @@
             android:keyWidth="15%p" android:isModifier="true"
             android:iconPreview="@drawable/sym_keyboard_feedback_shift"
             android:isSticky="true" android:keyEdgeFlags="left"/>
-        <Key android:codes="122" android:keyLabel="z"/>
-        <Key android:codes="120" android:keyLabel="x"/>
-        <Key android:codes="99" android:keyLabel="c"/>
-        <Key android:codes="118" android:keyLabel="v"/>
-        <Key android:codes="98" android:keyLabel="b"/>
-        <Key android:codes="110" android:keyLabel="n"/>
-        <Key android:codes="109" android:keyLabel="m"/>
+        <Key android:keyLabel="z"/>
+        <Key android:keyLabel="x"/>
+        <Key android:keyLabel="c"/>
+        <Key android:keyLabel="v"/>
+        <Key android:keyLabel="b"/>
+        <Key android:keyLabel="n"/>
+        <Key android:keyLabel="m"/>
         <Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete"
             android:keyWidth="15%p" android:keyEdgeFlags="right"
             android:iconPreview="@drawable/sym_keyboard_feedback_delete"
@@ -76,12 +75,11 @@
         <Key android:keyLabel="-" />
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
             android:iconPreview="@drawable/sym_keyboard_feedback_space"
-            android:keyWidth="20%p" android:isRepeatable="true"/>
+            android:keyWidth="20%p"/>
         <Key android:keyLabel="=" />
-        <Key android:codes="46" android:keyLabel="."
-            android:keyWidth="10%p"/>
-        <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
-            android:iconPreview="@drawable/sym_keyboard_feedback_return"
+        <Key android:keyLabel="." android:keyWidth="10%p"/>
+        <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_ok"
+            android:iconPreview="@drawable/sym_keyboard_feedback_ok"
             android:keyWidth="20%p" android:keyEdgeFlags="right"/>
     </Row>
 
diff --git a/core/res/res/xml-land/password_kbd_qwerty_shifted.xml b/core/res/res/xml-land/password_kbd_qwerty_shifted.xml
index 2285d91..1e37b6c 100755
--- a/core/res/res/xml-land/password_kbd_qwerty_shifted.xml
+++ b/core/res/res/xml-land/password_kbd_qwerty_shifted.xml
@@ -26,29 +26,29 @@
     >
 
     <Row>
-        <Key android:codes="113" android:keyLabel="q" android:keyEdgeFlags="left"/>
-        <Key android:codes="119" android:keyLabel="w"/>
-        <Key android:codes="101" android:keyLabel="e"/>
-        <Key android:codes="114" android:keyLabel="r"/>
-        <Key android:codes="116" android:keyLabel="t"/>
-        <Key android:codes="121" android:keyLabel="y"/>
-        <Key android:codes="117" android:keyLabel="u"/>
-        <Key android:codes="105" android:keyLabel="i"/>
-        <Key android:codes="111" android:keyLabel="o"/>
-        <Key android:codes="112" android:keyLabel="p" android:keyEdgeFlags="right"/>
+        <Key android:keyLabel="q" android:keyEdgeFlags="left"/>
+        <Key android:keyLabel="w"/>
+        <Key android:keyLabel="e"/>
+        <Key android:keyLabel="r"/>
+        <Key android:keyLabel="t"/>
+        <Key android:keyLabel="y"/>
+        <Key android:keyLabel="u"/>
+        <Key android:keyLabel="i"/>
+        <Key android:keyLabel="o"/>
+        <Key android:keyLabel="p" android:keyEdgeFlags="right"/>
     </Row>
 
     <Row>
-        <Key android:codes="97" android:keyLabel="a" android:horizontalGap="5%p"
+        <Key android:keyLabel="a" android:horizontalGap="5%p"
             android:keyEdgeFlags="left"/>
-        <Key android:codes="115" android:keyLabel="s"/>
-        <Key android:codes="100" android:keyLabel="d"/>
-        <Key android:codes="102" android:keyLabel="f"/>
-        <Key android:codes="103" android:keyLabel="g"/>
-        <Key android:codes="104" android:keyLabel="h"/>
-        <Key android:codes="106" android:keyLabel="j"/>
-        <Key android:codes="107" android:keyLabel="k"/>
-        <Key android:codes="108" android:keyLabel="l" android:keyEdgeFlags="right"/>
+        <Key android:keyLabel="s"/>
+        <Key android:keyLabel="d"/>
+        <Key android:keyLabel="f"/>
+        <Key android:keyLabel="g"/>
+        <Key android:keyLabel="h"/>
+        <Key android:keyLabel="j"/>
+        <Key android:keyLabel="k"/>
+        <Key android:keyLabel="l" android:keyEdgeFlags="right"/>
     </Row>
 
     <Row>
@@ -56,13 +56,13 @@
             android:keyWidth="15%p" android:isModifier="true"
             android:iconPreview="@drawable/sym_keyboard_feedback_shift"
             android:isSticky="true" android:keyEdgeFlags="left"/>
-        <Key android:codes="122" android:keyLabel="z"/>
-        <Key android:codes="120" android:keyLabel="x"/>
-        <Key android:codes="99" android:keyLabel="c"/>
-        <Key android:codes="118" android:keyLabel="v"/>
-        <Key android:codes="98" android:keyLabel="b"/>
-        <Key android:codes="110" android:keyLabel="n"/>
-        <Key android:codes="109" android:keyLabel="m"/>
+        <Key android:keyLabel="z"/>
+        <Key android:keyLabel="x"/>
+        <Key android:keyLabel="c"/>
+        <Key android:keyLabel="v"/>
+        <Key android:keyLabel="b"/>
+        <Key android:keyLabel="n"/>
+        <Key android:keyLabel="m"/>
         <Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete"
             android:keyWidth="15%p" android:keyEdgeFlags="right"
             android:iconPreview="@drawable/sym_keyboard_feedback_delete"
@@ -76,11 +76,11 @@
         <Key android:keyLabel="_" />
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
             android:iconPreview="@drawable/sym_keyboard_feedback_space"
-            android:keyWidth="20%p" android:isRepeatable="true"/>
+            android:keyWidth="20%p"/>
         <Key android:keyLabel="+" />
-        <Key android:codes="46" android:keyLabel="."/>
-        <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_return"
-            android:iconPreview="@drawable/sym_keyboard_feedback_return"
+        <Key android:keyLabel="."/>
+        <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_ok"
+            android:iconPreview="@drawable/sym_keyboard_feedback_ok"
             android:keyWidth="20%p" android:keyEdgeFlags="right"/>
     </Row>
 
diff --git a/core/res/res/xml/password_kbd_extension.xml b/core/res/res/xml/password_kbd_extension.xml
index 354594e..28b7efe 100755
--- a/core/res/res/xml/password_kbd_extension.xml
+++ b/core/res/res/xml/password_kbd_extension.xml
@@ -40,22 +40,15 @@
     </Row>
 
     <Row android:rowEdgeFlags="bottom">
-        <Key android:codes="49" android:keyLabel="1" android:keyEdgeFlags="left"
-        />
-        <Key android:codes="50" android:keyLabel="2"
-        />
-        <Key android:codes="51" android:keyLabel="3"
-        />
-        <Key android:codes="52" android:keyLabel="4"
-        />
-        <Key android:codes="53" android:keyLabel="5"
-        />
-        <Key android:codes="54" android:keyLabel="6"/>
-        <Key android:codes="55" android:keyLabel="7"
-        />
-        <Key android:codes="56" android:keyLabel="8"/>
-        <Key android:codes="57" android:keyLabel="9"/>
-        <Key android:codes="48" android:keyLabel="0"
-                android:keyEdgeFlags="right"/>
+        <Key android:keyLabel="1" android:keyEdgeFlags="left"/>
+        <Key android:keyLabel="2"/>
+        <Key android:keyLabel="3"/>
+        <Key android:keyLabel="4"/>
+        <Key android:keyLabel="5"/>
+        <Key android:keyLabel="6"/>
+        <Key android:keyLabel="7"/>
+        <Key android:keyLabel="8"/>
+        <Key android:keyLabel="9"/>
+        <Key android:keyLabel="0" android:keyEdgeFlags="right"/>
     </Row>
 </Keyboard>
diff --git a/core/res/res/xml/password_kbd_qwerty.xml b/core/res/res/xml/password_kbd_qwerty.xml
index d4a454b..5fa9b8a 100755
--- a/core/res/res/xml/password_kbd_qwerty.xml
+++ b/core/res/res/xml/password_kbd_qwerty.xml
@@ -26,42 +26,42 @@
     >
 
     <Row android:rowEdgeFlags="top">
-        <Key android:codes="49" android:keyLabel="1" android:keyEdgeFlags="left"/>
-        <Key android:codes="50" android:keyLabel="2"/>
-        <Key android:codes="51" android:keyLabel="3"/>
-        <Key android:codes="52" android:keyLabel="4"/>
-        <Key android:codes="53" android:keyLabel="5"/>
-        <Key android:codes="54" android:keyLabel="6"/>
-        <Key android:codes="55" android:keyLabel="7"/>
-        <Key android:codes="56" android:keyLabel="8"/>
-        <Key android:codes="57" android:keyLabel="9"/>
-        <Key android:codes="48" android:keyLabel="0" android:keyEdgeFlags="right"/>
+        <Key android:keyLabel="1" android:keyEdgeFlags="left"/>
+        <Key android:keyLabel="2"/>
+        <Key android:keyLabel="3"/>
+        <Key android:keyLabel="4"/>
+        <Key android:keyLabel="5"/>
+        <Key android:keyLabel="6"/>
+        <Key android:keyLabel="7"/>
+        <Key android:keyLabel="8"/>
+        <Key android:keyLabel="9"/>
+        <Key android:keyLabel="0" android:keyEdgeFlags="right"/>
     </Row>
 
     <Row>
-        <Key android:codes="113" android:keyLabel="q" android:keyEdgeFlags="left"/>
-        <Key android:codes="119" android:keyLabel="w"/>
-        <Key android:codes="101" android:keyLabel="e"/>
-        <Key android:codes="114" android:keyLabel="r"/>
-        <Key android:codes="116" android:keyLabel="t"/>
-        <Key android:codes="121" android:keyLabel="y"/>
-        <Key android:codes="117" android:keyLabel="u"/>
-        <Key android:codes="105" android:keyLabel="i"/>
-        <Key android:codes="111" android:keyLabel="o"/>
-        <Key android:codes="112" android:keyLabel="p" android:keyEdgeFlags="right"/>
+        <Key android:keyLabel="q" android:keyEdgeFlags="left"/>
+        <Key android:keyLabel="w"/>
+        <Key android:keyLabel="e"/>
+        <Key android:keyLabel="r"/>
+        <Key android:keyLabel="t"/>
+        <Key android:keyLabel="y"/>
+        <Key android:keyLabel="u"/>
+        <Key android:keyLabel="i"/>
+        <Key android:keyLabel="o"/>
+        <Key android:keyLabel="p" android:keyEdgeFlags="right"/>
     </Row>
 
     <Row>
-        <Key android:codes="97" android:keyLabel="a" android:horizontalGap="5%p"
+        <Key android:keyLabel="a" android:horizontalGap="5%p"
             android:keyEdgeFlags="left"/>
-        <Key android:codes="115" android:keyLabel="s"/>
-        <Key android:codes="100" android:keyLabel="d"/>
-        <Key android:codes="102" android:keyLabel="f"/>
-        <Key android:codes="103" android:keyLabel="g"/>
-        <Key android:codes="104" android:keyLabel="h"/>
-        <Key android:codes="106" android:keyLabel="j"/>
-        <Key android:codes="107" android:keyLabel="k"/>
-        <Key android:codes="108" android:keyLabel="l" android:keyEdgeFlags="right"/>
+        <Key android:keyLabel="s"/>
+        <Key android:keyLabel="d"/>
+        <Key android:keyLabel="f"/>
+        <Key android:keyLabel="g"/>
+        <Key android:keyLabel="h"/>
+        <Key android:keyLabel="j"/>
+        <Key android:keyLabel="k"/>
+        <Key android:keyLabel="l" android:keyEdgeFlags="right"/>
     </Row>
 
     <Row>
@@ -69,13 +69,13 @@
             android:keyWidth="15%p" android:isModifier="true"
             android:iconPreview="@drawable/sym_keyboard_feedback_shift"
             android:isSticky="true" android:keyEdgeFlags="left"/>
-        <Key android:codes="122" android:keyLabel="z"/>
-        <Key android:codes="120" android:keyLabel="x"/>
-        <Key android:codes="99" android:keyLabel="c"/>
-        <Key android:codes="118" android:keyLabel="v"/>
-        <Key android:codes="98" android:keyLabel="b"/>
-        <Key android:codes="110" android:keyLabel="n"/>
-        <Key android:codes="109" android:keyLabel="m"/>
+        <Key android:keyLabel="z"/>
+        <Key android:keyLabel="x"/>
+        <Key android:keyLabel="c"/>
+        <Key android:keyLabel="v"/>
+        <Key android:keyLabel="b"/>
+        <Key android:keyLabel="n"/>
+        <Key android:keyLabel="m"/>
         <Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete"
             android:keyWidth="15%p" android:keyEdgeFlags="right"
             android:iconPreview="@drawable/sym_keyboard_feedback_delete"
@@ -89,9 +89,9 @@
         <Key android:keyLabel="-" />
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
             android:iconPreview="@drawable/sym_keyboard_feedback_space"
-            android:keyWidth="20%p" android:isRepeatable="true"/>
+            android:keyWidth="20%p"/>
         <Key android:keyLabel="=" />
-        <Key android:codes="46" android:keyLabel="."
+        <Key android:keyLabel="."
             android:keyWidth="10%p"/>
         <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_ok"
             android:iconPreview="@drawable/sym_keyboard_feedback_ok"
diff --git a/core/res/res/xml/password_kbd_qwerty_shifted.xml b/core/res/res/xml/password_kbd_qwerty_shifted.xml
index f341d9e..e491aff 100755
--- a/core/res/res/xml/password_kbd_qwerty_shifted.xml
+++ b/core/res/res/xml/password_kbd_qwerty_shifted.xml
@@ -26,42 +26,42 @@
     >
 
     <Row android:rowEdgeFlags="top">
-        <Key android:codes="64" android:keyLabel="\@" android:keyEdgeFlags="left"/>
-        <Key android:codes="35" android:keyLabel="\#"/>
-        <Key android:codes="36" android:keyLabel="$"/>
-        <Key android:codes="37" android:keyLabel="%"/>
-        <Key android:codes="38" android:keyLabel="&amp;"/>
-        <Key android:codes="42" android:keyLabel="*"/>
-        <Key android:codes="45" android:keyLabel="-"/>
+        <Key android:keyLabel="\@" android:keyEdgeFlags="left"/>
+        <Key android:keyLabel="\#"/>
+        <Key android:keyLabel="$"/>
+        <Key android:keyLabel="%"/>
+        <Key android:keyLabel="&amp;"/>
+        <Key android:keyLabel="*"/>
+        <Key android:keyLabel="-"/>
         <Key android:keyLabel="+"/>
-        <Key android:codes="40" android:keyLabel="("/>
-        <Key android:codes="41" android:keyLabel=")" android:keyEdgeFlags="right"/>
+        <Key android:keyLabel="("/>
+        <Key android:keyLabel=")" android:keyEdgeFlags="right"/>
     </Row>
 
     <Row>
-        <Key android:codes="113" android:keyLabel="q" android:keyEdgeFlags="left"/>
-        <Key android:codes="119" android:keyLabel="w"/>
-        <Key android:codes="101" android:keyLabel="e"/>
-        <Key android:codes="114" android:keyLabel="r"/>
-        <Key android:codes="116" android:keyLabel="t"/>
-        <Key android:codes="121" android:keyLabel="y"/>
-        <Key android:codes="117" android:keyLabel="u"/>
-        <Key android:codes="105" android:keyLabel="i"/>
-        <Key android:codes="111" android:keyLabel="o"/>
-        <Key android:codes="112" android:keyLabel="p" android:keyEdgeFlags="right"/>
+        <Key android:keyLabel="q" android:keyEdgeFlags="left"/>
+        <Key android:keyLabel="w"/>
+        <Key android:keyLabel="e"/>
+        <Key android:keyLabel="r"/>
+        <Key android:keyLabel="t"/>
+        <Key android:keyLabel="y"/>
+        <Key android:keyLabel="u"/>
+        <Key android:keyLabel="i"/>
+        <Key android:keyLabel="o"/>
+        <Key android:keyLabel="p" android:keyEdgeFlags="right"/>
     </Row>
 
     <Row>
-        <Key android:codes="97" android:keyLabel="a" android:horizontalGap="5%p"
+        <Key android:keyLabel="a" android:horizontalGap="5%p"
             android:keyEdgeFlags="left"/>
-        <Key android:codes="115" android:keyLabel="s"/>
-        <Key android:codes="100" android:keyLabel="d"/>
-        <Key android:codes="102" android:keyLabel="f"/>
-        <Key android:codes="103" android:keyLabel="g"/>
-        <Key android:codes="104" android:keyLabel="h"/>
-        <Key android:codes="106" android:keyLabel="j"/>
-        <Key android:codes="107" android:keyLabel="k"/>
-        <Key android:codes="108" android:keyLabel="l" android:keyEdgeFlags="right"/>
+        <Key android:keyLabel="s"/>
+        <Key android:keyLabel="d"/>
+        <Key android:keyLabel="f"/>
+        <Key android:keyLabel="g"/>
+        <Key android:keyLabel="h"/>
+        <Key android:keyLabel="j"/>
+        <Key android:keyLabel="k"/>
+        <Key android:keyLabel="l" android:keyEdgeFlags="right"/>
     </Row>
 
     <Row>
@@ -69,13 +69,13 @@
             android:keyWidth="15%p" android:isModifier="true"
             android:iconPreview="@drawable/sym_keyboard_feedback_shift"
             android:isSticky="true" android:keyEdgeFlags="left"/>
-        <Key android:codes="122" android:keyLabel="z"/>
-        <Key android:codes="120" android:keyLabel="x"/>
-        <Key android:codes="99" android:keyLabel="c"/>
-        <Key android:codes="118" android:keyLabel="v"/>
-        <Key android:codes="98" android:keyLabel="b"/>
-        <Key android:codes="110" android:keyLabel="n"/>
-        <Key android:codes="109" android:keyLabel="m"/>
+        <Key android:keyLabel="z"/>
+        <Key android:keyLabel="x"/>
+        <Key android:keyLabel="c"/>
+        <Key android:keyLabel="v"/>
+        <Key android:keyLabel="b"/>
+        <Key android:keyLabel="n"/>
+        <Key android:keyLabel="m"/>
         <Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete"
             android:keyWidth="15%p" android:keyEdgeFlags="right"
             android:iconPreview="@drawable/sym_keyboard_feedback_delete"
@@ -89,9 +89,9 @@
         <Key android:keyLabel="_" />
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
             android:iconPreview="@drawable/sym_keyboard_feedback_space"
-            android:keyWidth="20%p" android:isRepeatable="true"/>
+            android:keyWidth="20%p"/>
         <Key android:keyLabel="+" />
-        <Key android:codes="46" android:keyLabel="."/>
+        <Key android:keyLabel="."/>
         <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_ok"
             android:iconPreview="@drawable/sym_keyboard_feedback_ok"
             android:keyWidth="20%p" android:keyEdgeFlags="right"/>
diff --git a/core/res/res/xml/password_kbd_symbols.xml b/core/res/res/xml/password_kbd_symbols.xml
index c97e6ae..14a7ec8 100755
--- a/core/res/res/xml/password_kbd_symbols.xml
+++ b/core/res/res/xml/password_kbd_symbols.xml
@@ -26,32 +26,32 @@
     >
 
     <Row>
-        <Key android:codes="49" android:keyLabel="1" android:keyEdgeFlags="left"/>
-        <Key android:codes="50" android:keyLabel="2"/>
-        <Key android:codes="51" android:keyLabel="3"/>
-        <Key android:codes="52" android:keyLabel="4"/>
-        <Key android:codes="53" android:keyLabel="5"/>
-        <Key android:codes="54" android:keyLabel="6"/>
-        <Key android:codes="55" android:keyLabel="7"/>
-        <Key android:codes="56" android:keyLabel="8"/>
-        <Key android:codes="57" android:keyLabel="9"/>
-        <Key android:codes="48" android:keyLabel="0" android:keyEdgeFlags="right"/>
+        <Key android:keyLabel="1" android:keyEdgeFlags="left"/>
+        <Key android:keyLabel="2"/>
+        <Key android:keyLabel="3"/>
+        <Key android:keyLabel="4"/>
+        <Key android:keyLabel="5"/>
+        <Key android:keyLabel="6"/>
+        <Key android:keyLabel="7"/>
+        <Key android:keyLabel="8"/>
+        <Key android:keyLabel="9"/>
+        <Key android:keyLabel="0" android:keyEdgeFlags="right"/>
     </Row>
 
     <Row>
-        <Key android:codes="64" android:keyLabel="\@" android:keyEdgeFlags="left"/>
-        <Key android:codes="35" android:keyLabel="\#"/>
-        <Key android:codes="36" android:keyLabel="$"/>
-        <Key android:codes="37" android:keyLabel="%"/>
-        <Key android:codes="38" android:keyLabel="&amp;"/>
-        <Key android:codes="42" android:keyLabel="*"/>
-        <Key android:codes="45" android:keyLabel="-"/>
+        <Key android:keyLabel="\@" android:keyEdgeFlags="left"/>
+        <Key android:keyLabel="\#"/>
+        <Key android:keyLabel="$"/>
+        <Key android:keyLabel="%"/>
+        <Key android:keyLabel="&amp;"/>
+        <Key android:keyLabel="*"/>
+        <Key android:keyLabel="-"/>
         <Key android:keyLabel="+"/>
-        <Key android:codes="40" android:keyLabel="("
+        <Key android:keyLabel="("
                 android:popupKeyboard="@xml/password_kbd_popup_template"
                 android:popupCharacters="[{&lt;"
         />
-        <Key android:codes="41" android:keyLabel=")" android:keyEdgeFlags="right"
+        <Key android:keyLabel=")" android:keyEdgeFlags="right"
                 android:popupKeyboard="@xml/password_kbd_popup_template"
                 android:popupCharacters="]}&gt;"
         />
@@ -61,13 +61,13 @@
         <Key android:codes="-1" android:keyLabel="@string/password_keyboard_label_alt_key"
                 android:keyWidth="15%p" android:isModifier="true"
                 android:isSticky="true" android:keyEdgeFlags="left"/>
-        <Key android:codes="33" android:keyLabel="!"/>
-        <Key android:codes="34" android:keyLabel="&quot;"/>
-        <Key android:codes="39" android:keyLabel="\'"/>
-        <Key android:codes="58" android:keyLabel=":"/>
-        <Key android:codes="59" android:keyLabel=";"/>
-        <Key android:codes="47" android:keyLabel="/" />
-        <Key android:codes="63" android:keyLabel="\?"/>
+        <Key android:keyLabel="!"/>
+        <Key android:keyLabel="&quot;"/>
+        <Key android:keyLabel="\'"/>
+        <Key android:keyLabel=":"/>
+        <Key android:keyLabel=";"/>
+        <Key android:keyLabel="/" />
+        <Key android:keyLabel="\?"/>
         <Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete"
             android:keyWidth="15%p" android:keyEdgeFlags="right"
             android:iconPreview="@drawable/sym_keyboard_feedback_delete"
@@ -80,8 +80,7 @@
         <Key android:keyLabel="," android:keyWidth="10%p"/>
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
             android:keyWidth="40%p"
-            android:iconPreview="@drawable/sym_keyboard_feedback_space"
-            android:isRepeatable="true"/>
+            android:iconPreview="@drawable/sym_keyboard_feedback_space"/>
         <Key android:keyLabel="." android:keyWidth="10%p" />
         <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_ok"
             android:keyWidth="20%p" android:keyEdgeFlags="right"
diff --git a/core/res/res/xml/password_kbd_symbols_shift.xml b/core/res/res/xml/password_kbd_symbols_shift.xml
index 97ec3c5f..4b84f4b 100755
--- a/core/res/res/xml/password_kbd_symbols_shift.xml
+++ b/core/res/res/xml/password_kbd_symbols_shift.xml
@@ -76,8 +76,7 @@
         <Key android:keyLabel="„" android:keyWidth="10%p" />
         <Key android:codes="32" android:keyIcon="@drawable/sym_keyboard_space"
             android:keyWidth="40%p"
-            android:iconPreview="@drawable/sym_keyboard_feedback_space"
-            android:isRepeatable="true"/>
+            android:iconPreview="@drawable/sym_keyboard_feedback_space"/>
         <Key android:keyLabel="…" android:keyWidth="10%p" />
         <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_ok"
             android:keyWidth="20%p" android:keyEdgeFlags="right"
diff --git a/core/tests/coretests/src/android/util/base64/Base64Test.java b/core/tests/coretests/src/android/util/base64/Base64Test.java
new file mode 100644
index 0000000..48192bb
--- /dev/null
+++ b/core/tests/coretests/src/android/util/base64/Base64Test.java
@@ -0,0 +1,520 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util.base64;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.Random;
+
+public class Base64Test extends TestCase {
+    private static final String TAG = "Base64Test";
+
+    /** Decodes a string, returning a string. */
+    private String decodeString(String in) throws Exception {
+        byte[] out = Base64.decode(in, 0);
+        return new String(out);
+    }
+
+    /**
+     * Encodes the string 'in' using 'flags'.  Asserts that decoding
+     * gives the same string.  Returns the encoded string.
+     */
+    private String encodeToString(String in, int flags) throws Exception {
+        String b64 = Base64.encodeToString(in.getBytes(), flags);
+        String dec = decodeString(b64);
+        assertEquals(in, dec);
+        return b64;
+    }
+
+    /** Assert that decoding 'in' throws IllegalArgumentException. */
+    private void assertBad(String in) throws Exception {
+        try {
+            byte[] out = Base64.decode(in, 0);
+            fail("should have failed to decode");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+
+    /** Assert that actual equals the first len bytes of expected. */
+    private void assertEquals(byte[] expected, int len, byte[] actual) {
+        assertEquals(len, actual.length);
+        for (int i = 0; i < len; ++i) {
+            assertEquals(expected[i], actual[i]);
+        }
+    }
+
+    /** Assert that actual equals the first len bytes of expected. */
+    private void assertEquals(byte[] expected, int len, byte[] actual, int alen) {
+        assertEquals(len, alen);
+        for (int i = 0; i < len; ++i) {
+            assertEquals(expected[i], actual[i]);
+        }
+    }
+
+    /** Assert that actual equals the first len bytes of expected. */
+    private void assertEquals(byte[] expected, byte[] actual) {
+        assertEquals(expected.length, actual.length);
+        for (int i = 0; i < expected.length; ++i) {
+            assertEquals(expected[i], actual[i]);
+        }
+    }
+
+    public void testDecodeExtraChars() throws Exception {
+        // padding 0
+        assertEquals("hello, world", decodeString("aGVsbG8sIHdvcmxk"));
+        assertBad("aGVsbG8sIHdvcmxk=");
+        assertBad("aGVsbG8sIHdvcmxk==");
+        assertBad("aGVsbG8sIHdvcmxk =");
+        assertBad("aGVsbG8sIHdvcmxk = = ");
+        assertEquals("hello, world", decodeString(" aGVs bG8s IHdv cmxk  "));
+        assertEquals("hello, world", decodeString(" aGV sbG8 sIHd vcmx k "));
+        assertEquals("hello, world", decodeString(" aG VsbG 8sIH dvcm xk "));
+        assertEquals("hello, world", decodeString(" a GVsb G8sI Hdvc mxk "));
+        assertEquals("hello, world", decodeString(" a G V s b G 8 s I H d v c m x k "));
+        assertEquals("hello, world", decodeString("_a*G_V*s_b*G_8*s_I*H_d*v_c*m_x*k_"));
+        assertEquals("hello, world", decodeString("aGVsbG8sIHdvcmxk"));
+
+        // padding 1
+        assertEquals("hello, world?!", decodeString("aGVsbG8sIHdvcmxkPyE="));
+        assertEquals("hello, world?!", decodeString("aGVsbG8sIHdvcmxkPyE"));
+        assertBad("aGVsbG8sIHdvcmxkPyE==");
+        assertBad("aGVsbG8sIHdvcmxkPyE ==");
+        assertBad("aGVsbG8sIHdvcmxkPyE = = ");
+        assertEquals("hello, world?!", decodeString("aGVsbG8sIHdvcmxkPy E="));
+        assertEquals("hello, world?!", decodeString("aGVsbG8sIHdvcmxkPy E"));
+        assertEquals("hello, world?!", decodeString("aGVsbG8sIHdvcmxkPy E ="));
+        assertEquals("hello, world?!", decodeString("aGVsbG8sIHdvcmxkPy E "));
+        assertEquals("hello, world?!", decodeString("aGVsbG8sIHdvcmxkPy E = "));
+        assertEquals("hello, world?!", decodeString("aGVsbG8sIHdvcmxkPy E   "));
+
+        // padding 2
+        assertEquals("hello, world.", decodeString("aGVsbG8sIHdvcmxkLg=="));
+        assertEquals("hello, world.", decodeString("aGVsbG8sIHdvcmxkLg"));
+        assertBad("aGVsbG8sIHdvcmxkLg=");
+        assertBad("aGVsbG8sIHdvcmxkLg =");
+        assertBad("aGVsbG8sIHdvcmxkLg = ");
+        assertEquals("hello, world.", decodeString("aGVsbG8sIHdvcmxkL g=="));
+        assertEquals("hello, world.", decodeString("aGVsbG8sIHdvcmxkL g"));
+        assertEquals("hello, world.", decodeString("aGVsbG8sIHdvcmxkL g =="));
+        assertEquals("hello, world.", decodeString("aGVsbG8sIHdvcmxkL g "));
+        assertEquals("hello, world.", decodeString("aGVsbG8sIHdvcmxkL g = = "));
+        assertEquals("hello, world.", decodeString("aGVsbG8sIHdvcmxkL g   "));
+    }
+
+    private static final byte[] BYTES = { (byte) 0xff, (byte) 0xee, (byte) 0xdd,
+                                          (byte) 0xcc, (byte) 0xbb, (byte) 0xaa,
+                                          (byte) 0x99, (byte) 0x88, (byte) 0x77 };
+
+    public void testBinaryDecode() throws Exception {
+        assertEquals(BYTES, 0, Base64.decode("", 0));
+        assertEquals(BYTES, 1, Base64.decode("/w==", 0));
+        assertEquals(BYTES, 2, Base64.decode("/+4=", 0));
+        assertEquals(BYTES, 3, Base64.decode("/+7d", 0));
+        assertEquals(BYTES, 4, Base64.decode("/+7dzA==", 0));
+        assertEquals(BYTES, 5, Base64.decode("/+7dzLs=", 0));
+        assertEquals(BYTES, 6, Base64.decode("/+7dzLuq", 0));
+        assertEquals(BYTES, 7, Base64.decode("/+7dzLuqmQ==", 0));
+        assertEquals(BYTES, 8, Base64.decode("/+7dzLuqmYg=", 0));
+    }
+
+    public void testWebSafe() throws Exception {
+        assertEquals(BYTES, 0, Base64.decode("", Base64.URL_SAFE));
+        assertEquals(BYTES, 1, Base64.decode("_w==", Base64.URL_SAFE));
+        assertEquals(BYTES, 2, Base64.decode("_-4=", Base64.URL_SAFE));
+        assertEquals(BYTES, 3, Base64.decode("_-7d", Base64.URL_SAFE));
+        assertEquals(BYTES, 4, Base64.decode("_-7dzA==", Base64.URL_SAFE));
+        assertEquals(BYTES, 5, Base64.decode("_-7dzLs=", Base64.URL_SAFE));
+        assertEquals(BYTES, 6, Base64.decode("_-7dzLuq", Base64.URL_SAFE));
+        assertEquals(BYTES, 7, Base64.decode("_-7dzLuqmQ==", Base64.URL_SAFE));
+        assertEquals(BYTES, 8, Base64.decode("_-7dzLuqmYg=", Base64.URL_SAFE));
+
+        assertEquals("", Base64.encodeToString(BYTES, 0, 0, Base64.URL_SAFE));
+        assertEquals("_w==\n", Base64.encodeToString(BYTES, 0, 1, Base64.URL_SAFE));
+        assertEquals("_-4=\n", Base64.encodeToString(BYTES, 0, 2, Base64.URL_SAFE));
+        assertEquals("_-7d\n", Base64.encodeToString(BYTES, 0, 3, Base64.URL_SAFE));
+        assertEquals("_-7dzA==\n", Base64.encodeToString(BYTES, 0, 4, Base64.URL_SAFE));
+        assertEquals("_-7dzLs=\n", Base64.encodeToString(BYTES, 0, 5, Base64.URL_SAFE));
+        assertEquals("_-7dzLuq\n", Base64.encodeToString(BYTES, 0, 6, Base64.URL_SAFE));
+        assertEquals("_-7dzLuqmQ==\n", Base64.encodeToString(BYTES, 0, 7, Base64.URL_SAFE));
+        assertEquals("_-7dzLuqmYg=\n", Base64.encodeToString(BYTES, 0, 8, Base64.URL_SAFE));
+    }
+
+    public void testFlags() throws Exception {
+        assertEquals("YQ==\n",       encodeToString("a", 0));
+        assertEquals("YQ==",         encodeToString("a", Base64.NO_WRAP));
+        assertEquals("YQ\n",         encodeToString("a", Base64.NO_PADDING));
+        assertEquals("YQ",           encodeToString("a", Base64.NO_PADDING | Base64.NO_WRAP));
+        assertEquals("YQ==\r\n",     encodeToString("a", Base64.CRLF));
+        assertEquals("YQ\r\n",       encodeToString("a", Base64.CRLF | Base64.NO_PADDING));
+
+        assertEquals("YWI=\n",       encodeToString("ab", 0));
+        assertEquals("YWI=",         encodeToString("ab", Base64.NO_WRAP));
+        assertEquals("YWI\n",        encodeToString("ab", Base64.NO_PADDING));
+        assertEquals("YWI",          encodeToString("ab", Base64.NO_PADDING | Base64.NO_WRAP));
+        assertEquals("YWI=\r\n",     encodeToString("ab", Base64.CRLF));
+        assertEquals("YWI\r\n",      encodeToString("ab", Base64.CRLF | Base64.NO_PADDING));
+
+        assertEquals("YWJj\n",       encodeToString("abc", 0));
+        assertEquals("YWJj",         encodeToString("abc", Base64.NO_WRAP));
+        assertEquals("YWJj\n",       encodeToString("abc", Base64.NO_PADDING));
+        assertEquals("YWJj",         encodeToString("abc", Base64.NO_PADDING | Base64.NO_WRAP));
+        assertEquals("YWJj\r\n",     encodeToString("abc", Base64.CRLF));
+        assertEquals("YWJj\r\n",     encodeToString("abc", Base64.CRLF | Base64.NO_PADDING));
+
+        assertEquals("YWJjZA==\n",   encodeToString("abcd", 0));
+        assertEquals("YWJjZA==",     encodeToString("abcd", Base64.NO_WRAP));
+        assertEquals("YWJjZA\n",     encodeToString("abcd", Base64.NO_PADDING));
+        assertEquals("YWJjZA",       encodeToString("abcd", Base64.NO_PADDING | Base64.NO_WRAP));
+        assertEquals("YWJjZA==\r\n", encodeToString("abcd", Base64.CRLF));
+        assertEquals("YWJjZA\r\n",   encodeToString("abcd", Base64.CRLF | Base64.NO_PADDING));
+    }
+
+    public void testLineLength() throws Exception {
+        String in_56 = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd";
+        String in_57 = in_56 + "e";
+        String in_58 = in_56 + "ef";
+        String in_59 = in_56 + "efg";
+        String in_60 = in_56 + "efgh";
+        String in_61 = in_56 + "efghi";
+
+        String prefix = "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5emFi";
+        String out_56 = prefix + "Y2Q=\n";
+        String out_57 = prefix + "Y2Rl\n";
+        String out_58 = prefix + "Y2Rl\nZg==\n";
+        String out_59 = prefix + "Y2Rl\nZmc=\n";
+        String out_60 = prefix + "Y2Rl\nZmdo\n";
+        String out_61 = prefix + "Y2Rl\nZmdoaQ==\n";
+
+        // no newline for an empty input array.
+        assertEquals("", encodeToString("", 0));
+
+        assertEquals(out_56, encodeToString(in_56, 0));
+        assertEquals(out_57, encodeToString(in_57, 0));
+        assertEquals(out_58, encodeToString(in_58, 0));
+        assertEquals(out_59, encodeToString(in_59, 0));
+        assertEquals(out_60, encodeToString(in_60, 0));
+        assertEquals(out_61, encodeToString(in_61, 0));
+
+        assertEquals(out_56.replaceAll("=", ""), encodeToString(in_56, Base64.NO_PADDING));
+        assertEquals(out_57.replaceAll("=", ""), encodeToString(in_57, Base64.NO_PADDING));
+        assertEquals(out_58.replaceAll("=", ""), encodeToString(in_58, Base64.NO_PADDING));
+        assertEquals(out_59.replaceAll("=", ""), encodeToString(in_59, Base64.NO_PADDING));
+        assertEquals(out_60.replaceAll("=", ""), encodeToString(in_60, Base64.NO_PADDING));
+        assertEquals(out_61.replaceAll("=", ""), encodeToString(in_61, Base64.NO_PADDING));
+
+        assertEquals(out_56.replaceAll("\n", ""), encodeToString(in_56, Base64.NO_WRAP));
+        assertEquals(out_57.replaceAll("\n", ""), encodeToString(in_57, Base64.NO_WRAP));
+        assertEquals(out_58.replaceAll("\n", ""), encodeToString(in_58, Base64.NO_WRAP));
+        assertEquals(out_59.replaceAll("\n", ""), encodeToString(in_59, Base64.NO_WRAP));
+        assertEquals(out_60.replaceAll("\n", ""), encodeToString(in_60, Base64.NO_WRAP));
+        assertEquals(out_61.replaceAll("\n", ""), encodeToString(in_61, Base64.NO_WRAP));
+    }
+
+    /**
+     * Tests that Base64.Encoder.encode() does correct handling of the
+     * tail for each call.
+     *
+     * This test is disabled because while it passes if you can get it
+     * to run, android's test infrastructure currently doesn't allow
+     * us to get at package-private members (Base64.Encoder in
+     * this case).
+     */
+    public void XXXtestEncodeInternal() throws Exception {
+        byte[] input = { (byte) 0x61, (byte) 0x62, (byte) 0x63 };
+        byte[] output = new byte[100];
+
+        Base64.Encoder encoder = new Base64.Encoder(Base64.NO_PADDING | Base64.NO_WRAP,
+                                                    output);
+
+        encoder.process(input, 0, 3, false);
+        assertEquals("YWJj".getBytes(), 4, encoder.output, encoder.op);
+        assertEquals(0, encoder.tailLen);
+
+        encoder.process(input, 0, 3, false);
+        assertEquals("YWJj".getBytes(), 4, encoder.output, encoder.op);
+        assertEquals(0, encoder.tailLen);
+
+        encoder.process(input, 0, 1, false);
+        assertEquals(0, encoder.op);
+        assertEquals(1, encoder.tailLen);
+
+        encoder.process(input, 0, 1, false);
+        assertEquals(0, encoder.op);
+        assertEquals(2, encoder.tailLen);
+
+        encoder.process(input, 0, 1, false);
+        assertEquals("YWFh".getBytes(), 4, encoder.output, encoder.op);
+        assertEquals(0, encoder.tailLen);
+
+        encoder.process(input, 0, 2, false);
+        assertEquals(0, encoder.op);
+        assertEquals(2, encoder.tailLen);
+
+        encoder.process(input, 0, 2, false);
+        assertEquals("YWJh".getBytes(), 4, encoder.output, encoder.op);
+        assertEquals(1, encoder.tailLen);
+
+        encoder.process(input, 0, 2, false);
+        assertEquals("YmFi".getBytes(), 4, encoder.output, encoder.op);
+        assertEquals(0, encoder.tailLen);
+
+        encoder.process(input, 0, 1, true);
+        assertEquals("YQ".getBytes(), 2, encoder.output, encoder.op);
+    }
+
+    private static final String lipsum =
+            "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " +
+            "Quisque congue eleifend odio, eu ornare nulla facilisis eget. " +
+            "Integer eget elit diam, sit amet laoreet nibh. Quisque enim " +
+            "urna, pharetra vitae consequat eget, adipiscing eu ante. " +
+            "Aliquam venenatis arcu nec nibh imperdiet tempor. In id dui " +
+            "eget lorem aliquam rutrum vel vitae eros. In placerat ornare " +
+            "pretium. Curabitur non fringilla mi. Fusce ultricies, turpis " +
+            "eu ultrices suscipit, ligula nisi consectetur eros, dapibus " +
+            "aliquet dui sapien a turpis. Donec ultricies varius ligula, " +
+            "ut hendrerit arcu malesuada at. Praesent sed elit pretium " +
+            "eros luctus gravida. In ac dolor lorem. Cras condimentum " +
+            "convallis elementum. Phasellus vel felis in nulla ultrices " +
+            "venenatis. Nam non tortor non orci convallis convallis. " +
+            "Nam tristique lacinia hendrerit. Pellentesque habitant morbi " +
+            "tristique senectus et netus et malesuada fames ac turpis " +
+            "egestas. Vivamus cursus, nibh eu imperdiet porta, magna " +
+            "ipsum mollis mauris, sit amet fringilla mi nisl eu mi. " +
+            "Phasellus posuere, leo at ultricies vehicula, massa risus " +
+            "volutpat sapien, eu tincidunt diam ipsum eget nulla. Cras " +
+            "molestie dapibus commodo. Ut vel tellus at massa gravida " +
+            "semper non sed orci.";
+
+    public void testInputStream() throws Exception {
+        int[] flagses = { Base64.DEFAULT,
+                          Base64.NO_PADDING,
+                          Base64.NO_WRAP,
+                          Base64.NO_PADDING | Base64.NO_WRAP,
+                          Base64.CRLF,
+                          Base64.URL_SAFE };
+        int[] writeLengths = { -10, -5, -1, 0, 1, 1, 2, 2, 3, 10, 100 };
+        Random rng = new Random(32176L);
+
+        // Test input needs to be at least 2048 bytes to fill up the
+        // read buffer of Base64InputStream.
+        byte[] plain = (lipsum + lipsum + lipsum + lipsum + lipsum).getBytes();
+
+        for (int flags: flagses) {
+            byte[] encoded = Base64.encode(plain, flags);
+
+            ByteArrayInputStream bais;
+            Base64InputStream b64is;
+            byte[] actual = new byte[plain.length * 2];
+            int ap;
+            int b;
+
+            // ----- test decoding ("encoded" -> "plain") -----
+
+            // read as much as it will give us in one chunk
+            bais = new ByteArrayInputStream(encoded);
+            b64is = new Base64InputStream(bais, flags);
+            ap = 0;
+            while ((b = b64is.read(actual, ap, actual.length-ap)) != -1) {
+                ap += b;
+            }
+            assertEquals(actual, ap, plain);
+
+            // read individual bytes
+            bais = new ByteArrayInputStream(encoded);
+            b64is = new Base64InputStream(bais, flags);
+            ap = 0;
+            while ((b = b64is.read()) != -1) {
+                actual[ap++] = (byte) b;
+            }
+            assertEquals(actual, ap, plain);
+
+            // mix reads of variously-sized arrays with one-byte reads
+            bais = new ByteArrayInputStream(encoded);
+            b64is = new Base64InputStream(bais, flags);
+            ap = 0;
+            readloop: while (true) {
+                int l = writeLengths[rng.nextInt(writeLengths.length)];
+                if (l >= 0) {
+                    b = b64is.read(actual, ap, l);
+                    if (b == -1) break readloop;
+                    ap += b;
+                } else {
+                    for (int i = 0; i < -l; ++i) {
+                        if ((b = b64is.read()) == -1) break readloop;
+                        actual[ap++] = (byte) b;
+                    }
+                }
+            }
+            assertEquals(actual, ap, plain);
+
+            // ----- test encoding ("plain" -> "encoded") -----
+
+            // read as much as it will give us in one chunk
+            bais = new ByteArrayInputStream(plain);
+            b64is = new Base64InputStream(bais, flags, true);
+            ap = 0;
+            while ((b = b64is.read(actual, ap, actual.length-ap)) != -1) {
+                ap += b;
+            }
+            assertEquals(actual, ap, encoded);
+
+            // read individual bytes
+            bais = new ByteArrayInputStream(plain);
+            b64is = new Base64InputStream(bais, flags, true);
+            ap = 0;
+            while ((b = b64is.read()) != -1) {
+                actual[ap++] = (byte) b;
+            }
+            assertEquals(actual, ap, encoded);
+
+            // mix reads of variously-sized arrays with one-byte reads
+            bais = new ByteArrayInputStream(plain);
+            b64is = new Base64InputStream(bais, flags, true);
+            ap = 0;
+            readloop: while (true) {
+                int l = writeLengths[rng.nextInt(writeLengths.length)];
+                if (l >= 0) {
+                    b = b64is.read(actual, ap, l);
+                    if (b == -1) break readloop;
+                    ap += b;
+                } else {
+                    for (int i = 0; i < -l; ++i) {
+                        if ((b = b64is.read()) == -1) break readloop;
+                        actual[ap++] = (byte) b;
+                    }
+                }
+            }
+            assertEquals(actual, ap, encoded);
+        }
+    }
+
+    /**
+     * Tests that Base64OutputStream produces exactly the same results
+     * as calling Base64.encode/.decode on an in-memory array.
+     */
+    public void testOutputStream() throws Exception {
+        int[] flagses = { Base64.DEFAULT,
+                          Base64.NO_PADDING,
+                          Base64.NO_WRAP,
+                          Base64.NO_PADDING | Base64.NO_WRAP,
+                          Base64.CRLF,
+                          Base64.URL_SAFE };
+        int[] writeLengths = { -10, -5, -1, 0, 1, 1, 2, 2, 3, 10, 100 };
+        Random rng = new Random(32176L);
+
+        // Test input needs to be at least 1024 bytes to test filling
+        // up the write(int) buffer of Base64OutputStream.
+        byte[] plain = (lipsum + lipsum).getBytes();
+
+        for (int flags: flagses) {
+            byte[] encoded = Base64.encode(plain, flags);
+
+            ByteArrayOutputStream baos;
+            Base64OutputStream b64os;
+            byte[] actual;
+            int p;
+
+            // ----- test encoding ("plain" -> "encoded") -----
+
+            // one large write(byte[]) of the whole input
+            baos = new ByteArrayOutputStream();
+            b64os = new Base64OutputStream(baos, flags);
+            b64os.write(plain);
+            b64os.close();
+            actual = baos.toByteArray();
+            assertEquals(encoded, actual);
+
+            // many calls to write(int)
+            baos = new ByteArrayOutputStream();
+            b64os = new Base64OutputStream(baos, flags);
+            for (int i = 0; i < plain.length; ++i) {
+                b64os.write(plain[i]);
+            }
+            b64os.close();
+            actual = baos.toByteArray();
+            assertEquals(encoded, actual);
+
+            // intermixed sequences of write(int) with
+            // write(byte[],int,int) of various lengths.
+            baos = new ByteArrayOutputStream();
+            b64os = new Base64OutputStream(baos, flags);
+            p = 0;
+            while (p < plain.length) {
+                int l = writeLengths[rng.nextInt(writeLengths.length)];
+                l = Math.min(l, plain.length-p);
+                if (l >= 0) {
+                    b64os.write(plain, p, l);
+                    p += l;
+                } else {
+                    l = Math.min(-l, plain.length-p);
+                    for (int i = 0; i < l; ++i) {
+                        b64os.write(plain[p+i]);
+                    }
+                    p += l;
+                }
+            }
+            b64os.close();
+            actual = baos.toByteArray();
+            assertEquals(encoded, actual);
+
+            // ----- test decoding ("encoded" -> "plain") -----
+
+            // one large write(byte[]) of the whole input
+            baos = new ByteArrayOutputStream();
+            b64os = new Base64OutputStream(baos, flags, false);
+            b64os.write(encoded);
+            b64os.close();
+            actual = baos.toByteArray();
+            assertEquals(plain, actual);
+
+            // many calls to write(int)
+            baos = new ByteArrayOutputStream();
+            b64os = new Base64OutputStream(baos, flags, false);
+            for (int i = 0; i < encoded.length; ++i) {
+                b64os.write(encoded[i]);
+            }
+            b64os.close();
+            actual = baos.toByteArray();
+            assertEquals(plain, actual);
+
+            // intermixed sequences of write(int) with
+            // write(byte[],int,int) of various lengths.
+            baos = new ByteArrayOutputStream();
+            b64os = new Base64OutputStream(baos, flags, false);
+            p = 0;
+            while (p < encoded.length) {
+                int l = writeLengths[rng.nextInt(writeLengths.length)];
+                l = Math.min(l, encoded.length-p);
+                if (l >= 0) {
+                    b64os.write(encoded, p, l);
+                    p += l;
+                } else {
+                    l = Math.min(-l, encoded.length-p);
+                    for (int i = 0; i < l; ++i) {
+                        b64os.write(encoded[p+i]);
+                    }
+                    p += l;
+                }
+            }
+            b64os.close();
+            actual = baos.toByteArray();
+            assertEquals(plain, actual);
+        }
+    }
+}
diff --git a/core/tests/coretests/src/com/google/android/net/ParentalControlTest.java b/core/tests/coretests/src/com/google/android/net/ParentalControlTest.java
deleted file mode 100644
index d8ffeab..0000000
--- a/core/tests/coretests/src/com/google/android/net/ParentalControlTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-package com.google.android.net;
-
-import com.google.android.net.ParentalControl;
-import com.google.android.net.ParentalControlState;
-
-import android.os.SystemClock;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-
-import junit.framework.Assert;
-
-public class ParentalControlTest extends AndroidTestCase {
-
-    private boolean mOnResultCalled = false;
-
-    public class Callback implements ParentalControl.Callback {
-        public void onResult(ParentalControlState state) {
-            synchronized (ParentalControlTest.class) {
-                mOnResultCalled = true;
-                ParentalControlTest.class.notifyAll();
-            }
-        }
-    }
-
-    @SmallTest
-    public void testParentalControlCallback() {
-        synchronized (ParentalControlTest.class) {
-            ParentalControl.getParentalControlState(new Callback(), null);
-            try {
-                long start = SystemClock.uptimeMillis();
-                ParentalControlTest.class.wait(20 * 1000);
-                long end = SystemClock.uptimeMillis();
-                Log.d("AndroidTests", "ParentalControlTest callback took " + (end-start) + " ms.");
-            } catch (InterruptedException ex) {
-            }
-        }
-
-        Assert.assertTrue(mOnResultCalled);
-    }
-}
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index 597cb57..b7491b2 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -26,14 +26,11 @@
     Clockopia.ttf
 
 ifneq ($(NO_FALLBACK_FONT),true)
+ifeq ($(filter %system/fonts/DroidSansFallback.ttf,$(PRODUCT_COPY_FILES)),)
+    # if the product makefile has set the the fallback font, don't override it.
     copy_from += DroidSansFallback.ttf
 endif
+endif
 
-copy_to := $(addprefix $(TARGET_OUT)/fonts/,$(copy_from))
-
-$(copy_to) : PRIVATE_MODULE := fonts
-$(copy_to) : $(TARGET_OUT)/fonts/% : $(LOCAL_PATH)/% | $(ACP)
-	$(transform-prebuilt-to-target)
-
-ALL_PREBUILT += $(copy_to)
-
+copy_file_pairs := $(foreach cf,$(copy_from),$(LOCAL_PATH)/$(cf):system/fonts/$(cf))
+PRODUCT_COPY_FILES += $(copy_file_pairs)
diff --git a/data/sounds/AudioPackage2.mk b/data/sounds/AudioPackage2.mk
index 5dacc70..d7f7c7e 100644
--- a/data/sounds/AudioPackage2.mk
+++ b/data/sounds/AudioPackage2.mk
@@ -67,6 +67,11 @@
 	$(LOCAL_PATH)/effects/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
 	$(LOCAL_PATH)/effects/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
 	$(LOCAL_PATH)/effects/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
+	$(LOCAL_PATH)/effects/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+	$(LOCAL_PATH)/effects/Dock.ogg:system/media/audio/ui/Dock.ogg \
+	$(LOCAL_PATH)/effects/Undock.ogg:system/media/audio/ui/Undock.ogg \
+	$(LOCAL_PATH)/effects/Lock.ogg:system/media/audio/ui/Lock.ogg \
+	$(LOCAL_PATH)/effects/Unlock.ogg:system/media/audio/ui/Unlock.ogg \
 	$(LOCAL_PATH)/newwavelabs/CrazyDream.ogg:system/media/audio/ringtones/CrazyDream.ogg \
 	$(LOCAL_PATH)/newwavelabs/DreamTheme.ogg:system/media/audio/ringtones/DreamTheme.ogg \
 	$(LOCAL_PATH)/newwavelabs/Big_Easy.ogg:system/media/audio/ringtones/Big_Easy.ogg \
diff --git a/data/sounds/AudioPackage3.mk b/data/sounds/AudioPackage3.mk
index f2f6212..64d6717 100644
--- a/data/sounds/AudioPackage3.mk
+++ b/data/sounds/AudioPackage3.mk
@@ -59,6 +59,11 @@
 	$(LOCAL_PATH)/effects/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
 	$(LOCAL_PATH)/effects/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
 	$(LOCAL_PATH)/effects/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
+	$(LOCAL_PATH)/effects/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+	$(LOCAL_PATH)/effects/Dock.ogg:system/media/audio/ui/Dock.ogg \
+	$(LOCAL_PATH)/effects/Undock.ogg:system/media/audio/ui/Undock.ogg \
+	$(LOCAL_PATH)/effects/Lock.ogg:system/media/audio/ui/Lock.ogg \
+	$(LOCAL_PATH)/effects/Unlock.ogg:system/media/audio/ui/Unlock.ogg \
 	$(LOCAL_PATH)/newwavelabs/Big_Easy.ogg:system/media/audio/ringtones/Big_Easy.ogg \
 	$(LOCAL_PATH)/newwavelabs/Bollywood.ogg:system/media/audio/ringtones/Bollywood.ogg \
 	$(LOCAL_PATH)/newwavelabs/Cairo.ogg:system/media/audio/ringtones/Cairo.ogg \
@@ -89,4 +94,3 @@
 	$(LOCAL_PATH)/notifications/pixiedust.ogg:system/media/audio/notifications/pixiedust.ogg \
 	$(LOCAL_PATH)/notifications/pizzicato.ogg:system/media/audio/notifications/pizzicato.ogg \
 	$(LOCAL_PATH)/notifications/tweeters.ogg:system/media/audio/notifications/tweeters.ogg
-
diff --git a/data/sounds/AudioPackage4.mk b/data/sounds/AudioPackage4.mk
index 6c36bad..b011b78 100644
--- a/data/sounds/AudioPackage4.mk
+++ b/data/sounds/AudioPackage4.mk
@@ -46,6 +46,11 @@
 	$(LOCAL_PATH)/effects/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \
 	$(LOCAL_PATH)/effects/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
 	$(LOCAL_PATH)/effects/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
+	$(LOCAL_PATH)/effects/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
+	$(LOCAL_PATH)/effects/Dock.ogg:system/media/audio/ui/Dock.ogg \
+	$(LOCAL_PATH)/effects/Undock.ogg:system/media/audio/ui/Undock.ogg \
+	$(LOCAL_PATH)/effects/Lock.ogg:system/media/audio/ui/Lock.ogg \
+	$(LOCAL_PATH)/effects/Unlock.ogg:system/media/audio/ui/Unlock.ogg \
 	$(LOCAL_PATH)/Ring_Classic_02.ogg:system/media/audio/ringtones/Ring_Classic_02.ogg \
 	$(LOCAL_PATH)/Ring_Digital_02.ogg:system/media/audio/ringtones/Ring_Digital_02.ogg \
 	$(LOCAL_PATH)/Ring_Synth_04.ogg:system/media/audio/ringtones/Ring_Synth_04.ogg \
diff --git a/data/sounds/effects/Dock.aif b/data/sounds/effects/Dock.aif
new file mode 100644
index 0000000..9f408cc
--- /dev/null
+++ b/data/sounds/effects/Dock.aif
Binary files differ
diff --git a/data/sounds/effects/Dock.ogg b/data/sounds/effects/Dock.ogg
new file mode 100644
index 0000000..1462813d
--- /dev/null
+++ b/data/sounds/effects/Dock.ogg
Binary files differ
diff --git a/data/sounds/effects/Lock.aiff b/data/sounds/effects/Lock.aiff
new file mode 100644
index 0000000..90870f2
--- /dev/null
+++ b/data/sounds/effects/Lock.aiff
Binary files differ
diff --git a/data/sounds/effects/Lock.ogg b/data/sounds/effects/Lock.ogg
new file mode 100644
index 0000000..841ee2e
--- /dev/null
+++ b/data/sounds/effects/Lock.ogg
Binary files differ
diff --git a/data/sounds/effects/LowBattery.aif b/data/sounds/effects/LowBattery.aif
new file mode 100644
index 0000000..9216583
--- /dev/null
+++ b/data/sounds/effects/LowBattery.aif
Binary files differ
diff --git a/data/sounds/effects/LowBattery.ogg b/data/sounds/effects/LowBattery.ogg
new file mode 100644
index 0000000..68eb2c3
--- /dev/null
+++ b/data/sounds/effects/LowBattery.ogg
Binary files differ
diff --git a/data/sounds/effects/Undock.aif b/data/sounds/effects/Undock.aif
new file mode 100644
index 0000000..fe9d0b05
--- /dev/null
+++ b/data/sounds/effects/Undock.aif
Binary files differ
diff --git a/data/sounds/effects/Undock.ogg b/data/sounds/effects/Undock.ogg
new file mode 100644
index 0000000..0053066
--- /dev/null
+++ b/data/sounds/effects/Undock.ogg
Binary files differ
diff --git a/data/sounds/effects/Unlock.aiff b/data/sounds/effects/Unlock.aiff
new file mode 100644
index 0000000..546ea39
--- /dev/null
+++ b/data/sounds/effects/Unlock.aiff
Binary files differ
diff --git a/data/sounds/effects/Unlock.ogg b/data/sounds/effects/Unlock.ogg
new file mode 100644
index 0000000..26d5ea6
--- /dev/null
+++ b/data/sounds/effects/Unlock.ogg
Binary files differ
diff --git a/docs/html/resources/articles/images/live_wallpapers_small.png b/docs/html/resources/articles/images/live_wallpapers_small.png
new file mode 100644
index 0000000..3b49b24
--- /dev/null
+++ b/docs/html/resources/articles/images/live_wallpapers_small.png
Binary files differ
diff --git a/docs/html/resources/articles/index.jd b/docs/html/resources/articles/index.jd
index 4fda6d7..d2f0996 100644
--- a/docs/html/resources/articles/index.jd
+++ b/docs/html/resources/articles/index.jd
@@ -77,6 +77,11 @@
 </dl>
 
 <dl>
+  <dt><a href="{@docRoot}resources/articles/live-wallpapers.html">Live Wallpapers</a></dt>
+  <dd>Live wallpapers are richer, animated, interactive backgrounds that users can display in their home screens. Learn how to create a live wallpaper and bundle it in an application that users can install on their devices.</dd>
+</dl>
+
+<dl>
   <dt><a href="{@docRoot}resources/articles/on-screen-inputs.html">Onscreen Input Methods</a></dt>
   <dd>The Input Method Framework (IMF) allows users to take advantage of on-screen input methods, such as software keyboards. This article provides an overview of Input Method Editors (IMEs) and how applications interact with them.</dd>
 </dl>
diff --git a/docs/html/resources/articles/live-wallpapers.jd b/docs/html/resources/articles/live-wallpapers.jd
new file mode 100644
index 0000000..8dda879
--- /dev/null
+++ b/docs/html/resources/articles/live-wallpapers.jd
@@ -0,0 +1,84 @@
+page.title=Live Wallpapers
+@jd:body
+
+<p>Starting with Android 2.1 (API Level 7), users can now enjoy <em>live
+wallpapers</em> &mdash; richer, animated, interactive backgrounds &mdash; on
+their home screens. A live wallpaper is very similar to a normal Android
+application and has access to all the facilities of the platform: SGL (2D
+drawing), OpenGL (3D drawing), GPS, accelerometers, network access, etc. The
+live wallpapers included on Nexus One demonstrate the use of some of these APIs
+to create fun and interesting user experiences. For instance, the Grass
+wallpaper uses the phone's location to compute sunrise and sunset times in order
+to display the appropriate sky.</p>
+
+<img src="images/live_wallpapers_small.png" style="align:center" />
+
+<p>Creating your own live wallpaper is easy, especially if you have had
+previous experience with <a
+href="../../../reference/android/view/SurfaceView.html"><code>SurfaceView</code></a> or <a
+href="../../../reference/android/graphics/Canvas.html"><code>Canvas</code></a>. 
+To learn how to create a live wallpaper, you should check out the <a 
+href="../samples/CubeLiveWallpaper/index.html">CubeLiveWallpaper sample code</a>.</p>
+
+<p>In terms of implementation, a live wallpaper is very similar to a regular
+Android <a href="../../../reference/android/app/Service.html">service</a>. The
+only difference is the addition of a new method, <a
+href="../../../reference/android/service/wallpaper/WallpaperService.
+html#onCreateEngine()"><code>onCreateEngine()</code></a>, whose goal is to create a <a
+href="../../../reference/android/service/wallpaper/WallpaperService.Engine.html">
+<code>WallpaperService.Engine</code></a>. The engine is responsible for
+handling the lifecycle and drawing of a wallpaper. The system provides a surface
+on which you can draw, just like you would with a <code>SurfaceView</code></a>.
+Drawing a wallpaper can be very expensive so you should optimize your code
+as much as possible to avoid using too much CPU, not only for battery life
+but also to avoid slowing down the rest of the system. That is also why the
+most important part of the lifecycle of a wallpaper is <a href="../../../reference/android/service/wallpaper/WallpaperService.Engine.html#onVisibilityChanged%28boolean%29">when it becomes invisible</a>. 
+When invisible, such as when the user launches an application that covers
+the home screen, a wallpaper must stop all activity.</p>
+
+<p>The engine can also implement several methods to interact with the user
+or the home application. For instance, if you want your wallpaper to scroll
+along when the user swipes from one home screen to another, you can use <a href="../../../reference/android/service/wallpaper/WallpaperService.Engine.html#onOffsetsChanged%28float,%20float,%20float,%20float,%20int,%20int%29"><code>onOffsetsChanged()</code></a>.
+To react to touch events, simply implement <a href="../../../reference/android/service/wallpaper/WallpaperService.Engine.html#onTouchEvent%28android.view.MotionEvent%29"><code>onTouchEvent(MotionEvent)</code></a>.
+Finally, applications can send arbitrary commands to the live wallpaper.
+Currently, only the standard home application sends commands to the <a
+href="../../../reference/android/service/wallpaper/WallpaperService.Engine.html#onCommand%28java.lang.String,%20int,%20int,%20int,%20android.os.Bundle,%20boolean%29"><code>onCommand()</code></a>
+method of the live wallpaper:</p>
+
+<ul>
+<li><code>android.wallpaper.tap</code>: When the user taps an empty space
+on the workspace. This command is interpreted by the Nexus and Water live
+wallpapers to make the wallpaper react to user interaction. For instance,
+if you tap an empty space on the Water live wallpaper, new ripples appear
+under your finger.</li>
+<li><code>android.home.drop</code>: When the user drops an icon or a widget
+on the workspace. This command is also interpreted by the Nexus and Water
+live wallpapers.</li>
+</ul>
+
+<p>If you are developing a live wallpaper, remember that the feature is
+supported only on Android 2.1 (API level 7) and higher versions of the platform.
+To ensure that your application can only be installed on devices that support
+live wallpapers, remember to add the following to the application's manifest
+before publishing to Android Market:</p>
+
+<ul>
+<li><code>&lt;uses-sdk android:minSdkVersion="7" /&gt;</code>, which indicates
+to Android Market and the platform that your application requires Android 2.1 or
+higher. For more information, see the <a href="../../../guide/appendix/api-levels.html">API
+Levels</a> and the documentation for the
+<a href="../../../guide/topics/manifest/uses-sdk-element.html"><code>&lt;uses-sdk&gt;</code></a>
+element.</li>
+<li><code>&lt;uses-feature android:name="android.software.live_wallpaper" /&gt;</code>,
+which tells Android Market that your application includes a live wallpaper
+Android Market uses this feature as a filter, when presenting users lists of
+available applications. When you declaring this feature, Android Market
+displays your application only to users whose devices support live wallpapers,
+while hiding it from other devices on which it would not be able to run. For
+more information, see the documentation for the
+<a href="../../../guide/topics/manifest/uses-feature-element.html"><code>&lt;uses-feature&gt;</code></a>
+element.</li>
+</ul>
+
+<p>Many great live wallpapers are already available on Android Market and
+we can't wait to see more!</p>
diff --git a/docs/html/resources/resources_toc.cs b/docs/html/resources/resources_toc.cs
index e337e38..0972029 100644
--- a/docs/html/resources/resources_toc.cs
+++ b/docs/html/resources/resources_toc.cs
@@ -83,6 +83,9 @@
         <li><a href="<?cs var:toroot ?>resources/articles/live-folders.html">
                 <span class="en">Live Folders</span>
                 </a></li>
+        <li><a href="<?cs var:toroot ?>resources/articles/live-wallpapers.html">
+                <span class="en">Live Wallpapers</span>
+                </a> <span class="new">new!</span></li>
         <li><a href="<?cs var:toroot ?>resources/articles/on-screen-inputs.html">
                 <span class="en">Onscreen Input Methods</span>
                 </a></li>
@@ -178,28 +181,34 @@
               </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/BluetoothChat/index.html">
                 <span class="en">Bluetooth Chat</span>
-              </a> <span class="new">new!</span></li>
+              </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/BusinessCard/index.html">
                 <span class="en">Business Card</span>
-              </a> <span class="new">new!</span></li>
+              </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/ContactManager/index.html">
                 <span class="en">Contact Manager</span>
-              </a> <span class="new">new!</span></li>
+              </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/Home/index.html">
                 <span class="en">Home</span>
               </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/JetBoy/index.html">
                 <span class="en">JetBoy</span>
               </a></li>
+          <li><a href="<?cs var:toroot ?>resources/samples/CubeLiveWallpaper/index.html">
+                <span class="en">Live Wallpaper</span>
+                </a> <span class="new">new!</span></li>
           <li><a href="<?cs var:toroot ?>resources/samples/LunarLander/index.html">
                 <span class="en">Lunar Lander</span>
               </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/MultiResolution/index.html">
                 <span class="en">Multiple Resolutions</span>
-              </a> <span class="new">new!</span></li>
+              </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/NotePad/index.html">
                 <span class="en">Note Pad</span>
               </a></li>
+          <li><a href="<?cs var:toroot ?>resources/samples/SampleSyncAdapter/index.html">
+                <span class="en">Sample Sync Adapter</span>
+              </a> <span class="new">new!</span></li>
           <li><a href="<?cs var:toroot ?>resources/samples/SearchableDictionary/index.html">
                 <span class="en">Searchable Dictionary</span>
               </a></li>
@@ -211,10 +220,10 @@
               </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/Wiktionary/index.html">
                 <span class="en">Wiktionary</span>
-              </a> <span class="new">new!</span></li>
+              </a></li>
           <li><a href="<?cs var:toroot ?>resources/samples/WiktionarySimple/index.html">
                 <span class="en">Wiktionary (Simplified)</span>
-              </a> <span class="new">new!</span></li>
+              </a></li>
         </ul>
       </li>
     </ul>
diff --git a/docs/html/resources/samples/images/CubeLiveWallpaper1.png b/docs/html/resources/samples/images/CubeLiveWallpaper1.png
new file mode 100644
index 0000000..55bc1e9
--- /dev/null
+++ b/docs/html/resources/samples/images/CubeLiveWallpaper1.png
Binary files differ
diff --git a/docs/html/resources/samples/images/CubeLiveWallpaper3.png b/docs/html/resources/samples/images/CubeLiveWallpaper3.png
new file mode 100644
index 0000000..2747a88
--- /dev/null
+++ b/docs/html/resources/samples/images/CubeLiveWallpaper3.png
Binary files differ
diff --git a/docs/html/resources/samples/index.jd b/docs/html/resources/samples/index.jd
index 0beb781..5ebf41c 100644
--- a/docs/html/resources/samples/index.jd
+++ b/docs/html/resources/samples/index.jd
@@ -27,10 +27,10 @@
 platforms) and allow you to view the source files in your browser. </p>
 
 <div class="special">
-  <p>Some of the samples in this listing are not yet available in the
-  SDK. While we work to update the SDK, you can
-  <a href="{@docRoot}shareables/latest_samples.zip">download the latest samples</a> as a ZIP
-  archive.</p>
+  <p>Some of the samples in this listing may not yet be available in the
+  SDK. To ensure that you have the latest versions of the samples, you can
+  <a href="{@docRoot}shareables/latest_samples.zip">download the samples pack</a>
+  as a .zip archive.</p>
 </div>
 
 <dl>
@@ -55,11 +55,15 @@
 
  <dt><a href="Home/index.html">Home</a></dt>
   <dd>A home screen replacement application.</dd>
-  
+
  <dt><a href="JetBoy/index.html">JetBoy</a></dt>
   <dd>A game that demonstrates the SONiVOX JET interactive music technology,
   with {@link android.media.JetPlayer}.</dd>
-    
+
+ <dt><a href="CubeLiveWallpaper/index.html">Live Wallpaper</a></dt>
+  <dd>An application that demonstrates how to create a live wallpaper and 
+  bundle it in an application that users can install on their devices.</dd>
+
  <dt><a href="LunarLander/index.html">Lunar Lander</a></dt>
   <dd>A classic Lunar Lander game.</dd>
 
@@ -70,14 +74,21 @@
  <dt><a href="NotePad/index.html">Note Pad</a></dt>
   <dd>An application for saving notes. Similar (but not identical) to the 
     <a href="{@docRoot}resources/tutorials/notepad/index.html">Notepad tutorial</a>.</dd>
-  
+
+ <dt><a href="SampleSyncAdapter/index.html">SampleSyncAdapter</a></dt>
+  <dd>Demonstrates how an application can communicate with a
+cloud-based service and synchronize its data with data stored locally in a
+content provider. The sample uses two related parts of the Android framework
+&mdash; the account manager and the synchronization manager (through a sync
+adapter).</dd>
+
  <dt><a href="SearchableDictionary/index.html">Searchable Dictionary</a></dt>
   <dd>A sample application that demonstrates Android's search framework, 
   including how to provide search suggestions for Quick Search Box.</dd>
-  
+
  <dt><a href="Snake/index.html">Snake</a></dt>
   <dd>An implementation of the classic game "Snake."</dd>
-  
+
  <dt><a href="SoftKeyboard/index.html">Soft Keyboard</a></dt>
   <dd>An example of writing an input method for a software keyboard.</dd>
 
diff --git a/docs/html/shareables/latest_samples.zip b/docs/html/shareables/latest_samples.zip
index 42fad99..34102c5 100644
--- a/docs/html/shareables/latest_samples.zip
+++ b/docs/html/shareables/latest_samples.zip
Binary files differ
diff --git a/docs/html/sitemap.txt b/docs/html/sitemap.txt
index f82b2fe..5039dfc 100644
--- a/docs/html/sitemap.txt
+++ b/docs/html/sitemap.txt
@@ -2864,11 +2864,6 @@
 http://developer.android.com/reference/org/apache/http/cookie/params/package-descr.html
 http://developer.android.com/reference/java/util/concurrent/locks/package-descr.html
 http://developer.android.com/reference/org/apache/http/conn/routing/package-descr.html
-http://developer.android.com/guide/samples/index.html
-http://developer.android.com/guide/tutorials/notepad/notepad-ex1.html
-http://developer.android.com/guide/tutorials/notepad/notepad-ex2.html
-http://developer.android.com/guide/tutorials/notepad/notepad-ex3.html
-http://developer.android.com/guide/tutorials/notepad/notepad-extra-credit.html
 http://developer.android.com/guide/appendix/faq/commontasks.html
 http://developer.android.com/reference/javax/security/cert/package-descr.html
 http://developer.android.com/reference/org/xml/sax/ext/package-descr.html
@@ -3029,7 +3024,6 @@
 http://developer.android.com/sdk/api_diff/6/changes/android.view.WindowManager.LayoutParams.html
 http://developer.android.com/reference/android/net/package-descr.html
 http://developer.android.com/reference/org/apache/http/client/package-descr.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html
 http://developer.android.com/sdk/download.html?v=archives/android-sdk-windows-1.6_r1.zip
 http://developer.android.com/sdk/download.html?v=archives/android-sdk-mac_x86-1.6_r1.zip
 http://developer.android.com/sdk/download.html?v=archives/android-sdk-linux_x86-1.6_r1.tgz
@@ -3299,7 +3293,6 @@
 http://developer.android.com/resources/samples/BluetoothChat/res/layout/message.html
 http://developer.android.com/resources/samples/NotePad/res/drawable-ldpi-v6/app_notes.html
 http://developer.android.com/resources/samples/NotePad/res/drawable-ldpi-v6/live_folder_notes.html
-http://developer.android.com/guide/tutorials/views/index.html
 http://developer.android.com/sdk/api_diff/4/changes/pkg_android.html
 http://developer.android.com/sdk/api_diff/4/changes/pkg_android.app.html
 http://developer.android.com/sdk/api_diff/4/changes/pkg_android.content.res.html
@@ -3523,21 +3516,6 @@
 http://developer.android.com/resources/samples/ApiDemos/tests/src/com/example/android/apis/index.html
 http://developer.android.com/reference/org/apache/http/conn/ssl/package-descr.html
 http://developer.android.com/resources/samples/ContactManager/res/drawable-hdpi/icon.html
-http://developer.android.com/guide/tutorials/views/hello-linearlayout.html
-http://developer.android.com/guide/tutorials/views/hello-relativelayout.html
-http://developer.android.com/guide/tutorials/views/hello-tablelayout.html
-http://developer.android.com/guide/tutorials/views/hello-datepicker.html
-http://developer.android.com/guide/tutorials/views/hello-timepicker.html
-http://developer.android.com/guide/tutorials/views/hello-formstuff.html
-http://developer.android.com/guide/tutorials/views/hello-spinner.html
-http://developer.android.com/guide/tutorials/views/hello-autocomplete.html
-http://developer.android.com/guide/tutorials/views/hello-listview.html
-http://developer.android.com/guide/tutorials/views/hello-gridview.html
-http://developer.android.com/guide/tutorials/views/hello-gallery.html
-http://developer.android.com/guide/tutorials/views/hello-tabwidget.html
-http://developer.android.com/guide/tutorials/views/hello-mapview.html
-http://developer.android.com/guide/tutorials/views/hello-webview.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/index.html
 http://developer.android.com/sdk/api_diff/5/changes/packages_index_all.html
 http://developer.android.com/sdk/api_diff/5/changes/classes_index_all.html
 http://developer.android.com/sdk/api_diff/5/changes/constructors_index_all.html
@@ -3858,112 +3836,6 @@
 http://developer.android.com/reference/org/w3c/dom/package-descr.html
 http://developer.android.com/reference/org/apache/http/package-descr.html
 http://developer.android.com/resources/samples/MultiResolution/src/com/example/index.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/RelativeLayout1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/RelativeLayout2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout4.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout5.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout6.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout7.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout8.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout9.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ScrollView1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ScrollView2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout4.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout5.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout6.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout7.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout8.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout9.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout10.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout11.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TableLayout12.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Baseline1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Baseline2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Baseline3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Baseline4.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Baseline6.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Baseline7.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/BaselineNested1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/BaselineNested2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/BaselineNested3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/RadioGroup1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ScrollBar1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ScrollBar2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Visibility1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List4.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List5.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List6.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List7.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List8.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/CustomView1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ImageButton1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/DateWidgets1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/DateWidgets2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Gallery1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Gallery2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Spinner1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Grid1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Grid2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ImageSwitcher1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/TextSwitcher1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Animation1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Animation2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Controls1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Controls2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete4.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete5.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ProgressBar4.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Focus1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Focus2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Focus3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Animation3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/AutoComplete6.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Buttons1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ChronometerDemo.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ExpandableList1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ExpandableList2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ExpandableList3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ImageView1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/InternalSelectionFocus.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/InternalSelectionScroll.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/InternalSelectionView.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LabelView.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation4.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation5.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation6.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LayoutAnimation7.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/LinearLayout10.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List10.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List11.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List12.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List13.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List14.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/List9.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/RatingBar1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/ScrollBar3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/SeekBar1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Tabs1.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Tabs2.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/Tabs3.html
-http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/view/WebView1.html
 http://developer.android.com/resources/samples/Home/res/drawable/all_applications.html
 http://developer.android.com/resources/samples/Home/res/drawable/all_applications_background.html
 http://developer.android.com/resources/samples/Home/res/drawable/all_applications_button_background.html
diff --git a/graphics/java/android/graphics/YuvImage.java b/graphics/java/android/graphics/YuvImage.java
index 09b4bf4..5a4531b 100644
--- a/graphics/java/android/graphics/YuvImage.java
+++ b/graphics/java/android/graphics/YuvImage.java
@@ -21,13 +21,11 @@
 /**
  * YuvImage contains YUV data and provides a method that compresses a region of
  * the YUV data to a Jpeg. The YUV data should be provided as a single byte
- * array irrespective of the number of image planes in it. The stride of each
- * image plane should be provided as well.
+ * array irrespective of the number of image planes in it.
+ * Currently only PixelFormat.YCbCr_420_SP and PixelFormat.YCbCr_422_I are supported.
  *
- * To compress a rectangle region in the YUV data, users have to specify a
- * region by width, height and offsets, where each image plane has a
- * corresponding offset. All offsets are measured as a displacement in bytes
- * from yuv[0], where yuv[0] is the beginning of the yuv data.
+ * To compress a rectangle region in the YUV data, users have to specify the
+ * region by left, top, width and height.
  */
 public class YuvImage {
 
@@ -55,21 +53,56 @@
     private int[] mStrides;
 
     /**
+     * The width of the image.
+     */
+    private int mWidth;
+
+    /**
+     * The height of the the image.
+     */
+    private int mHeight;
+
+    /**
      * Construct an YuvImage.
      *
-     * @param yuv The YUV data. In the case of more than one image plane, all the planes must be
-     *            concatenated into a single byte array.
-     * @param format The YUV data format as defined in {@link PixelFormat}.
-     * @param strides Row bytes of each image plane.
+     * @param yuv     The YUV data. In the case of more than one image plane, all the planes must be
+     *                concatenated into a single byte array.
+     * @param format  The YUV data format as defined in {@link PixelFormat}.
+     * @param width   The width of the YuvImage.
+     * @param height  The height of the YuvImage.
+     * @param strides (Optional) Row bytes of each image plane. If yuv contains padding, the stride
+     *                of each image must be provided. If strides is null, the method assumes no
+     *                padding and derives the row bytes by format and width itself.
+     * @throws IllegalArgumentException if format is not support; width or height <= 0; or yuv is
+     *                null.
      */
-    public YuvImage(byte[] yuv, int format, int[] strides) {
-        if ((yuv == null) || (strides == null)) {
+    public YuvImage(byte[] yuv, int format, int width, int height, int[] strides) {
+        if (format != PixelFormat.YCbCr_420_SP &&
+                format != PixelFormat.YCbCr_422_I) {
             throw new IllegalArgumentException(
-                    "yuv or strides cannot be null");
+                    "only support PixelFormat.YCbCr_420_SP " +
+                    "and PixelFormat.YCbCr_422_I for now");
         }
+
+        if (width <= 0  || height <= 0) {
+            throw new IllegalArgumentException(
+                    "width and height must large than 0");
+        }
+
+        if (yuv == null) {
+            throw new IllegalArgumentException("yuv cannot be null");
+        }
+
+        if (strides == null) {
+            mStrides = calculateStrides(width, format);
+        } else {
+            mStrides = strides;
+        }
+
         mData = yuv;
         mFormat = format;
-        mStrides = strides;
+        mWidth = width;
+        mHeight = height;
     }
 
     /**
@@ -77,22 +110,21 @@
      * Only PixelFormat.YCbCr_420_SP and PixelFormat.YCbCr_422_I
      * are supported for now.
      *
-     * @param width The width of the rectangle region.
-     * @param height The height of the rectangle region.
-     * @param offsets The offsets of the rectangle region in each image plane.
-     *                The offsets are measured as a displacement in bytes from
-     *                yuv[0], where yuv[0] is the beginning of the yuv data.
-     * @param quality  Hint to the compressor, 0-100. 0 meaning compress for
-     *                 small size, 100 meaning compress for max quality.
-     * @param stream   The outputstream to write the compressed data.
-     *
-     * @return true if successfully compressed to the specified stream.
-     *
+     * @param rectangle The rectangle region to be compressed. The medthod checks if rectangle is
+     *                  inside the image. Also, the method modifies rectangle if the chroma pixels
+     *                  in it are not matched with the luma pixels in it.
+     * @param quality   Hint to the compressor, 0-100. 0 meaning compress for
+     *                  small size, 100 meaning compress for max quality.
+     * @param stream    OutputStream to write the compressed data.
+     * @return          True if the compression is successful.
+     * @throws IllegalArgumentException if rectangle is invalid; quality is not within [0,
+     *                  100]; or stream is null.
      */
-    public boolean compressToJpeg(int width, int height, int[] offsets, int quality,
-            OutputStream stream) {
-        if (!validate(mFormat, width, height, offsets)) {
-            return false;
+    public boolean compressToJpeg(Rect rectangle, int quality, OutputStream stream) {
+        Rect wholeImage = new Rect(0, 0, mWidth, mHeight);
+        if (!wholeImage.contains(rectangle)) {
+            throw new IllegalArgumentException(
+                    "rectangle is not inside the image");
         }
 
         if (quality < 0 || quality > 100) {
@@ -100,14 +132,19 @@
         }
 
         if (stream == null) {
-            throw new NullPointerException();
+            throw new IllegalArgumentException("stream cannot be null");
         }
 
-        return nativeCompressToJpeg(mData, mFormat, width, height, offsets,
-                mStrides, quality, stream, new byte[WORKING_COMPRESS_STORAGE]);
+        adjustRectangle(rectangle);
+        int[] offsets = calculateOffsets(rectangle.left, rectangle.top);
+
+        return nativeCompressToJpeg(mData, mFormat, rectangle.width(),
+                rectangle.height(), offsets, mStrides, quality, stream,
+                new byte[WORKING_COMPRESS_STORAGE]);
     }
 
-    /**
+
+   /**
      * @return the YUV data.
      */
     public byte[] getYuvData() {
@@ -128,37 +165,71 @@
         return mStrides;
     }
 
-    protected boolean validate(int format, int width, int height, int[] offsets) {
-        if (format != PixelFormat.YCbCr_420_SP &&
-                format != PixelFormat.YCbCr_422_I) {
-            throw new IllegalArgumentException(
-                    "only support PixelFormat.YCbCr_420_SP " +
-                    "and PixelFormat.YCbCr_422_I for now");
+    /**
+     * @return the width of the image.
+     */
+    public int getWidth() {
+        return mWidth;
+    }
+
+    /**
+     * @return the height of the image.
+     */
+    public int getHeight() {
+        return mHeight;
+    }
+
+    int[] calculateOffsets(int left, int top) {
+        int[] offsets = null;
+        if (mFormat == PixelFormat.YCbCr_420_SP) {
+            offsets = new int[] {top * mStrides[0] + left,
+                  mHeight * mStrides[0] + top / 2 * mStrides[1]
+                  + left / 2 * 2 };
+            return offsets;
         }
 
-        if (offsets.length != mStrides.length) {
-            throw new IllegalArgumentException(
-                    "the number of image planes are mismatched");
+        if (mFormat == PixelFormat.YCbCr_422_I) {
+            offsets = new int[] {top * mStrides[0] + left / 2 * 4};
+            return offsets;
         }
 
-        if (width <= 0  || height <= 0) {
-            throw new IllegalArgumentException(
-                    "width and height must large than 0");
-        }
+        return offsets;
+    }
 
-        int requiredSize;
+    private int[] calculateStrides(int width, int format) {
+        int[] strides = null;
         if (format == PixelFormat.YCbCr_420_SP) {
-            requiredSize = height * mStrides[0] +(height >> 1) * mStrides[1];
-        } else {
-            requiredSize = height * mStrides[0];
+            strides = new int[] {width, width};
+            return strides;
         }
 
-        if (requiredSize > mData.length) {
-            throw new IllegalArgumentException(
-                    "width or/and height is larger than the yuv data");
+        if (format == PixelFormat.YCbCr_422_I) {
+            strides = new int[] {width * 2};
+            return strides;
         }
 
-        return true;
+        return strides;
+    }
+
+   private void adjustRectangle(Rect rect) {
+       int width = rect.width();
+       int height = rect.height();
+       if (mFormat == PixelFormat.YCbCr_420_SP) {
+           // Make sure left, top, width and height are all even.
+           width &= ~1;
+           height &= ~1;
+           rect.left &= ~1;
+           rect.top &= ~1;
+           rect.right = rect.left + width;
+           rect.bottom = rect.top + height;
+        }
+
+        if (mFormat == PixelFormat.YCbCr_422_I) {
+            // Make sure left and width are both even.
+            width &= ~1;
+            rect.left &= ~1;
+            rect.right = rect.left + width;
+        }
     }
 
     //////////// native methods
diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java
index c4a7822..2083e05 100644
--- a/graphics/java/android/graphics/drawable/RotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/RotateDrawable.java
@@ -204,13 +204,27 @@
                 com.android.internal.R.styleable.RotateDrawable_visible);
         
         TypedValue tv = a.peekValue(com.android.internal.R.styleable.RotateDrawable_pivotX);
-        boolean pivotXRel = tv.type == TypedValue.TYPE_FRACTION;
-        float pivotX = pivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
+        boolean pivotXRel;
+        float pivotX;
+        if (tv == null) {
+            pivotXRel = true;
+            pivotX = 0.5f;
+        } else {
+            pivotXRel = tv.type == TypedValue.TYPE_FRACTION;
+            pivotX = pivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
+        }
         
         tv = a.peekValue(com.android.internal.R.styleable.RotateDrawable_pivotY);
-        boolean pivotYRel = tv.type == TypedValue.TYPE_FRACTION;
-        float pivotY = pivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
-        
+        boolean pivotYRel;
+        float pivotY;
+        if (tv == null) {
+            pivotYRel = true;
+            pivotY = 0.5f;
+        } else {
+            pivotYRel = tv.type == TypedValue.TYPE_FRACTION;
+            pivotY = pivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
+        }
+
         float fromDegrees = a.getFloat(
                 com.android.internal.R.styleable.RotateDrawable_fromDegrees, 0.0f);
         float toDegrees = a.getFloat(
diff --git a/graphics/java/android/renderscript/RSSurfaceView.java b/graphics/java/android/renderscript/RSSurfaceView.java
index ad1bb54..1d3f82d 100644
--- a/graphics/java/android/renderscript/RSSurfaceView.java
+++ b/graphics/java/android/renderscript/RSSurfaceView.java
@@ -36,7 +36,7 @@
  **/
 public class RSSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
     private SurfaceHolder mSurfaceHolder;
-    private RenderScript mRS;
+    private RenderScriptGL mRS;
 
     /**
      * Standard View constructor. In order to render something, you
@@ -146,13 +146,13 @@
 
     // ----------------------------------------------------------------------
 
-    public RenderScript createRenderScript(boolean useDepth, boolean forceSW) {
+    public RenderScriptGL createRenderScript(boolean useDepth, boolean forceSW) {
         Log.v(RenderScript.LOG_TAG, "createRenderScript");
-        mRS = new RenderScript(useDepth, forceSW);
+        mRS = new RenderScriptGL(useDepth, forceSW);
         return mRS;
     }
 
-    public RenderScript createRenderScript(boolean useDepth) {
+    public RenderScriptGL createRenderScript(boolean useDepth) {
         return createRenderScript(useDepth, false);
     }
 
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 29361af..84b1a70 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -31,11 +31,9 @@
  **/
 public class RenderScript {
     static final String LOG_TAG = "RenderScript_jni";
-    private static final boolean DEBUG  = false;
+    protected static final boolean DEBUG  = false;
     @SuppressWarnings({"UnusedDeclaration", "deprecation"})
-    private static final boolean LOG_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;
-    int mWidth;
-    int mHeight;
+    protected static final boolean LOG_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;
 
 
 
@@ -44,8 +42,8 @@
      * field offsets.
      */
     @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
-    private static boolean sInitialized;
-    native private static void _nInit();
+    protected static boolean sInitialized;
+    native protected static void _nInit();
 
 
     static {
@@ -64,7 +62,8 @@
     native int  nDeviceCreate();
     native void nDeviceDestroy(int dev);
     native void nDeviceSetConfig(int dev, int param, int value);
-    native int  nContextCreate(int dev, int ver, boolean useDepth);
+    native int  nContextCreateGL(int dev, int ver, boolean useDepth);
+    native int  nContextCreate(int dev, int ver);
     native void nContextDestroy(int con);
     native void nContextSetSurface(int w, int h, Surface sur);
     native void nContextSetPriority(int p);
@@ -190,11 +189,10 @@
     native void nAnimationAdd(float time, float[] attribs);
     native int  nAnimationCreate();
 
-    private int     mDev;
-    private int     mContext;
+    protected int     mDev;
+    protected int     mContext;
     @SuppressWarnings({"FieldCanBeLocal"})
-    private Surface mSurface;
-    private MessageThread mMessageThread;
+    protected MessageThread mMessageThread;
 
     Element mElement_USER_U8;
     Element mElement_USER_I8;
@@ -251,7 +249,7 @@
         nContextSetPriority(p.mID);
     }
 
-    private static class MessageThread extends Thread {
+    protected static class MessageThread extends Thread {
         RenderScript mRS;
         boolean mRun = true;
 
@@ -289,26 +287,18 @@
         }
     }
 
-    public RenderScript(boolean useDepth, boolean forceSW) {
-        mSurface = null;
-        mWidth = 0;
-        mHeight = 0;
-        mDev = nDeviceCreate();
-        if(forceSW) {
-            nDeviceSetConfig(mDev, 0, 1);
-        }
-        mContext = nContextCreate(mDev, 0, useDepth);
-        mMessageThread = new MessageThread(this);
-        mMessageThread.start();
-        Element.initPredefined(this);
+    protected RenderScript() {
     }
 
-    public void contextSetSurface(int w, int h, Surface sur) {
-        mSurface = sur;
-        mWidth = w;
-        mHeight = h;
-        validate();
-        nContextSetSurface(w, h, mSurface);
+    public static RenderScript create() {
+        RenderScript rs = new RenderScript();
+
+        rs.mDev = rs.nDeviceCreate();
+        rs.mContext = rs.nContextCreate(rs.mDev, 0);
+        rs.mMessageThread = new MessageThread(rs);
+        rs.mMessageThread.start();
+        Element.initPredefined(rs);
+        return rs;
     }
 
     public void contextDump(int bits) {
@@ -332,77 +322,15 @@
         return mContext != 0;
     }
 
-    void pause() {
-        validate();
-        nContextPause();
-    }
-
-    void resume() {
-        validate();
-        nContextResume();
-    }
-
-    //////////////////////////////////////////////////////////////////////////////////
-    // File
-
-    public class File extends BaseObj {
-        File(int id) {
-            super(RenderScript.this);
-            mID = id;
-        }
-    }
-
-    public File fileOpen(String s) throws IllegalStateException, IllegalArgumentException
-    {
-        if(s.length() < 1) {
-            throw new IllegalArgumentException("fileOpen does not accept a zero length string.");
-        }
-
-        try {
-            byte[] bytes = s.getBytes("UTF-8");
-            int id = nFileOpen(bytes);
-            return new File(id);
-        } catch (java.io.UnsupportedEncodingException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-
     ///////////////////////////////////////////////////////////////////////////////////
     // Root state
 
-    private int safeID(BaseObj o) {
+    protected int safeID(BaseObj o) {
         if(o != null) {
             return o.mID;
         }
         return 0;
     }
-
-    public void contextBindRootScript(Script s) {
-        validate();
-        nContextBindRootScript(safeID(s));
-    }
-
-    public void contextBindProgramFragmentStore(ProgramStore p) {
-        validate();
-        nContextBindProgramFragmentStore(safeID(p));
-    }
-
-    public void contextBindProgramFragment(ProgramFragment p) {
-        validate();
-        nContextBindProgramFragment(safeID(p));
-    }
-
-    public void contextBindProgramRaster(ProgramRaster p) {
-        validate();
-        nContextBindProgramRaster(safeID(p));
-    }
-
-    public void contextBindProgramVertex(ProgramVertex p) {
-        validate();
-        nContextBindProgramVertex(safeID(p));
-    }
-
 }
 
 
diff --git a/graphics/java/android/renderscript/RenderScriptGL.java b/graphics/java/android/renderscript/RenderScriptGL.java
new file mode 100644
index 0000000..d1df23d
--- /dev/null
+++ b/graphics/java/android/renderscript/RenderScriptGL.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 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.
+ */
+
+package android.renderscript;
+
+import java.lang.reflect.Field;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.util.Config;
+import android.util.Log;
+import android.view.Surface;
+
+
+/**
+ * @hide
+ *
+ **/
+public class RenderScriptGL extends RenderScript {
+    private Surface mSurface;
+    int mWidth;
+    int mHeight;
+
+
+    public RenderScriptGL(boolean useDepth, boolean forceSW) {
+        mSurface = null;
+        mWidth = 0;
+        mHeight = 0;
+        mDev = nDeviceCreate();
+        if(forceSW) {
+            nDeviceSetConfig(mDev, 0, 1);
+        }
+        mContext = nContextCreateGL(mDev, 0, useDepth);
+        mMessageThread = new MessageThread(this);
+        mMessageThread.start();
+        Element.initPredefined(this);
+    }
+
+    public void contextSetSurface(int w, int h, Surface sur) {
+        mSurface = sur;
+        mWidth = w;
+        mHeight = h;
+        validate();
+        nContextSetSurface(w, h, mSurface);
+    }
+
+
+    void pause() {
+        validate();
+        nContextPause();
+    }
+
+    void resume() {
+        validate();
+        nContextResume();
+    }
+
+
+    public void contextBindRootScript(Script s) {
+        validate();
+        nContextBindRootScript(safeID(s));
+    }
+
+    public void contextBindProgramFragmentStore(ProgramStore p) {
+        validate();
+        nContextBindProgramFragmentStore(safeID(p));
+    }
+
+    public void contextBindProgramFragment(ProgramFragment p) {
+        validate();
+        nContextBindProgramFragment(safeID(p));
+    }
+
+    public void contextBindProgramRaster(ProgramRaster p) {
+        validate();
+        nContextBindProgramRaster(safeID(p));
+    }
+
+    public void contextBindProgramVertex(ProgramVertex p) {
+        validate();
+        nContextBindProgramVertex(safeID(p));
+    }
+
+
+
+
+    //////////////////////////////////////////////////////////////////////////////////
+    // File
+
+    public class File extends BaseObj {
+        File(int id) {
+            super(RenderScriptGL.this);
+            mID = id;
+        }
+    }
+
+    public File fileOpen(String s) throws IllegalStateException, IllegalArgumentException
+    {
+        if(s.length() < 1) {
+            throw new IllegalArgumentException("fileOpen does not accept a zero length string.");
+        }
+
+        try {
+            byte[] bytes = s.getBytes("UTF-8");
+            int id = nFileOpen(bytes);
+            return new File(id);
+        } catch (java.io.UnsupportedEncodingException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+}
+
+
diff --git a/graphics/jni/Android.mk b/graphics/jni/Android.mk
index 799fcbb..8476be1 100644
--- a/graphics/jni/Android.mk
+++ b/graphics/jni/Android.mk
@@ -19,7 +19,8 @@
         libcutils \
         libskia \
         libutils \
-        libui
+        libui \
+        libsurfaceflinger_client 
 
 LOCAL_STATIC_LIBRARIES :=
 
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 7ded133..0ffdf71 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -23,7 +23,7 @@
 #include <math.h>
 #include <utils/misc.h>
 
-#include <ui/Surface.h>
+#include <surfaceflinger/Surface.h>
 
 #include <core/SkBitmap.h>
 #include <core/SkPixelRef.h>
@@ -151,10 +151,17 @@
 }
 
 static jint
-nContextCreate(JNIEnv *_env, jobject _this, jint dev, jint ver, jboolean useDepth)
+nContextCreate(JNIEnv *_env, jobject _this, jint dev, jint ver)
 {
     LOG_API("nContextCreate");
-    return (jint)rsContextCreate((RsDevice)dev, ver, useDepth);
+    return (jint)rsContextCreate((RsDevice)dev, ver);
+}
+
+static jint
+nContextCreateGL(JNIEnv *_env, jobject _this, jint dev, jint ver, jboolean useDepth)
+{
+    LOG_API("nContextCreateGL");
+    return (jint)rsContextCreateGL((RsDevice)dev, ver, useDepth);
 }
 
 static void
@@ -260,7 +267,7 @@
 {
     int fieldCount = _env->GetArrayLength(_ids);
     RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    LOG_API("nElementCreate, con(%p), type(%i), kind(%i), norm(%i), size(%i)", con, type, kind, norm, size);
+    LOG_API("nElementCreate2, con(%p)", con);
 
     jint *ids = _env->GetIntArrayElements(_ids, NULL);
     const char ** nameArray = (const char **)calloc(fieldCount, sizeof(char *));
@@ -1089,7 +1096,7 @@
     jint *paramPtr = _env->GetIntArrayElements(params, NULL);
     jint paramLen = _env->GetArrayLength(params);
 
-    LOG_API("nProgramFragmentCreate, con(%p), paramLen(%i)", con, shaderLen, paramLen);
+    LOG_API("nProgramFragmentCreate, con(%p), paramLen(%i)", con, paramLen);
 
     jint ret = (jint)rsProgramFragmentCreate(con, (uint32_t *)paramPtr, paramLen);
     _env->ReleaseIntArrayElements(params, paramPtr, JNI_ABORT);
@@ -1332,7 +1339,8 @@
 {"nDeviceCreate",                  "()I",                                  (void*)nDeviceCreate },
 {"nDeviceDestroy",                 "(I)V",                                 (void*)nDeviceDestroy },
 {"nDeviceSetConfig",               "(III)V",                               (void*)nDeviceSetConfig },
-{"nContextCreate",                 "(IIZ)I",                               (void*)nContextCreate },
+{"nContextCreate",                 "(II)I",                                (void*)nContextCreate },
+{"nContextCreateGL",               "(IIZ)I",                               (void*)nContextCreateGL },
 {"nContextSetPriority",            "(I)V",                                 (void*)nContextSetPriority },
 {"nContextSetSurface",             "(IILandroid/view/Surface;)V",          (void*)nContextSetSurface },
 {"nContextDestroy",                "(I)V",                                 (void*)nContextDestroy },
diff --git a/include/ui/Camera.h b/include/camera/Camera.h
similarity index 98%
rename from include/ui/Camera.h
rename to include/camera/Camera.h
index c506fb8..ee2b30c 100644
--- a/include/ui/Camera.h
+++ b/include/camera/Camera.h
@@ -19,10 +19,12 @@
 #define ANDROID_HARDWARE_CAMERA_H
 
 #include <utils/Timers.h>
-#include <ui/ICameraClient.h>
+#include <camera/ICameraClient.h>
 
 namespace android {
 
+class ISurface;
+
 /*
  * A set of bit masks for specifying how the received preview frames are
  * handled before the previewCallback() call.
diff --git a/include/ui/CameraHardwareInterface.h b/include/camera/CameraHardwareInterface.h
similarity index 98%
rename from include/ui/CameraHardwareInterface.h
rename to include/camera/CameraHardwareInterface.h
index 240c134..d877c74 100644
--- a/include/ui/CameraHardwareInterface.h
+++ b/include/camera/CameraHardwareInterface.h
@@ -19,12 +19,14 @@
 
 #include <binder/IMemory.h>
 #include <utils/RefBase.h>
-#include <ui/ISurface.h>
-#include <ui/Camera.h>
-#include <ui/CameraParameters.h>
-#include <ui/Overlay.h>
+#include <surfaceflinger/ISurface.h>
+#include <camera/Camera.h>
+#include <camera/CameraParameters.h>
 
 namespace android {
+
+class Overlay;
+
 /**
  *  The size of image for display.
  */
diff --git a/include/ui/CameraParameters.h b/include/camera/CameraParameters.h
similarity index 96%
rename from include/ui/CameraParameters.h
rename to include/camera/CameraParameters.h
index 2c29bfb..e328f33 100644
--- a/include/ui/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -187,6 +187,13 @@
     // Vertical angle of view in degrees.
     // Example value: "42.5". Read only.
     static const char KEY_VERTICAL_VIEW_ANGLE[];
+    // Exposure compensation. The value is multiplied by 100. -100 means -1 EV.
+    // 130 means +1.3 EV.
+    // Example value: "0" or "133". Read/write.
+    static const char KEY_EXPOSURE_COMPENSATION[];
+    // Supported exposure compensation.
+    // Example value: "-100,-66,-33,0,33,66,100". Read only.
+    static const char KEY_SUPPORTED_EXPOSURE_COMPENSATION[];
 
 
         // Values for white balance settings.
diff --git a/include/ui/ICamera.h b/include/camera/ICamera.h
similarity index 97%
rename from include/ui/ICamera.h
rename to include/camera/ICamera.h
index 5642691..6fcf9e5 100644
--- a/include/ui/ICamera.h
+++ b/include/camera/ICamera.h
@@ -20,10 +20,10 @@
 #include <utils/RefBase.h>
 #include <binder/IInterface.h>
 #include <binder/Parcel.h>
-#include <ui/ISurface.h>
+#include <surfaceflinger/ISurface.h>
 #include <binder/IMemory.h>
 #include <utils/String8.h>
-#include <ui/Camera.h>
+#include <camera/Camera.h>
 
 namespace android {
 
diff --git a/include/ui/ICameraClient.h b/include/camera/ICameraClient.h
similarity index 100%
rename from include/ui/ICameraClient.h
rename to include/camera/ICameraClient.h
diff --git a/include/ui/ICameraService.h b/include/camera/ICameraService.h
similarity index 95%
rename from include/ui/ICameraService.h
rename to include/camera/ICameraService.h
index 061681a..82b1283 100644
--- a/include/ui/ICameraService.h
+++ b/include/camera/ICameraService.h
@@ -21,8 +21,8 @@
 #include <binder/IInterface.h>
 #include <binder/Parcel.h>
 
-#include <ui/ICameraClient.h>
-#include <ui/ICamera.h>
+#include <camera/ICameraClient.h>
+#include <camera/ICamera.h>
 
 namespace android {
 
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
index b6f654f..2619691 100644
--- a/include/media/IMediaPlayer.h
+++ b/include/media/IMediaPlayer.h
@@ -46,6 +46,8 @@
     virtual status_t        setAudioStreamType(int type) = 0;
     virtual status_t        setLooping(int loop) = 0;
     virtual status_t        setVolume(float leftVolume, float rightVolume) = 0;
+    virtual status_t        suspend() = 0;
+    virtual status_t        resume() = 0;
 
     // Invoke a generic method on the player by using opaque parcels
     // for the request and reply.
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index a5a1bb8..9e606d9 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -20,7 +20,6 @@
 #ifdef __cplusplus
 
 #include <sys/types.h>
-#include <ui/ISurface.h>
 #include <utils/Errors.h>
 #include <utils/KeyedVector.h>
 #include <utils/String8.h>
@@ -33,6 +32,8 @@
 namespace android {
 
 class Parcel;
+class ISurface;
+
 template<typename T> class SortedVector;
 
 enum player_type {
@@ -62,7 +63,8 @@
     // AudioSink: abstraction layer for audio output
     class AudioSink : public RefBase {
     public:
-        typedef void (*AudioCallback)(
+        // Callback returns the number of bytes actually written to the buffer.
+        typedef size_t (*AudioCallback)(
                 AudioSink *audioSink, void *buffer, size_t size, void *cookie);
 
         virtual             ~AudioSink() {}
@@ -77,8 +79,7 @@
         virtual status_t    getPosition(uint32_t *position) = 0;
 
         // If no callback is specified, use the "write" API below to submit
-        // audio data. Otherwise return a full buffer of audio data on each
-        // callback.
+        // audio data.
         virtual status_t    open(
                 uint32_t sampleRate, int channelCount,
                 int format=AudioSystem::PCM_16_BIT,
@@ -117,6 +118,9 @@
     virtual status_t    reset() = 0;
     virtual status_t    setLooping(int loop) = 0;
     virtual player_type playerType() = 0;
+    virtual status_t    suspend() { return INVALID_OPERATION; }
+    virtual status_t    resume() { return INVALID_OPERATION; }
+
     virtual void        setNotifyCallback(void* cookie, notify_callback_f notifyFunc) {
                             mCookie = cookie; mNotify = notifyFunc; }
     // Invoke a generic method on the player by using opaque parcels
diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h
index 022b849..9b12410 100644
--- a/include/media/mediametadataretriever.h
+++ b/include/media/mediametadataretriever.h
@@ -55,6 +55,7 @@
     METADATA_KEY_WRITER          = 21,
     METADATA_KEY_MIMETYPE        = 22,
     METADATA_KEY_DISC_NUMBER     = 23,
+    METADATA_KEY_ALBUMARTIST     = 24,
     // Add more here...
 };
 
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index c9198d6..7fad1b7 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -18,7 +18,6 @@
 #define ANDROID_MEDIAPLAYER_H
 
 #include <binder/IMemory.h>
-#include <ui/Surface.h>
 #include <media/IMediaPlayerClient.h>
 #include <media/IMediaPlayer.h>
 #include <media/IMediaDeathNotifier.h>
@@ -28,6 +27,8 @@
 
 namespace android {
 
+class Surface;
+
 enum media_event_type {
     MEDIA_NOP               = 0, // interface test message
     MEDIA_PREPARED          = 1,
@@ -164,6 +165,8 @@
             status_t        invoke(const Parcel& request, Parcel *reply);
             status_t        setMetadataFilter(const Parcel& filter);
             status_t        getMetadata(bool update_only, bool apply_filter, Parcel *metadata);
+            status_t        suspend();
+            status_t        resume();
 private:
             void            clear_l();
             status_t        seekTo_l(int msec);
diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h
index 843e051..8e5f05f 100644
--- a/include/media/stagefright/AudioPlayer.h
+++ b/include/media/stagefright/AudioPlayer.h
@@ -90,11 +90,11 @@
     static void AudioCallback(int event, void *user, void *info);
     void AudioCallback(int event, void *info);
 
-    static void AudioSinkCallback(
+    static size_t AudioSinkCallback(
             MediaPlayerBase::AudioSink *audioSink,
             void *data, size_t size, void *me);
 
-    void fillBuffer(void *data, size_t size);
+    size_t fillBuffer(void *data, size_t size);
 
     int64_t getRealTimeUsLocked() const;
 
diff --git a/include/media/stagefright/HardwareAPI.h b/include/media/stagefright/HardwareAPI.h
index b7daddc..221c679 100644
--- a/include/media/stagefright/HardwareAPI.h
+++ b/include/media/stagefright/HardwareAPI.h
@@ -20,7 +20,7 @@
 
 #include <media/stagefright/OMXPluginBase.h>
 #include <media/stagefright/VideoRenderer.h>
-#include <ui/ISurface.h>
+#include <surfaceflinger/ISurface.h>
 #include <utils/RefBase.h>
 
 #include <OMX_Component.h>
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 8f423f7..45cc4f6 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -51,6 +51,7 @@
 
     kKeyAlbum             = 'albu',  // cstring
     kKeyArtist            = 'arti',  // cstring
+    kKeyAlbumArtist       = 'aart',  // cstring
     kKeyComposer          = 'comp',  // cstring
     kKeyGenre             = 'genr',  // cstring
     kKeyTitle             = 'titl',  // cstring
diff --git a/include/private/ui/LayerState.h b/include/private/surfaceflinger/LayerState.h
similarity index 91%
rename from include/private/ui/LayerState.h
rename to include/private/surfaceflinger/LayerState.h
index f1a2618..d7fe572e 100644
--- a/include/private/ui/LayerState.h
+++ b/include/private/surfaceflinger/LayerState.h
@@ -14,17 +14,18 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_COMPOSER_LAYER_STATE_H
-#define ANDROID_COMPOSER_LAYER_STATE_H
+#ifndef ANDROID_SF_LAYER_STATE_H
+#define ANDROID_SF_LAYER_STATE_H
 
 #include <stdint.h>
 #include <sys/types.h>
 
 #include <utils/Errors.h>
 
-#include <ui/ISurfaceFlingerClient.h>
 #include <ui/Region.h>
 
+#include <surfaceflinger/ISurface.h>
+
 namespace android {
 
 class Parcel;
@@ -69,5 +70,5 @@
 
 }; // namespace android
 
-#endif // ANDROID_COMPOSER_LAYER_STATE_H
+#endif // ANDROID_SF_LAYER_STATE_H
 
diff --git a/include/private/ui/SharedBufferStack.h b/include/private/surfaceflinger/SharedBufferStack.h
similarity index 98%
rename from include/private/ui/SharedBufferStack.h
rename to include/private/surfaceflinger/SharedBufferStack.h
index bbc1822..9b5a1e0 100644
--- a/include/private/ui/SharedBufferStack.h
+++ b/include/private/surfaceflinger/SharedBufferStack.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_UI_SHARED_BUFFER_STACK_H
-#define ANDROID_UI_SHARED_BUFFER_STACK_H
+#ifndef ANDROID_SF_SHARED_BUFFER_STACK_H
+#define ANDROID_SF_SHARED_BUFFER_STACK_H
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -356,4 +356,4 @@
 // ---------------------------------------------------------------------------
 }; // namespace android
 
-#endif /* ANDROID_UI_SHARED_BUFFER_STACK_H */
+#endif /* ANDROID_SF_SHARED_BUFFER_STACK_H */
diff --git a/include/ui/ISurface.h b/include/surfaceflinger/ISurface.h
similarity index 96%
rename from include/ui/ISurface.h
rename to include/surfaceflinger/ISurface.h
index c7f181c..472f759 100644
--- a/include/ui/ISurface.h
+++ b/include/surfaceflinger/ISurface.h
@@ -14,15 +14,17 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_ISURFACE_H
-#define ANDROID_ISURFACE_H
+#ifndef ANDROID_SF_ISURFACE_H
+#define ANDROID_SF_ISURFACE_H
 
 #include <stdint.h>
 #include <sys/types.h>
 
 #include <utils/Errors.h>
-#include <binder/IInterface.h>
 #include <utils/RefBase.h>
+
+#include <binder/IInterface.h>
+
 #include <ui/PixelFormat.h>
 
 #include <hardware/hardware.h>
@@ -107,4 +109,4 @@
 
 }; // namespace android
 
-#endif // ANDROID_ISURFACE_H
+#endif // ANDROID_SF_ISURFACE_H
diff --git a/include/ui/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h
similarity index 89%
rename from include/ui/ISurfaceComposer.h
rename to include/surfaceflinger/ISurfaceComposer.h
index 25d954c..d1e7785 100644
--- a/include/ui/ISurfaceComposer.h
+++ b/include/surfaceflinger/ISurfaceComposer.h
@@ -14,25 +14,24 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_ISURFACE_COMPOSER_H
-#define ANDROID_ISURFACE_COMPOSER_H
+#ifndef ANDROID_SF_ISURFACE_COMPOSER_H
+#define ANDROID_SF_ISURFACE_COMPOSER_H
 
 #include <stdint.h>
 #include <sys/types.h>
 
 #include <utils/RefBase.h>
 #include <utils/Errors.h>
+
 #include <binder/IInterface.h>
 
 #include <ui/PixelFormat.h>
-#include <ui/ISurfaceFlingerClient.h>
+
+#include <surfaceflinger/ISurfaceFlingerClient.h>
 
 namespace android {
-
 // ----------------------------------------------------------------------------
 
-class DisplayInfo;
-
 class ISurfaceComposer : public IInterface
 {
 public:
@@ -92,19 +91,19 @@
     /* retrieve the control block */
     virtual sp<IMemoryHeap> getCblk() const = 0;
 
-    /* open/close transactions. recquires ACCESS_SURFACE_FLINGER permission */
+    /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */
     virtual void openGlobalTransaction() = 0;
     virtual void closeGlobalTransaction() = 0;
 
-    /* [un]freeze display. recquires ACCESS_SURFACE_FLINGER permission */
+    /* [un]freeze display. requires ACCESS_SURFACE_FLINGER permission */
     virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags) = 0;
     virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags) = 0;
 
-    /* Set display orientation. recquires ACCESS_SURFACE_FLINGER permission */
+    /* Set display orientation. requires ACCESS_SURFACE_FLINGER permission */
     virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags) = 0;
 
     /* signal that we're done booting.
-     * recquires ACCESS_SURFACE_FLINGER permission
+     * Requires ACCESS_SURFACE_FLINGER permission
      */
     virtual void bootFinished() = 0;
 
@@ -143,4 +142,4 @@
 
 }; // namespace android
 
-#endif // ANDROID_ISURFACE_COMPOSER_H
+#endif // ANDROID_SF_ISURFACE_COMPOSER_H
diff --git a/include/ui/ISurfaceFlingerClient.h b/include/surfaceflinger/ISurfaceFlingerClient.h
similarity index 92%
rename from include/ui/ISurfaceFlingerClient.h
rename to include/surfaceflinger/ISurfaceFlingerClient.h
index 5d231e6d..1fba162 100644
--- a/include/ui/ISurfaceFlingerClient.h
+++ b/include/surfaceflinger/ISurfaceFlingerClient.h
@@ -14,28 +14,26 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_ISURFACE_FLINGER_CLIENT_H
-#define ANDROID_ISURFACE_FLINGER_CLIENT_H
+#ifndef ANDROID_SF_ISURFACE_FLINGER_CLIENT_H
+#define ANDROID_SF_ISURFACE_FLINGER_CLIENT_H
 
 #include <stdint.h>
 #include <sys/types.h>
 
 #include <utils/Errors.h>
-#include <binder/IInterface.h>
 #include <utils/RefBase.h>
 
-#include <ui/ISurface.h>
+#include <binder/IInterface.h>
 
 #include <ui/PixelFormat.h>
   
+#include <surfaceflinger/ISurface.h>
+
 namespace android {
 
 // ----------------------------------------------------------------------------
 
-class Rect;
-class Point;
-class IMemory;
-class ISurface;
+class IMemoryHeap;
 
 typedef int32_t    ClientID;
 typedef int32_t    DisplayID;
@@ -89,4 +87,4 @@
 
 }; // namespace android
 
-#endif // ANDROID_ISURFACE_FLINGER_CLIENT_H
+#endif // ANDROID_SF_ISURFACE_FLINGER_CLIENT_H
diff --git a/include/ui/Surface.h b/include/surfaceflinger/Surface.h
similarity index 97%
rename from include/ui/Surface.h
rename to include/surfaceflinger/Surface.h
index 008c297..9808832 100644
--- a/include/ui/Surface.h
+++ b/include/surfaceflinger/Surface.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_UI_SURFACE_H
-#define ANDROID_UI_SURFACE_H
+#ifndef ANDROID_SF_SURFACE_H
+#define ANDROID_SF_SURFACE_H
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -23,13 +23,13 @@
 #include <utils/RefBase.h>
 #include <utils/threads.h>
 
-#include <ui/ISurface.h>
 #include <ui/PixelFormat.h>
 #include <ui/Region.h>
-#include <ui/ISurfaceFlingerClient.h>
-
 #include <ui/egl/android_natives.h>
 
+#include <surfaceflinger/ISurface.h>
+#include <surfaceflinger/ISurfaceFlingerClient.h>
+
 namespace android {
 
 // ---------------------------------------------------------------------------
@@ -250,5 +250,5 @@
 
 }; // namespace android
 
-#endif // ANDROID_UI_SURFACE_H
+#endif // ANDROID_SF_SURFACE_H
 
diff --git a/include/ui/SurfaceComposerClient.h b/include/surfaceflinger/SurfaceComposerClient.h
similarity index 95%
rename from include/ui/SurfaceComposerClient.h
rename to include/surfaceflinger/SurfaceComposerClient.h
index 777b878..49e83c0 100644
--- a/include/ui/SurfaceComposerClient.h
+++ b/include/surfaceflinger/SurfaceComposerClient.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_SURFACE_COMPOSER_CLIENT_H
-#define ANDROID_SURFACE_COMPOSER_CLIENT_H
+#ifndef ANDROID_SF_SURFACE_COMPOSER_CLIENT_H
+#define ANDROID_SF_SURFACE_COMPOSER_CLIENT_H
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -27,17 +27,18 @@
 #include <utils/threads.h>
 
 #include <ui/PixelFormat.h>
-#include <ui/ISurfaceComposer.h>
 #include <ui/Region.h>
-#include <ui/Surface.h>
+
+#include <surfaceflinger/Surface.h>
 
 namespace android {
 
 // ---------------------------------------------------------------------------
 
 class Region;
-class SurfaceFlingerSynchro;
 class SharedClient;
+class ISurfaceComposer;
+class DisplayInfo;
 
 class SurfaceComposerClient : virtual public RefBase
 {
@@ -158,5 +159,5 @@
 
 }; // namespace android
 
-#endif // ANDROID_SURFACE_COMPOSER_CLIENT_H
+#endif // ANDROID_SF_SURFACE_COMPOSER_CLIENT_H
 
diff --git a/include/utils/AndroidUnicode.h b/include/utils/AndroidUnicode.h
deleted file mode 100644
index 563fcd0..0000000
--- a/include/utils/AndroidUnicode.h
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT 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_UNICODE_H
-#define ANDROID_UNICODE_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#define REPLACEMENT_CHAR (0xFFFD)
-
-// this part of code is copied from umachine.h under ICU
-/**
- * Define UChar32 as a type for single Unicode code points.
- * UChar32 is a signed 32-bit integer (same as int32_t).
- *
- * The Unicode code point range is 0..0x10ffff.
- * All other values (negative or >=0x110000) are illegal as Unicode code points.
- * They may be used as sentinel values to indicate "done", "error"
- * or similar non-code point conditions.
- *
- * @stable ICU 2.4
- */
-typedef int32_t UChar32;
-
-namespace android {
-
-    class Encoding;
-    /**
-     * \class Unicode
-     *
-     * Helper class for getting properties of Unicode characters. Characters
-     * can have one of the types listed in CharType and each character can have the
-     * directionality of Direction.
-     */
-    class Unicode
-    {
-    public:
-        /**
-         * Directions specified in the Unicode standard. These directions map directly
-         * to java.lang.Character.
-         */
-        enum Direction {
-            DIRECTIONALITY_UNDEFINED = -1,
-            DIRECTIONALITY_LEFT_TO_RIGHT,
-            DIRECTIONALITY_RIGHT_TO_LEFT,
-            DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC,
-            DIRECTIONALITY_EUROPEAN_NUMBER,
-            DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR,
-            DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR,
-            DIRECTIONALITY_ARABIC_NUMBER,
-            DIRECTIONALITY_COMMON_NUMBER_SEPARATOR,
-            DIRECTIONALITY_NONSPACING_MARK,
-            DIRECTIONALITY_BOUNDARY_NEUTRAL,
-            DIRECTIONALITY_PARAGRAPH_SEPARATOR,
-            DIRECTIONALITY_SEGMENT_SEPARATOR,
-            DIRECTIONALITY_WHITESPACE,
-            DIRECTIONALITY_OTHER_NEUTRALS,
-            DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING,
-            DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE,
-            DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING,
-            DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE,
-            DIRECTIONALITY_POP_DIRECTIONAL_FORMAT
-        };
-
-        /**
-         * Character types as specified in the Unicode standard. These map directly to
-         * java.lang.Character.
-         */
-        enum CharType {
-            CHARTYPE_UNASSIGNED = 0,
-            CHARTYPE_UPPERCASE_LETTER,
-            CHARTYPE_LOWERCASE_LETTER,
-            CHARTYPE_TITLECASE_LETTER,
-            CHARTYPE_MODIFIER_LETTER,
-            CHARTYPE_OTHER_LETTER,
-            CHARTYPE_NON_SPACING_MARK,
-            CHARTYPE_ENCLOSING_MARK,
-            CHARTYPE_COMBINING_SPACING_MARK,
-            CHARTYPE_DECIMAL_DIGIT_NUMBER,
-            CHARTYPE_LETTER_NUMBER,
-            CHARTYPE_OTHER_NUMBER,
-            CHARTYPE_SPACE_SEPARATOR,
-            CHARTYPE_LINE_SEPARATOR,
-            CHARTYPE_PARAGRAPH_SEPARATOR,
-            CHARTYPE_CONTROL,
-            CHARTYPE_FORMAT,
-            CHARTYPE_MISSING_VALUE_FOR_JAVA,    /* This is the mysterious missing 17 value from the java constants */
-            CHARTYPE_PRIVATE_USE,
-            CHARTYPE_SURROGATE,
-            CHARTYPE_DASH_PUNCTUATION,
-            CHARTYPE_START_PUNCTUATION,
-            CHARTYPE_END_PUNCTUATION,
-            CHARTYPE_CONNECTOR_PUNCTUATION,
-            CHARTYPE_OTHER_PUNCTUATION,
-            CHARTYPE_MATH_SYMBOL,
-            CHARTYPE_CURRENCY_SYMBOL,
-            CHARTYPE_MODIFIER_SYMBOL,
-            CHARTYPE_OTHER_SYMBOL,
-            CHARTYPE_INITIAL_QUOTE_PUNCTUATION,
-            CHARTYPE_FINAL_QUOTE_PUNCTUATION
-        };
-
-        /**
-         * Decomposition types as described by the unicode standard. These values map to
-         * the same values in uchar.h in ICU.
-         */
-        enum DecompositionType {
-            DECOMPOSITION_NONE = 0,
-            DECOMPOSITION_CANONICAL,
-            DECOMPOSITION_COMPAT,
-            DECOMPOSITION_CIRCLE,
-            DECOMPOSITION_FINAL,
-            DECOMPOSITION_FONT,
-            DECOMPOSITION_FRACTION,
-            DECOMPOSITION_INITIAL,
-            DECOMPOSITION_ISOLATED,
-            DECOMPOSITION_MEDIAL,
-            DECOMPOSITION_NARROW,
-            DECOMPOSITION_NOBREAK,
-            DECOMPOSITION_SMALL,
-            DECOMPOSITION_SQUARE,
-            DECOMPOSITION_SUB,
-            DECOMPOSITION_SUPER,
-            DECOMPOSITION_VERTICAL,
-            DECOMPOSITION_WIDE
-        };
-
-        /**
-         * Returns the packed data for java calls
-         * @param c The unicode character.
-         * @return The packed data for the character.
-         *
-         * Copied from java.lang.Character implementation:
-         * 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
-         * F E D C B A 9 8 7 6 5 4 3 2 1 0 F E D C B A 9 8 7 6 5 4 3 2 1 0
-         * 
-         *                              31 types                 ---------
-         *                   18 directionalities       ---------
-         *                   2 mirroreds             -
-         *                               -----------      56  toupper diffs
-         *                   -----------                  48  tolower diffs
-         *               ---                              4 totitlecase diffs
-         * -------------                                 84 numeric values
-         *     ---------                                 24 mirror char diffs
-         */
-        static uint32_t getPackedData(UChar32 c);
-        
-        /**
-         * Get the Character type.
-         * @param c The unicode character.
-         * @return The character's type or CHARTYPE_UNASSIGNED if the character is invalid
-         *         or has an unassigned class.
-         */
-        static CharType getType(UChar32 c);    
-
-        /**
-         * Get the Character's decomposition type.
-         * @param c The unicode character.
-         * @return The character's decomposition type or DECOMPOSITION_NONE is there 
-         *         is no decomposition.
-         */
-        static DecompositionType getDecompositionType(UChar32 c);
-        
-        /**
-         * Returns the digit value of a character or -1 if the character
-         * is not within the specified radix.
-         *
-         * The digit value is computed for integer characters and letters
-         * within the given radix. This function does not handle Roman Numerals,
-         * fractions, or any other characters that may represent numbers.
-         * 
-         * @param c The unicode character
-         * @param radix The intended radix.
-         * @return The digit value or -1 if there is no digit value or if the value is outside the radix.
-         */
-        static int getDigitValue(UChar32 c, int radix = 10);
-
-        /**
-         * Return the numeric value of a character
-         *
-         * @param c The unicode character.
-         * @return The numeric value of the character. -1 if the character has no numeric value, 
-         *         -2 if the character has a numeric value that is not representable by an integer.
-         */
-        static int getNumericValue(UChar32 c);
-
-        /**
-         * Convert the character to lowercase
-         * @param c The unicode character.
-         * @return The lowercase character equivalent of c. If c does not have a lowercase equivalent,
-         *         the original character is returned.
-         */
-        static UChar32 toLower(UChar32 c);
-            
-        /**
-         * Convert the character to uppercase
-         * @param c The unicode character.
-         * @return The uppercase character equivalent of c. If c does not have an uppercase equivalent,
-         *         the original character is returned.
-         */
-        static UChar32 toUpper(UChar32 c);
-    
-        /**
-         * Get the directionality of the character.
-         * @param c The unicode character.
-         * @return The direction of the character or DIRECTIONALITY_UNDEFINED.
-         */
-        static Direction getDirectionality(UChar32 c);
-            
-        /**
-         * Check if the character is a mirrored character. This means that the character
-         * has an equivalent character that is the mirror image of itself.
-         * @param c The unicode character.
-         * @return True iff c has a mirror equivalent.
-         */
-        static bool isMirrored(UChar32 c);
-         
-        /**
-         * Return the mirror of the given character.
-         * @param c The unicode character.
-         * @return The mirror equivalent of c. If c does not have a mirror equivalent,
-         *         the original character is returned.
-         * @see isMirrored
-         */
-        static UChar32 toMirror(UChar32 c);
-        
-        /**
-         * Convert the character to title case.
-         * @param c The unicode character.
-         * @return The titlecase equivalent of c. If c does not have a titlecase equivalent,
-         *         the original character is returned.
-         */
-        static UChar32 toTitle(UChar32 c);
-
-   };
-
-}
-
-#endif
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index 6090f600..13ea27e 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -939,10 +939,23 @@
         SCREENLONG_YES = 0x20,
     };
     
+    enum {
+        // uiMode bits for the mode type.
+        MASK_UI_MODE_TYPE = 0x0f,
+        UI_MODE_TYPE_NORMAL = 0x00,
+        UI_MODE_TYPE_CAR = 0x01,
+
+        // uiMode bits for the night switch.
+        MASK_UI_MODE_NIGHT = 0x30,
+        UI_MODE_NIGHT_ANY = 0x00,
+        UI_MODE_NIGHT_NO = 0x10,
+        UI_MODE_NIGHT_YES = 0x20,
+    };
+
     union {
         struct {
             uint8_t screenLayout;
-            uint8_t screenConfigPad0;
+            uint8_t uiMode;
             uint8_t screenConfigPad1;
             uint8_t screenConfigPad2;
         };
@@ -996,6 +1009,8 @@
         diff = (int32_t)(version - o.version);
         if (diff != 0) return diff;
         diff = (int32_t)(screenLayout - o.screenLayout);
+        if (diff != 0) return diff;
+        diff = (int32_t)(uiMode - o.uiMode);
         return (int)diff;
     }
     
@@ -1014,7 +1029,8 @@
         CONFIG_DENSITY = 0x0100,
         CONFIG_SCREEN_SIZE = 0x0200,
         CONFIG_VERSION = 0x0400,
-        CONFIG_SCREEN_LAYOUT = 0x0800
+        CONFIG_SCREEN_LAYOUT = 0x0800,
+        CONFIG_UI_MODE = 0x1000
     };
     
     // Compare two configuration, returning CONFIG_* flags set for each value
@@ -1034,6 +1050,7 @@
         if (screenSize != o.screenSize) diffs |= CONFIG_SCREEN_SIZE;
         if (version != o.version) diffs |= CONFIG_VERSION;
         if (screenLayout != o.screenLayout) diffs |= CONFIG_SCREEN_LAYOUT;
+        if (uiMode != o.uiMode) diffs |= CONFIG_UI_MODE;
         return diffs;
     }
     
@@ -1078,19 +1095,28 @@
             }
         }
 
-        if (screenType || o.screenType) {
-            if (orientation != o.orientation) {
-                if (!orientation) return false;
-                if (!o.orientation) return true;
-            }
+        if (orientation != o.orientation) {
+            if (!orientation) return false;
+            if (!o.orientation) return true;
+        }
 
-            // density is never 'more specific'
-            // as the default just equals 160
-
-            if (touchscreen != o.touchscreen) {
-                if (!touchscreen) return false;
-                if (!o.touchscreen) return true;
+        if (screenConfig || o.screenConfig) {
+            if (((uiMode^o.uiMode) & MASK_UI_MODE_TYPE) != 0) {
+                if (!(uiMode & MASK_UI_MODE_TYPE)) return false;
+                if (!(o.uiMode & MASK_UI_MODE_TYPE)) return true;
             }
+            if (((uiMode^o.uiMode) & MASK_UI_MODE_NIGHT) != 0) {
+                if (!(uiMode & MASK_UI_MODE_NIGHT)) return false;
+                if (!(o.uiMode & MASK_UI_MODE_NIGHT)) return true;
+            }
+        }
+
+        // density is never 'more specific'
+        // as the default just equals 160
+
+        if (touchscreen != o.touchscreen) {
+            if (!touchscreen) return false;
+            if (!o.touchscreen) return true;
         }
 
         if (input || o.input) {
@@ -1186,11 +1212,22 @@
                 }
             }
 
-            if (screenType || o.screenType) {
-                if ((orientation != o.orientation) && requested->orientation) {
-                    return (orientation);
-                }
+            if ((orientation != o.orientation) && requested->orientation) {
+                return (orientation);
+            }
 
+            if (screenConfig || o.screenConfig) {
+                if (((uiMode^o.uiMode) & MASK_UI_MODE_TYPE) != 0
+                        && (requested->uiMode & MASK_UI_MODE_TYPE)) {
+                    return (uiMode & MASK_UI_MODE_TYPE);
+                }
+                if (((uiMode^o.uiMode) & MASK_UI_MODE_NIGHT) != 0
+                        && (requested->uiMode & MASK_UI_MODE_NIGHT)) {
+                    return (uiMode & MASK_UI_MODE_NIGHT);
+                }
+            }
+
+            if (screenType || o.screenType) {
                 if (density != o.density) {
                     // density is tough.  Any density is potentially useful
                     // because the system will scale it.  Scaling down
@@ -1340,6 +1377,20 @@
                     && screenLong != setScreenLong) {
                 return false;
             }
+
+            const int uiModeType = uiMode&MASK_UI_MODE_TYPE;
+            const int setUiModeType = settings.uiMode&MASK_UI_MODE_TYPE;
+            if (setUiModeType != 0 && uiModeType != 0
+                    && uiModeType != setUiModeType) {
+                return false;
+            }
+
+            const int uiModeNight = uiMode&MASK_UI_MODE_NIGHT;
+            const int setUiModeNight = settings.uiMode&MASK_UI_MODE_NIGHT;
+            if (setUiModeNight != 0 && uiModeNight != 0
+                    && uiModeNight != setUiModeNight) {
+                return false;
+            }
         }
         if (screenType != 0) {
             if (settings.orientation != 0 && orientation != 0
@@ -1420,13 +1471,15 @@
     String8 toString() const {
         char buf[200];
         sprintf(buf, "imsi=%d/%d lang=%c%c reg=%c%c orient=%d touch=%d dens=%d "
-                "kbd=%d nav=%d input=%d scrnW=%d scrnH=%d sz=%d long=%d vers=%d.%d",
+                "kbd=%d nav=%d input=%d scrnW=%d scrnH=%d sz=%d long=%d "
+                "ui=%d night=%d vers=%d.%d",
                 mcc, mnc,
                 language[0] ? language[0] : '-', language[1] ? language[1] : '-',
                 country[0] ? country[0] : '-', country[1] ? country[1] : '-',
                 orientation, touchscreen, density, keyboard, navigation, inputFlags,
                 screenWidth, screenHeight,
                 screenLayout&MASK_SCREENSIZE, screenLayout&MASK_SCREENLONG,
+                uiMode&MASK_UI_MODE_TYPE, uiMode&MASK_UI_MODE_NIGHT,
                 sdkVersion, minorVersion);
         return String8(buf);
     }
diff --git a/keystore/tests/src/android/security/SystemKeyStoreTest.java b/keystore/tests/src/android/security/SystemKeyStoreTest.java
index a9e2687..a4d744b 100644
--- a/keystore/tests/src/android/security/SystemKeyStoreTest.java
+++ b/keystore/tests/src/android/security/SystemKeyStoreTest.java
@@ -60,7 +60,7 @@
 
     public void testBasicAccess() throws Exception {
         try {
-            byte[] newKey = mSysKeyStore.generateNewKey(128, "Blowfish", keyName);
+            byte[] newKey = mSysKeyStore.generateNewKey(128, "AES", keyName);
             assertNotNull(newKey);
             byte[] recKey = mSysKeyStore.retrieveKey(keyName);
             assertEquals(newKey.length, recKey.length);
@@ -75,8 +75,9 @@
             assertNotNull(newKeyStr);
             String recKeyStr = mSysKeyStore.retrieveKeyHexString(keyName2);
             assertEquals(newKeyStr, recKeyStr);
+
             mSysKeyStore.deleteKey(keyName2);
-            String nullKey2 = mSysKeyStore.retrieveKeyHexString(keyName);
+            String nullKey2 = mSysKeyStore.retrieveKeyHexString(keyName2);
             assertNull(nullKey2);
         } catch (Exception e) {
             fail();
diff --git a/libs/camera/Android.mk b/libs/camera/Android.mk
new file mode 100644
index 0000000..03ff229
--- /dev/null
+++ b/libs/camera/Android.mk
@@ -0,0 +1,25 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	Camera.cpp \
+	CameraParameters.cpp \
+	ICamera.cpp \
+	ICameraClient.cpp \
+	ICameraService.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+	libutils \
+	libbinder \
+	libhardware \
+	libsurfaceflinger_client \
+	libui
+
+LOCAL_MODULE:= libcamera_client
+
+ifeq ($(TARGET_SIMULATOR),true)
+    LOCAL_LDLIBS += -lpthread
+endif
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/ui/Camera.cpp b/libs/camera/Camera.cpp
similarity index 98%
rename from libs/ui/Camera.cpp
rename to libs/camera/Camera.cpp
index 09a36f1..8620e71 100644
--- a/libs/ui/Camera.cpp
+++ b/libs/camera/Camera.cpp
@@ -19,12 +19,15 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "Camera"
 #include <utils/Log.h>
-#include <binder/IServiceManager.h>
 #include <utils/threads.h>
+
+#include <binder/IServiceManager.h>
 #include <binder/IMemory.h>
-#include <ui/Surface.h>
-#include <ui/Camera.h>
-#include <ui/ICameraService.h>
+
+#include <camera/Camera.h>
+#include <camera/ICameraService.h>
+
+#include <surfaceflinger/Surface.h>
 
 namespace android {
 
@@ -281,7 +284,7 @@
 // send command to camera driver
 status_t Camera::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2)
 {
-    LOGD("sendCommand");
+    LOGV("sendCommand");
     sp <ICamera> c = mCamera;
     if (c == 0) return NO_INIT;
     return c->sendCommand(cmd, arg1, arg2);
diff --git a/libs/ui/CameraParameters.cpp b/libs/camera/CameraParameters.cpp
similarity index 97%
rename from libs/ui/CameraParameters.cpp
rename to libs/camera/CameraParameters.cpp
index c4958a0..1bf1759 100644
--- a/libs/ui/CameraParameters.cpp
+++ b/libs/camera/CameraParameters.cpp
@@ -20,7 +20,7 @@
 
 #include <string.h>
 #include <stdlib.h>
-#include <ui/CameraParameters.h>
+#include <camera/CameraParameters.h>
 
 namespace android {
 // Parameter keys to communicate between camera application and driver.
@@ -59,6 +59,8 @@
 const char CameraParameters::KEY_FOCAL_LENGTH[] = "focal-length";
 const char CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE[] = "horizontal-view-angle";
 const char CameraParameters::KEY_VERTICAL_VIEW_ANGLE[] = "vertical-view-angle";
+const char CameraParameters::KEY_EXPOSURE_COMPENSATION[] = "exposure-compensation";
+const char CameraParameters::KEY_SUPPORTED_EXPOSURE_COMPENSATION[] = "exposure-compensation-values";
 
 // Values for white balance settings.
 const char CameraParameters::WHITE_BALANCE_AUTO[] = "auto";
diff --git a/libs/ui/ICamera.cpp b/libs/camera/ICamera.cpp
similarity index 99%
rename from libs/ui/ICamera.cpp
rename to libs/camera/ICamera.cpp
index e1b3ec7..724bd20 100644
--- a/libs/ui/ICamera.cpp
+++ b/libs/camera/ICamera.cpp
@@ -21,7 +21,7 @@
 #include <stdint.h>
 #include <sys/types.h>
 #include <binder/Parcel.h>
-#include <ui/ICamera.h>
+#include <camera/ICamera.h>
 
 namespace android {
 
@@ -344,7 +344,7 @@
             return NO_ERROR;
          } break;
         case SEND_COMMAND: {
-            LOGD("SEND_COMMAND");
+            LOGV("SEND_COMMAND");
             CHECK_INTERFACE(ICamera, data, reply);
             int command = data.readInt32();
             int arg1 = data.readInt32();
diff --git a/libs/ui/ICameraClient.cpp b/libs/camera/ICameraClient.cpp
similarity index 98%
rename from libs/ui/ICameraClient.cpp
rename to libs/camera/ICameraClient.cpp
index 42b4da4..cb3bd0c 100644
--- a/libs/ui/ICameraClient.cpp
+++ b/libs/camera/ICameraClient.cpp
@@ -20,7 +20,7 @@
 #include <utils/Log.h>
 #include <stdint.h>
 #include <sys/types.h>
-#include <ui/ICameraClient.h>
+#include <camera/ICameraClient.h>
 
 namespace android {
 
diff --git a/libs/ui/ICameraService.cpp b/libs/camera/ICameraService.cpp
similarity index 98%
rename from libs/ui/ICameraService.cpp
rename to libs/camera/ICameraService.cpp
index 84986c6..46b5478 100644
--- a/libs/ui/ICameraService.cpp
+++ b/libs/camera/ICameraService.cpp
@@ -22,7 +22,7 @@
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 
-#include <ui/ICameraService.h>
+#include <camera/ICameraService.h>
 
 namespace android {
 
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index 6662333..02667d8 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -55,7 +55,8 @@
 void rsDeviceDestroy(RsDevice);
 void rsDeviceSetConfig(RsDevice, RsDeviceParam, int32_t value);
 
-RsContext rsContextCreate(RsDevice, uint32_t version, bool useDepth);
+RsContext rsContextCreate(RsDevice, uint32_t version);
+RsContext rsContextCreateGL(RsDevice, uint32_t version, bool useDepth);
 void rsContextDestroy(RsContext);
 void rsObjDestroyOOB(RsContext, void *);
 
diff --git a/libs/rs/java/Film/src/com/android/film/FilmRS.java b/libs/rs/java/Film/src/com/android/film/FilmRS.java
index b80e619..7d04502 100644
--- a/libs/rs/java/Film/src/com/android/film/FilmRS.java
+++ b/libs/rs/java/Film/src/com/android/film/FilmRS.java
@@ -40,7 +40,7 @@
     public FilmRS() {
     }
 
-    public void init(RenderScript rs, Resources res, int width, int height) {
+    public void init(RenderScriptGL rs, Resources res, int width, int height) {
         mRS = rs;
         mRes = res;
         initRS();
@@ -65,7 +65,7 @@
 
 
     private Resources mRes;
-    private RenderScript mRS;
+    private RenderScriptGL mRS;
     private Script mScriptStrip;
     private Script mScriptImage;
     private Sampler mSampler;
diff --git a/libs/rs/java/Film/src/com/android/film/FilmView.java b/libs/rs/java/Film/src/com/android/film/FilmView.java
index 4a201fd..5bc2811 100644
--- a/libs/rs/java/Film/src/com/android/film/FilmView.java
+++ b/libs/rs/java/Film/src/com/android/film/FilmView.java
@@ -22,6 +22,7 @@
 
 import android.renderscript.RSSurfaceView;
 import android.renderscript.RenderScript;
+import android.renderscript.RenderScriptGL;
 
 import android.content.Context;
 import android.content.res.Resources;
@@ -45,7 +46,7 @@
         //setFocusable(true);
     }
 
-    private RenderScript mRS;
+    private RenderScriptGL mRS;
     private FilmRS mRender;
 
 
diff --git a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
index 71f95a7..9356579 100644
--- a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
+++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
@@ -37,7 +37,7 @@
     public FountainRS() {
     }
 
-    public void init(RenderScript rs, Resources res, int width, int height) {
+    public void init(RenderScriptGL rs, Resources res, int width, int height) {
         mRS = rs;
         mRes = res;
         initRS();
@@ -65,7 +65,7 @@
 
     private Resources mRes;
 
-    private RenderScript mRS;
+    private RenderScriptGL mRS;
     private Allocation mIntAlloc;
     private SimpleMesh mSM;
     private SomeData mSD;
diff --git a/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java b/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java
index fcb93f4..dfd6a49 100644
--- a/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java
+++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java
@@ -22,6 +22,7 @@
 
 import android.renderscript.RSSurfaceView;
 import android.renderscript.RenderScript;
+import android.renderscript.RenderScriptGL;
 
 import android.content.Context;
 import android.content.res.Resources;
@@ -45,7 +46,7 @@
         //setFocusable(true);
     }
 
-    private RenderScript mRS;
+    private RenderScriptGL mRS;
     private FountainRS mRender;
 
     public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
diff --git a/libs/rs/java/ImageProcessing/res/raw/threshold.rs b/libs/rs/java/ImageProcessing/res/raw/threshold.rs
index dec5587..888f0cd 100644
--- a/libs/rs/java/ImageProcessing/res/raw/threshold.rs
+++ b/libs/rs/java/ImageProcessing/res/raw/threshold.rs
@@ -1,3 +1,29 @@
+/*
+// block of defines matching what RS will insert at runtime.
+struct Params_s{
+    int inHeight;
+    int inWidth;
+    int outHeight;
+    int outWidth;
+    float threshold;
+};
+struct Params_s * Params;
+struct InPixel_s{
+    char a;
+    char b;
+    char g;
+    char r;
+};
+struct InPixel_s * InPixel;
+struct OutPixel_s{
+    char a;
+    char b;
+    char g;
+    char r;
+};
+struct OutPixel_s * OutPixel;
+*/
+
 struct color_s {
     char b;
     char g;
@@ -5,40 +31,32 @@
     char a;
 };
 
-void filter(struct color_s *in, struct color_s *out, struct vec3_s *luminanceVector) {
-    struct vec3_s pixel;
-    pixel.x = (in->r & 0xFF) / 255.0f;
-    pixel.y = (in->g & 0xFF) / 255.0f;
-    pixel.z = (in->b & 0xFF) / 255.0f;
-
-    float luminance = vec3Dot(luminanceVector, &pixel);
-    luminance = maxf(0.0f, luminance - Params->threshold);
-    vec3Scale(&pixel, signf(luminance));
-
-    out->a = in->a;
-    out->r = pixel.x * 255.0f;
-    out->g = pixel.y * 255.0f;
-    out->b = pixel.z * 255.0f;
-}
-
 void main() {
+    int t = uptimeMillis();
+
     struct color_s *in = (struct color_s *) InPixel;
     struct color_s *out = (struct color_s *) OutPixel;
-    
-    struct vec3_s luminanceVector;
-    luminanceVector.x = 0.2125f;
-    luminanceVector.y = 0.7154f;
-    luminanceVector.z = 0.0721f;
 
     int count = Params->inWidth * Params->inHeight;
     int i;
+    float threshold = (Params->threshold * 255.f);
 
     for (i = 0; i < count; i++) {
-        filter(in, out, &luminanceVector);
+        float luminance = 0.2125f * in->r +
+                          0.7154f * in->g +
+                          0.0721f * in->b;
+        if (luminance > threshold) {
+            *out = *in;
+        } else {
+            *((int *)out) = *((int *)in) & 0xff000000;
+        }
 
         in++;
         out++;
     }
 
+    t= uptimeMillis() - t;
+    debugI32("Filter time", t);
+
     sendToClient(&count, 1, 4, 0);
 }
diff --git a/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
index 0ca00b3..9ce53d8 100644
--- a/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
+++ b/libs/rs/java/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
@@ -31,11 +31,13 @@
 import android.view.SurfaceHolder;
 import android.widget.ImageView;
 import android.widget.SeekBar;
+import java.lang.Math;
 
 public class ImageProcessingActivity extends Activity implements SurfaceHolder.Callback {
     private Bitmap mBitmap;
     private Params mParams;
     private Script.Invokable mInvokable;
+    private int[] mInData;
     private int[] mOutData;
 
     @SuppressWarnings({"FieldCanBeLocal"})
@@ -87,6 +89,31 @@
         }
     }
 
+    private void javaFilter() {
+        long t = java.lang.System.currentTimeMillis();
+        int count = mParams.inWidth * mParams.inHeight;
+        float threshold = mParams.threshold * 255.f;
+
+        for (int i = 0; i < count; i++) {
+            final float r = (float)((mInData[i] >> 0) & 0xff);
+            final float g = (float)((mInData[i] >> 8) & 0xff);
+            final float b = (float)((mInData[i] >> 16) & 0xff);
+
+            final float luminance = 0.2125f * r +
+                              0.7154f * g +
+                              0.0721f * b;
+            if (luminance > threshold) {
+                mOutData[i] = mInData[i];
+            } else {
+                mOutData[i] = mInData[i] & 0xff000000;
+            }
+        }
+
+        t = java.lang.System.currentTimeMillis() - t;
+
+        android.util.Log.v("Img", "frame time ms " + t);
+    }
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -106,7 +133,15 @@
                 if (fromUser) {
                     mParams.threshold = progress / 100.0f;
                     mParamsAllocation.data(mParams);
-                    mInvokable.execute();
+
+                    if (true) {
+                        mInvokable.execute();
+                    } else {
+                        javaFilter();
+                        mBitmap.setPixels(mOutData, 0, mParams.outWidth, 0, 0,
+                                mParams.outWidth, mParams.outHeight);
+                        mDisplayView.invalidate();
+                    }
                 }
             }
 
@@ -126,14 +161,13 @@
     }
 
     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
-        mRS.contextSetSurface(width, height, holder.getSurface());
     }
 
     public void surfaceDestroyed(SurfaceHolder holder) {
     }
 
     private Script.Invokable createScript() {
-        mRS = new RenderScript(false, false);
+        mRS = RenderScript.create();
         mRS.mMessageCallback = new FilterCallback();
 
         mParamsType = Type.createFromClass(mRS, Params.class, 1, "Parameters");
@@ -150,9 +184,9 @@
                 Element.createUser(mRS, Element.DataType.SIGNED_32),
                 pixelCount);
 
-        final int[] data = new int[pixelCount];
-        mBitmap.getPixels(data, 0, mParams.inWidth, 0, 0, mParams.inWidth, mParams.inHeight);
-        mInPixelsAllocation.data(data);
+        mInData = new int[pixelCount];
+        mBitmap.getPixels(mInData, 0, mParams.inWidth, 0, 0, mParams.inWidth, mParams.inHeight);
+        mInPixelsAllocation.data(mInData);
 
         mOutData = new int[pixelCount];
         mOutPixelsAllocation.data(mOutData);
@@ -164,7 +198,7 @@
         sb.setType(true, 2);
         Script.Invokable invokable = sb.addInvokable("main");
         sb.setScript(getResources(), R.raw.threshold);
-        sb.setRoot(true);
+        //sb.setRoot(true);
 
         ScriptC script = sb.create();
         script.bindAllocation(mParamsAllocation, 0);
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index ac115d3..10e5285 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -29,7 +29,7 @@
 ContextSetSurface {
 	param uint32_t width
 	param uint32_t height
-	param void *sur
+	param android_native_window_t *sur
 	}
 
 ContextDump {
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 261b827..dec993a 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -19,6 +19,7 @@
 #include "rsThreadIO.h"
 #include <ui/FramebufferNativeWindow.h>
 #include <ui/EGLUtils.h>
+#include <ui/egl/android_natives.h>
 
 #include <sys/types.h>
 #include <sys/resource.h>
@@ -289,15 +290,17 @@
          LOGE("pthread_setspecific %i", status);
      }
 
-     rsc->mStateRaster.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
-     rsc->setRaster(NULL);
-     rsc->mStateVertex.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
-     rsc->setVertex(NULL);
-     rsc->mStateFragment.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
-     rsc->setFragment(NULL);
-     rsc->mStateFragmentStore.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
-     rsc->setFragmentStore(NULL);
-     rsc->mStateVertexArray.init(rsc);
+     if (rsc->mIsGraphicsContext) {
+         rsc->mStateRaster.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
+         rsc->setRaster(NULL);
+         rsc->mStateVertex.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
+         rsc->setVertex(NULL);
+         rsc->mStateFragment.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
+         rsc->setFragment(NULL);
+         rsc->mStateFragmentStore.init(rsc, rsc->mEGL.mWidth, rsc->mEGL.mHeight);
+         rsc->setFragmentStore(NULL);
+         rsc->mStateVertexArray.init(rsc);
+     }
 
      rsc->mRunning = true;
      bool mDraw = true;
@@ -307,7 +310,7 @@
          mDraw &= (rsc->mWndSurface != NULL);
 
          uint32_t targetTime = 0;
-         if (mDraw) {
+         if (mDraw && rsc->mIsGraphicsContext) {
              targetTime = rsc->runRootScript();
              mDraw = targetTime && !rsc->mPaused;
              rsc->timerSet(RS_TIMER_CLEAR_SWAP);
@@ -329,23 +332,27 @@
      }
 
      LOGV("RS Thread exiting");
-     rsc->mRaster.clear();
-     rsc->mFragment.clear();
-     rsc->mVertex.clear();
-     rsc->mFragmentStore.clear();
-     rsc->mRootScript.clear();
-     rsc->mStateRaster.deinit(rsc);
-     rsc->mStateVertex.deinit(rsc);
-     rsc->mStateFragment.deinit(rsc);
-     rsc->mStateFragmentStore.deinit(rsc);
+     if (rsc->mIsGraphicsContext) {
+         rsc->mRaster.clear();
+         rsc->mFragment.clear();
+         rsc->mVertex.clear();
+         rsc->mFragmentStore.clear();
+         rsc->mRootScript.clear();
+         rsc->mStateRaster.deinit(rsc);
+         rsc->mStateVertex.deinit(rsc);
+         rsc->mStateFragment.deinit(rsc);
+         rsc->mStateFragmentStore.deinit(rsc);
+     }
      ObjectBase::zeroAllUserRef(rsc);
 
      rsc->mObjDestroy.mNeedToEmpty = true;
      rsc->objDestroyOOBRun();
 
-     pthread_mutex_lock(&gInitMutex);
-     rsc->deinitEGL();
-     pthread_mutex_unlock(&gInitMutex);
+     if (rsc->mIsGraphicsContext) {
+         pthread_mutex_lock(&gInitMutex);
+         rsc->deinitEGL();
+         pthread_mutex_unlock(&gInitMutex);
+     }
 
      LOGV("RS Thread exited");
      return NULL;
@@ -371,7 +378,7 @@
 #endif
 }
 
-Context::Context(Device *dev, bool useDepth)
+Context::Context(Device *dev, bool isGraphics, bool useDepth)
 {
     pthread_mutex_lock(&gInitMutex);
 
@@ -383,6 +390,8 @@
     mPaused = false;
     mObjHead = NULL;
     memset(&mEGL, 0, sizeof(mEGL));
+    memset(&mGL, 0, sizeof(mGL));
+    mIsGraphicsContext = isGraphics;
 
     int status;
     pthread_attr_t threadAttr;
@@ -452,9 +461,9 @@
     objDestroyOOBDestroy();
 }
 
-void Context::setSurface(uint32_t w, uint32_t h, Surface *sur)
+void Context::setSurface(uint32_t w, uint32_t h, android_native_window_t *sur)
 {
-    LOGV("setSurface %i %i %p", w, h, sur);
+    rsAssert(mIsGraphicsContext);
 
     EGLBoolean ret;
     if (mEGL.mSurface != NULL) {
@@ -544,21 +553,25 @@
 
 void Context::pause()
 {
+    rsAssert(mIsGraphicsContext);
     mPaused = true;
 }
 
 void Context::resume()
 {
+    rsAssert(mIsGraphicsContext);
     mPaused = false;
 }
 
 void Context::setRootScript(Script *s)
 {
+    rsAssert(mIsGraphicsContext);
     mRootScript.set(s);
 }
 
 void Context::setFragmentStore(ProgramFragmentStore *pfs)
 {
+    rsAssert(mIsGraphicsContext);
     if (pfs == NULL) {
         mFragmentStore.set(mStateFragmentStore.mDefault);
     } else {
@@ -568,6 +581,7 @@
 
 void Context::setFragment(ProgramFragment *pf)
 {
+    rsAssert(mIsGraphicsContext);
     if (pf == NULL) {
         mFragment.set(mStateFragment.mDefault);
     } else {
@@ -577,6 +591,7 @@
 
 void Context::setRaster(ProgramRaster *pr)
 {
+    rsAssert(mIsGraphicsContext);
     if (pr == NULL) {
         mRaster.set(mStateRaster.mDefault);
     } else {
@@ -586,6 +601,7 @@
 
 void Context::setVertex(ProgramVertex *pv)
 {
+    rsAssert(mIsGraphicsContext);
     if (pv == NULL) {
         mVertex.set(mStateVertex.mDefault);
     } else {
@@ -841,9 +857,9 @@
     rsc->resume();
 }
 
-void rsi_ContextSetSurface(Context *rsc, uint32_t w, uint32_t h, void *sur)
+void rsi_ContextSetSurface(Context *rsc, uint32_t w, uint32_t h, android_native_window_t *sur)
 {
-    rsc->setSurface(w, h, (Surface *)sur);
+    rsc->setSurface(w, h, sur);
 }
 
 void rsi_ContextSetPriority(Context *rsc, int32_t p)
@@ -860,10 +876,19 @@
 }
 
 
-RsContext rsContextCreate(RsDevice vdev, uint32_t version, bool useDepth)
+RsContext rsContextCreate(RsDevice vdev, uint32_t version)
 {
+    LOGV("rsContextCreate %p", vdev);
     Device * dev = static_cast<Device *>(vdev);
-    Context *rsc = new Context(dev, useDepth);
+    Context *rsc = new Context(dev, false, false);
+    return rsc;
+}
+
+RsContext rsContextCreateGL(RsDevice vdev, uint32_t version, bool useDepth)
+{
+    LOGV("rsContextCreateGL %p, %i", vdev, useDepth);
+    Device * dev = static_cast<Device *>(vdev);
+    Context *rsc = new Context(dev, true, useDepth);
     return rsc;
 }
 
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index 2edd16d..03e65f1 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -19,8 +19,6 @@
 
 #include "rsUtils.h"
 
-#include <ui/Surface.h>
-
 #include "rsThreadIO.h"
 #include "rsType.h"
 #include "rsMatrix.h"
@@ -43,15 +41,17 @@
 #include "rsgApiStructs.h"
 #include "rsLocklessFifo.h"
 
+#include <ui/egl/android_natives.h>
 
 // ---------------------------------------------------------------------------
 namespace android {
+
 namespace renderscript {
 
 class Context
 {
 public:
-    Context(Device *, bool useDepth);
+    Context(Device *, bool isGraphics, bool useDepth);
     ~Context();
 
     static pthread_key_t gThreadTLSKey;
@@ -98,7 +98,7 @@
 
     void pause();
     void resume();
-    void setSurface(uint32_t w, uint32_t h, Surface *sur);
+    void setSurface(uint32_t w, uint32_t h, android_native_window_t *sur);
     void setPriority(int32_t p);
 
     void assignName(ObjectBase *obj, const char *name, uint32_t len);
@@ -201,6 +201,7 @@
     uint32_t mWidth;
     uint32_t mHeight;
     int32_t mThreadPriority;
+    bool mIsGraphicsContext;
 
     bool mRunning;
     bool mExit;
@@ -237,7 +238,7 @@
 
     static void * threadProc(void *);
 
-    Surface *mWndSurface;
+    android_native_window_t *mWndSurface;
 
     Vector<ObjectBase *> mNames;
 
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk
index b3fed58..395a937 100644
--- a/libs/surfaceflinger/Android.mk
+++ b/libs/surfaceflinger/Android.mk
@@ -39,7 +39,8 @@
 	libEGL \
 	libGLESv1_CM \
 	libbinder \
-	libui
+	libui \
+	libsurfaceflinger_client
 
 LOCAL_C_INCLUDES := \
 	$(call include-path-for, corecg graphics)
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 1870d3a..f38efab 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -27,7 +27,8 @@
 
 #include <ui/GraphicBuffer.h>
 #include <ui/PixelFormat.h>
-#include <ui/Surface.h>
+
+#include <surfaceflinger/Surface.h>
 
 #include "clz.h"
 #include "Layer.h"
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index f73ea0c..a49faf7 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -23,14 +23,15 @@
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 
-#include <private/ui/SharedBufferStack.h>
-#include <private/ui/LayerState.h>
-
 #include <utils/RefBase.h>
 
 #include <ui/Region.h>
 #include <ui/Overlay.h>
 
+#include <surfaceflinger/ISurfaceFlingerClient.h>
+#include <private/surfaceflinger/SharedBufferStack.h>
+#include <private/surfaceflinger/LayerState.h>
+
 #include <pixelflinger/pixelflinger.h>
 
 #include "Transform.h"
diff --git a/libs/surfaceflinger/LayerBlur.h b/libs/surfaceflinger/LayerBlur.h
index 2e9d7c6..5b63dec 100644
--- a/libs/surfaceflinger/LayerBlur.h
+++ b/libs/surfaceflinger/LayerBlur.h
@@ -20,8 +20,6 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <private/ui/LayerState.h>
-
 #include <ui/Region.h>
 
 #include "LayerBase.h"
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 965b7dd..2d6152e 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -39,7 +39,6 @@
 
 #include <ui/GraphicBufferAllocator.h>
 #include <ui/PixelFormat.h>
-#include <ui/DisplayInfo.h>
 
 #include <pixelflinger/pixelflinger.h>
 #include <GLES/gl.h>
@@ -350,8 +349,8 @@
     mServerCblk->connected |= 1<<dpy;
     display_cblk_t* dcblk = mServerCblk->displays + dpy;
     memset(dcblk, 0, sizeof(display_cblk_t));
-    dcblk->w            = w;
-    dcblk->h            = h;
+    dcblk->w            = plane.getWidth();
+    dcblk->h            = plane.getHeight();
     dcblk->format       = f;
     dcblk->orientation  = ISurfaceComposer::eOrientationDefault;
     dcblk->xdpi         = hw.getDpiX();
@@ -621,14 +620,8 @@
             const DisplayHardware& hw(plane.displayHardware());
             volatile display_cblk_t* dcblk = mServerCblk->displays + dpy;
             dcblk->orientation = orientation;
-            if (orientation & eOrientationSwapMask) {
-                // 90 or 270 degrees orientation
-                dcblk->w = hw.getHeight();
-                dcblk->h = hw.getWidth();
-            } else {
-                dcblk->w = hw.getWidth();
-                dcblk->h = hw.getHeight();
-            }
+            dcblk->w = plane.getWidth();
+            dcblk->h = plane.getHeight();
 
             mVisibleRegionsDirty = true;
             mDirtyRegion.set(hw.bounds());
@@ -1795,13 +1788,47 @@
     return mHw ? true : false;
 }
 
-void GraphicPlane::setDisplayHardware(DisplayHardware *hw) {
-    mHw = hw;
+int GraphicPlane::getWidth() const {
+    return mWidth;
 }
 
-void GraphicPlane::setTransform(const Transform& tr) {
-    mTransform = tr;
-    mGlobalTransform = mOrientationTransform * mTransform;
+int GraphicPlane::getHeight() const {
+    return mHeight;
+}
+
+void GraphicPlane::setDisplayHardware(DisplayHardware *hw)
+{
+    mHw = hw;
+
+    // initialize the display orientation transform.
+    // it's a constant that should come from the display driver.
+    int displayOrientation = ISurfaceComposer::eOrientationDefault;
+    char property[PROPERTY_VALUE_MAX];
+    if (property_get("ro.sf.hwrotation", property, NULL) > 0) {
+        //displayOrientation
+        switch (atoi(property)) {
+        case 90:
+            displayOrientation = ISurfaceComposer::eOrientation90;
+            break;
+        case 270:
+            displayOrientation = ISurfaceComposer::eOrientation270;
+            break;
+        }
+    }
+
+    const float w = hw->getWidth();
+    const float h = hw->getHeight();
+    GraphicPlane::orientationToTransfrom(displayOrientation, w, h,
+            &mDisplayTransform);
+    if (displayOrientation & ISurfaceComposer::eOrientationSwapMask) {
+        mDisplayWidth = h;
+        mDisplayHeight = w;
+    } else {
+        mDisplayWidth = w;
+        mDisplayHeight = h;
+    }
+
+    setOrientation(ISurfaceComposer::eOrientationDefault);
 }
 
 status_t GraphicPlane::orientationToTransfrom(
@@ -1810,8 +1837,9 @@
     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;
+        // make sure the default orientation is optimal
+        tr->reset();
+        return NO_ERROR;
     case ISurfaceComposer::eOrientation90:
         a=0; b=-1; c=1; d=0; x=w; y=0;
         break;
@@ -1831,20 +1859,16 @@
 
 status_t GraphicPlane::setOrientation(int orientation)
 {
-    const DisplayHardware& hw(displayHardware());
-    const float w = hw.getWidth();
-    const float h = hw.getHeight();
-
-    if (orientation == ISurfaceComposer::eOrientationDefault) {
-        // make sure the default orientation is optimal
-        mOrientationTransform.reset();
-        mOrientation = orientation;
-        mGlobalTransform = mTransform;
-        return NO_ERROR;
-    }
-
     // If the rotation can be handled in hardware, this is where
     // the magic should happen.
+
+    const DisplayHardware& hw(displayHardware());
+    const float w = mDisplayWidth;
+    const float h = mDisplayHeight;
+    mWidth = int(w);
+    mHeight = int(h);
+
+    Transform orientationTransform;
     if (UNLIKELY(orientation == 42)) {
         float a, b, c, d, x, y;
         const float r = (3.14159265f / 180.0f) * 42.0f;
@@ -1853,14 +1877,18 @@
         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);
-        mOrientationTransform.set(a, b, c, d);
-        mOrientationTransform.set(x, y);
+        orientationTransform.set(a, b, c, d);
+        orientationTransform.set(x, y);
     } else {
         GraphicPlane::orientationToTransfrom(orientation, w, h,
-                &mOrientationTransform);
+                &orientationTransform);
+        if (orientation & ISurfaceComposer::eOrientationSwapMask) {
+            mWidth = int(h);
+            mHeight = int(w);
+        }
     }
     mOrientation = orientation;
-    mGlobalTransform = mOrientationTransform * mTransform;
+    mGlobalTransform = mDisplayTransform * orientationTransform;
     return NO_ERROR;
 }
 
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index c0ab73d..4520c0e 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -31,11 +31,8 @@
 #include <binder/Permission.h>
 
 #include <ui/PixelFormat.h>
-#include <ui/ISurfaceComposer.h>
-#include <ui/ISurfaceFlingerClient.h>
-
-#include <private/ui/SharedBufferStack.h>
-#include <private/ui/LayerState.h>
+#include <surfaceflinger/ISurfaceComposer.h>
+#include <surfaceflinger/ISurfaceFlingerClient.h>
 
 #include "Barrier.h"
 #include "Layer.h"
@@ -116,9 +113,10 @@
         bool                    initialized() const;
 
         void                    setDisplayHardware(DisplayHardware *);
-        void                    setTransform(const Transform& tr);
         status_t                setOrientation(int orientation);
         int                     getOrientation() const { return mOrientation; }
+        int                     getWidth() const;
+        int                     getHeight() const;
 
         const DisplayHardware&  displayHardware() const;
         const Transform&        transform() const;
@@ -129,10 +127,13 @@
         GraphicPlane            operator = (const GraphicPlane&);
 
         DisplayHardware*        mHw;
-        Transform               mTransform;
-        Transform               mOrientationTransform;
         Transform               mGlobalTransform;
+        Transform               mDisplayTransform;
         int                     mOrientation;
+        float                   mDisplayWidth;
+        float                   mDisplayHeight;
+        int                     mWidth;
+        int                     mHeight;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/tests/overlays/Android.mk b/libs/surfaceflinger/tests/overlays/Android.mk
index dc47e45..592b601 100644
--- a/libs/surfaceflinger/tests/overlays/Android.mk
+++ b/libs/surfaceflinger/tests/overlays/Android.mk
@@ -7,7 +7,8 @@
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
 	libutils \
-    libui
+    libui \
+    libsurfaceflinger_client
 
 LOCAL_MODULE:= test-overlays
 
diff --git a/libs/surfaceflinger/tests/overlays/overlays.cpp b/libs/surfaceflinger/tests/overlays/overlays.cpp
index 0b9322e..c248a61 100644
--- a/libs/surfaceflinger/tests/overlays/overlays.cpp
+++ b/libs/surfaceflinger/tests/overlays/overlays.cpp
@@ -3,10 +3,11 @@
 #include <binder/IServiceManager.h>
 #include <utils/Log.h>
 
-#include <ui/Surface.h>
-#include <ui/ISurface.h>
 #include <ui/Overlay.h>
-#include <ui/SurfaceComposerClient.h>
+
+#include <surfaceflinger/Surface.h>
+#include <surfaceflinger/ISurface.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
 
 using namespace android;
 
diff --git a/libs/surfaceflinger/tests/resize/Android.mk b/libs/surfaceflinger/tests/resize/Android.mk
index ef1532f..24c2d01 100644
--- a/libs/surfaceflinger/tests/resize/Android.mk
+++ b/libs/surfaceflinger/tests/resize/Android.mk
@@ -7,7 +7,8 @@
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
 	libutils \
-    libui
+    libui \
+    libsurfaceflinger_client
 
 LOCAL_MODULE:= test-resize
 
diff --git a/libs/surfaceflinger/tests/resize/resize.cpp b/libs/surfaceflinger/tests/resize/resize.cpp
index 21c6ab6..127cca3 100644
--- a/libs/surfaceflinger/tests/resize/resize.cpp
+++ b/libs/surfaceflinger/tests/resize/resize.cpp
@@ -1,14 +1,16 @@
 #include <cutils/memory.h>
 
-#include <utils/IPCThreadState.h>
-#include <utils/ProcessState.h>
-#include <utils/IServiceManager.h>
 #include <utils/Log.h>
 
-#include <ui/Surface.h>
-#include <ui/ISurface.h>
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+
+#include <surfaceflinger/Surface.h>
+#include <surfaceflinger/ISurface.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
+
 #include <ui/Overlay.h>
-#include <ui/SurfaceComposerClient.h>
 
 using namespace android;
 
diff --git a/libs/surfaceflinger_client/Android.mk b/libs/surfaceflinger_client/Android.mk
new file mode 100644
index 0000000..fe85b34
--- /dev/null
+++ b/libs/surfaceflinger_client/Android.mk
@@ -0,0 +1,26 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	ISurfaceComposer.cpp \
+	ISurface.cpp \
+	ISurfaceFlingerClient.cpp \
+	LayerState.cpp \
+	SharedBufferStack.cpp \
+	Surface.cpp \
+	SurfaceComposerClient.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+	libutils \
+	libbinder \
+	libhardware \
+	libui
+
+LOCAL_MODULE:= libsurfaceflinger_client
+
+ifeq ($(TARGET_SIMULATOR),true)
+    LOCAL_LDLIBS += -lpthread
+endif
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libs/ui/ISurface.cpp b/libs/surfaceflinger_client/ISurface.cpp
similarity index 98%
rename from libs/ui/ISurface.cpp
rename to libs/surfaceflinger_client/ISurface.cpp
index 6f3d762..9125146 100644
--- a/libs/ui/ISurface.cpp
+++ b/libs/surfaceflinger_client/ISurface.cpp
@@ -23,12 +23,12 @@
 #include <binder/Parcel.h>
 #include <binder/IMemory.h>
 
-#include <ui/ISurface.h>
 #include <ui/Overlay.h>
-#include <ui/Surface.h>
-
 #include <ui/GraphicBuffer.h>
 
+#include <surfaceflinger/Surface.h>
+#include <surfaceflinger/ISurface.h>
+
 namespace android {
 
 // ----------------------------------------------------------------------
diff --git a/libs/ui/ISurfaceComposer.cpp b/libs/surfaceflinger_client/ISurfaceComposer.cpp
similarity index 98%
rename from libs/ui/ISurfaceComposer.cpp
rename to libs/surfaceflinger_client/ISurfaceComposer.cpp
index fd2a590..b6f4e24 100644
--- a/libs/ui/ISurfaceComposer.cpp
+++ b/libs/surfaceflinger_client/ISurfaceComposer.cpp
@@ -25,9 +25,10 @@
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 
-#include <ui/ISurfaceComposer.h>
 #include <ui/DisplayInfo.h>
 
+#include <surfaceflinger/ISurfaceComposer.h>
+
 // ---------------------------------------------------------------------------
 
 #define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
diff --git a/libs/ui/ISurfaceFlingerClient.cpp b/libs/surfaceflinger_client/ISurfaceFlingerClient.cpp
similarity index 97%
rename from libs/ui/ISurfaceFlingerClient.cpp
rename to libs/surfaceflinger_client/ISurfaceFlingerClient.cpp
index 4a6a1d7..e636c52 100644
--- a/libs/ui/ISurfaceFlingerClient.cpp
+++ b/libs/surfaceflinger_client/ISurfaceFlingerClient.cpp
@@ -26,12 +26,12 @@
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 
-#include <ui/ISurface.h>
-#include <ui/ISurfaceFlingerClient.h>
 #include <ui/Point.h>
 #include <ui/Rect.h>
 
-#include <private/ui/LayerState.h>
+#include <surfaceflinger/ISurface.h>
+#include <surfaceflinger/ISurfaceFlingerClient.h>
+#include <private/surfaceflinger/LayerState.h>
 
 // ---------------------------------------------------------------------------
 
diff --git a/libs/ui/LayerState.cpp b/libs/surfaceflinger_client/LayerState.cpp
similarity index 82%
rename from libs/ui/LayerState.cpp
rename to libs/surfaceflinger_client/LayerState.cpp
index a53ffb7..114a9e9 100644
--- a/libs/ui/LayerState.cpp
+++ b/libs/surfaceflinger_client/LayerState.cpp
@@ -16,37 +16,25 @@
 
 #include <utils/Errors.h>
 #include <binder/Parcel.h>
-#include <private/ui/LayerState.h>
+#include <private/surfaceflinger/LayerState.h>
 
 namespace android {
 
 status_t layer_state_t::write(Parcel& output) const
 {
     size_t size = sizeof(layer_state_t);
-
-    //output.writeStrongBinder(surface->asBinder());
-    //size -= sizeof(surface);
-
     transparentRegion.write(output);
     size -= sizeof(transparentRegion);
-    
     output.write(this, size);
-    
     return NO_ERROR;
 }
 
 status_t layer_state_t::read(const Parcel& input)
 {
     size_t size = sizeof(layer_state_t);
-
-    //surface = interface_cast<ISurface>(input.readStrongBinder());
-    //size -= sizeof(surface);
-
     transparentRegion.read(input);
     size -= sizeof(transparentRegion);
-
     input.read(this, size);
-    
     return NO_ERROR;
 }
 
diff --git a/libs/ui/SharedBufferStack.cpp b/libs/surfaceflinger_client/SharedBufferStack.cpp
similarity index 99%
rename from libs/ui/SharedBufferStack.cpp
rename to libs/surfaceflinger_client/SharedBufferStack.cpp
index 46b6766..ceb5e59 100644
--- a/libs/ui/SharedBufferStack.cpp
+++ b/libs/surfaceflinger_client/SharedBufferStack.cpp
@@ -23,7 +23,7 @@
 #include <utils/Log.h>
 #include <utils/threads.h>
 
-#include <private/ui/SharedBufferStack.h>
+#include <private/surfaceflinger/SharedBufferStack.h>
 
 #include <ui/Rect.h>
 #include <ui/Region.h>
diff --git a/libs/ui/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
similarity index 98%
rename from libs/ui/Surface.cpp
rename to libs/surfaceflinger_client/Surface.cpp
index c7be05b..eb3457b 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -26,22 +26,25 @@
 #include <utils/Errors.h>
 #include <utils/threads.h>
 #include <utils/CallStack.h>
+#include <utils/Log.h>
+
+#include <pixelflinger/pixelflinger.h>
+
 #include <binder/IPCThreadState.h>
 #include <binder/IMemory.h>
-#include <utils/Log.h>
 
 #include <ui/DisplayInfo.h>
 #include <ui/GraphicBuffer.h>
 #include <ui/GraphicBufferMapper.h>
-#include <ui/ISurface.h>
-#include <ui/Surface.h>
-#include <ui/SurfaceComposerClient.h>
 #include <ui/Rect.h>
 
-#include <pixelflinger/pixelflinger.h>
+#include <surfaceflinger/Surface.h>
+#include <surfaceflinger/ISurface.h>
+#include <surfaceflinger/ISurfaceComposer.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
 
-#include <private/ui/SharedBufferStack.h>
-#include <private/ui/LayerState.h>
+#include <private/surfaceflinger/SharedBufferStack.h>
+#include <private/surfaceflinger/LayerState.h>
 
 namespace android {
 
diff --git a/libs/ui/SurfaceComposerClient.cpp b/libs/surfaceflinger_client/SurfaceComposerClient.cpp
similarity index 97%
rename from libs/ui/SurfaceComposerClient.cpp
rename to libs/surfaceflinger_client/SurfaceComposerClient.cpp
index eda84ef..0b5e504 100644
--- a/libs/ui/SurfaceComposerClient.cpp
+++ b/libs/surfaceflinger_client/SurfaceComposerClient.cpp
@@ -29,19 +29,21 @@
 #include <utils/Errors.h>
 #include <utils/threads.h>
 #include <utils/KeyedVector.h>
-#include <binder/IServiceManager.h>
-#include <binder/IMemory.h>
 #include <utils/Log.h>
 
+#include <binder/IServiceManager.h>
+#include <binder/IMemory.h>
+
 #include <ui/DisplayInfo.h>
-#include <ui/ISurfaceComposer.h>
-#include <ui/ISurfaceFlingerClient.h>
-#include <ui/ISurface.h>
-#include <ui/SurfaceComposerClient.h>
 #include <ui/Rect.h>
 
-#include <private/ui/LayerState.h>
-#include <private/ui/SharedBufferStack.h>
+#include <surfaceflinger/ISurfaceComposer.h>
+#include <surfaceflinger/ISurfaceFlingerClient.h>
+#include <surfaceflinger/ISurface.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
+
+#include <private/surfaceflinger/LayerState.h>
+#include <private/surfaceflinger/SharedBufferStack.h>
 
 #define VERBOSE(...)	((void)0)
 //#define VERBOSE			LOGD
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index 84aec61..f7acd97 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -2,8 +2,6 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-	Camera.cpp \
-	CameraParameters.cpp \
 	EGLUtils.cpp \
 	EventHub.cpp \
 	EventRecurrence.cpp \
@@ -13,21 +11,11 @@
 	GraphicBufferMapper.cpp \
 	KeyLayoutMap.cpp \
 	KeyCharacterMap.cpp \
-	ICamera.cpp \
-	ICameraClient.cpp \
-	ICameraService.cpp \
 	IOverlay.cpp \
-	ISurfaceComposer.cpp \
-	ISurface.cpp \
-	ISurfaceFlingerClient.cpp \
-	LayerState.cpp \
 	Overlay.cpp \
 	PixelFormat.cpp \
 	Rect.cpp \
-	Region.cpp \
-	SharedBufferStack.cpp \
-	Surface.cpp \
-	SurfaceComposerClient.cpp
+	Region.cpp
 
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
index c5e22e5..1fa2c68 100644
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -27,7 +27,6 @@
 #include <utils/threads.h>
 #include <utils/RefBase.h>
 
-#include <ui/SurfaceComposerClient.h>
 #include <ui/Rect.h>
 #include <ui/FramebufferNativeWindow.h>
 
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk
index 59409a2..d2cfd3b 100644
--- a/libs/utils/Android.mk
+++ b/libs/utils/Android.mk
@@ -75,7 +75,6 @@
 # we have the common sources, plus some device-specific stuff
 LOCAL_SRC_FILES:= \
 	$(commonSources) \
-	Unicode.cpp \
     BackupData.cpp \
 	BackupHelpers.cpp
 
diff --git a/libs/utils/CharacterData.h b/libs/utils/CharacterData.h
deleted file mode 100644
index e931d99..0000000
--- a/libs/utils/CharacterData.h
+++ /dev/null
@@ -1,730 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-// Automatically generated on 07-11-2006 by make-CharacterDataC
-// DO NOT EDIT DIRECTLY
-namespace CharacterData {
-
-    // Structure containing an array of ranges
-    struct Range {
-        int length;
-        const uint32_t* array;
-    };
-
-    // For Latin1 characters just index into this array to get the index and decomposition
-    static const uint16_t LATIN1_DATA[] = {
-        0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 
-        0x0001, 0x0002, 0x0003, 0x0002, 0x0004, 0x0003, 0x0001, 0x0001, 
-        0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 
-        0x0001, 0x0001, 0x0001, 0x0001, 0x0003, 0x0003, 0x0003, 0x0002, 
-        0x0005, 0x0006, 0x0006, 0x0007, 0x0008, 0x0007, 0x0006, 0x0006, 
-        0x0009, 0x000A, 0x0006, 0x000B, 0x000C, 0x000D, 0x000C, 0x000C, 
-        0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 
-        0x0016, 0x0017, 0x000C, 0x0006, 0x0018, 0x0019, 0x001A, 0x0006, 
-        0x0006, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x0020, 0x0021, 
-        0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 
-        0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x0030, 0x0031, 
-        0x0032, 0x0033, 0x0034, 0x0035, 0x0006, 0x0036, 0x0037, 0x0038, 
-        0x0037, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 
-        0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 
-        0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 
-        0x0050, 0x0051, 0x0052, 0x0035, 0x0019, 0x0036, 0x0019, 0x0001, 
-        0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0003, 0x0001, 0x0001, 
-        0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 
-        0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 
-        0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 
-        0x5853, 0x0006, 0x0008, 0x0008, 0x0008, 0x0008, 0x0054, 0x0054, 
-        0x1037, 0x0054, 0x7855, 0x0056, 0x0019, 0x0057, 0x0054, 0x1037, 
-        0x0058, 0x0059, 0x785A, 0x785B, 0x1037, 0x105C, 0x0054, 0x0006, 
-        0x1037, 0x785D, 0x7855, 0x005E, 0x305F, 0x305F, 0x305F, 0x0006, 
-        0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0060, 0x0860, 
-        0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 
-        0x0060, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0019, 
-        0x0060, 0x0860, 0x0860, 0x0860, 0x0860, 0x0860, 0x0060, 0x0055, 
-        0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0061, 0x0861, 
-        0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 
-        0x0061, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0019, 
-        0x0061, 0x0861, 0x0861, 0x0861, 0x0861, 0x0861, 0x0061, 0x0862
-    };
-
-    // Each of these arrays is stripped into ranges. In order to build the arrays, each
-    // codepoint was bit-shifted so that even and odd characters were separated into different
-    // arrays. The identifier of each array is the top byte after bit-shifting.
-    // The numbers stored in the array are the bit-shifted codepoint, the decomposition, and an
-    // index into another array of all possible packed data values. The top 16 bits are the
-    // codepoint and the bottom 16 are the decomposition and index. The top 5 bits for the decomposition
-    // and the rest for the index.
-    static const uint32_t a0[] = {
-        0x00800863, 0x00880063, 0x00890863, 0x00930063, 0x00940863, 0x00980864, 0x00991063, 0x009A0863, 
-        0x009C0055, 0x009D0865, 0x00A01065, 0x00A10065, 0x00A20865, 0x00A50063, 0x00A60863, 0x00A90063, 
-        0x00AA0863, 0x00B30063, 0x00B40863, 0x00BC0866, 0x00BD0865, 0x00C00055, 0x00C10063, 0x00C30067, 
-        0x00C40065, 0x00C50068, 0x00C60065, 0x00C70069, 0x00C8006A, 0x00C90065, 0x00CA006B, 0x00CB006C, 
-        0x00CC0063, 0x00CD006D, 0x00CE006C, 0x00CF006E, 0x00D00863, 0x00D10063, 0x00D3006F, 0x00D40065, 
-        0x00D50055, 0x00D60063, 0x00D7006F, 0x00D80865, 0x00D90070, 0x00DA0065, 0x00DC0063, 0x00DD0055, 
-        0x00DE0063, 0x00DF0055, 0x00E00071, 0x00E21072, 0x00E31073, 0x00E41074, 0x00E51072, 0x00E61073, 
-        0x00E70865, 0x00EF0863, 0x00F20063, 0x00F30863, 0x00F80855, 0x00F91074, 0x00FA0863, 0x00FB0075, 
-        0x00FC0863, 0x010E0063, 0x010F0863, 0x01100076, 0x01110063, 0x01130863, 0x011A0055, 0x011D0077, 
-        0x011E0065, 0x011F0077, 0x01200055, 0x01210078, 0x01280055, 0x012A0079, 0x012B007A, 0x012C0055, 
-        0x0130007A, 0x01310055, 0x0134007B, 0x01350055, 0x0139007C, 0x013A0055, 0x0140007D, 0x01410055, 
-        0x0144007D, 0x0145007E, 0x01460055, 0x0149007F, 0x014A0080, 0x014B0055, 0x01587881, 0x015D0082, 
-        0x015E0081, 0x01610037, 0x01630082, 0x01680081, 0x01690037, 0x016C1037, 0x016F0037, 0x01707881, 
-        0x01730037, 0x01770081, 0x01780037, 0x01800083, 0x01A00883, 0x01A10083, 0x01A20883, 0x01A30083, 
-        0x01B80078, 0x01BA0837, 0x01BB0078, 0x01BD1081, 0x01BE0078, 0x01BF0806, 0x01C00078, 0x01C21037, 
-        0x01C30884, 0x01C40885, 0x01C60886, 0x01C70887, 0x01C80855, 0x01C90060, 0x01D10078, 0x01D20060, 
-        0x01D50860, 0x01D60888, 0x01D70889, 0x01D80855, 0x01D90061, 0x01E1008A, 0x01E20061, 0x01E50861, 
-        0x01E6088B, 0x01E7088C, 0x01E8108D, 0x01E91077, 0x01EA0877, 0x01EB108E, 0x01EC0063, 0x01F8108F, 
-        0x01F91090, 0x01FA1091, 0x01FB0019, 0x01FC0065, 0x01FD0063, 0x01FE0055, 0x01FF0077, 0x02000892, 
-        0x02010092, 0x02060892, 0x02080060, 0x02180061, 0x02280893, 0x02290093, 0x022E0893, 0x02300063, 
-        0x023B0863, 0x023C0063, 0x02410094, 0x02420083, 0x02440095, 0x02450063, 0x02600077, 0x02610865, 
-        0x02620065, 0x02680863, 0x026A0063, 0x026B0863, 0x026C0063, 0x026D0863, 0x02700063, 0x02710863, 
-        0x02740063, 0x02750863, 0x027B0063, 0x027C0863, 0x027D0078, 0x02800063, 0x02880078, 0x02990096, 
-        0x02AC0078, 0x02AD0097, 0x02B00078, 0x02B10098, 0x02C40078, 0x02C50099, 0x02C60078, 0x02C90083, 
-        0x02DD0078, 0x02DE0083, 0x02DF009A, 0x02E10083, 0x02E3009A, 0x02E40078, 0x02E8009B, 0x02F60078, 
-        0x02F8009B, 0x02FA009A, 0x02FB0078, 0x0300009C, 0x03020078, 0x0306000C, 0x03070054, 0x03080083, 
-        0x030B0078, 0x030F009D, 0x03100078, 0x0311089E, 0x0314009E, 0x031E0078, 0x0320009F, 0x0321009E, 
-        0x03260083, 0x033000A0, 0x033100A1, 0x033200A2, 0x033300A3, 0x033400A4, 0x03350007, 0x033600A5, 
-        0x0337009E, 0x03380083, 0x0339009E, 0x033B109E, 0x033D009E, 0x0360089E, 0x0362009E, 0x036A009D, 
-        0x036B0083, 0x036F0095, 0x03700083, 0x0373009F, 0x03740083, 0x0377009E, 0x0378000E, 0x03790010, 
-        0x037A0012, 0x037B0014, 0x037C0016, 0x037D009E, 0x037F00A6, 0x0380009D, 0x03870078, 0x0388009E, 
-        0x03980083, 0x03A60078, 0x03A7009E, 0x03B70078, 0x03C0009E, 0x03D30083, 0x03D90078, 0x04810083, 
-        0x04820071, 0x049A0871, 0x049B0071, 0x049D0078, 0x049E0083, 0x049F00A7, 0x04A10083, 0x04A500A7, 
-        0x04A70078, 0x04A80071, 0x04A90083, 0x04AB0078, 0x04AC0871, 0x04B00071, 0x04B10083, 0x04B20097, 
-        0x04B300A8, 0x04B400A9, 0x04B500AA, 0x04B600AB, 0x04B700AC, 0x04B80097, 0x04B90078, 0x04C100A7, 
-        0x04C20078, 0x04C30071, 0x04C70078, 0x04C80071, 0x04C90078, 0x04CA0071, 0x04DA0078, 0x04DB0071, 
-        0x04DD0078, 0x04DE0083, 0x04DF00A7, 0x04E10083, 0x04E30078, 0x04E400A7, 0x04E50078, 0x04E608A7, 
-        0x04E70071, 0x04E80078, 0x04EE0871, 0x04EF0078, 0x04F00071, 0x04F10083, 0x04F20078, 0x04F300A8, 
-        0x04F400A9, 0x04F500AA, 0x04F600AB, 0x04F700AC, 0x04F80071, 0x04F90008, 0x04FA00AD, 0x04FB00AE, 
-        0x04FC00AF, 0x04FD0094, 0x04FE0078, 0x05010083, 0x05020078, 0x05030071, 0x05060078, 0x05080071, 
-        0x05090078, 0x050A0071, 0x051A0078, 0x051B0871, 0x051C0071, 0x051D0078, 0x051E0083, 0x051F00A7, 
-        0x05210083, 0x05220078, 0x05240083, 0x05250078, 0x05260083, 0x05270078, 0x052D0871, 0x052E0071, 
-        0x052F0871, 0x05300078, 0x053300A8, 0x053400A9, 0x053500AA, 0x053600AB, 0x053700AC, 0x05380083, 
-        0x05390071, 0x053B0078, 0x05410083, 0x05420078, 0x05430071, 0x05470078, 0x05480071, 0x05490078, 
-        0x054A0071, 0x055A0078, 0x055B0071, 0x055D0078, 0x055E0083, 0x055F00A7, 0x05610083, 0x05630078, 
-        0x05640083, 0x05650078, 0x056600A7, 0x05670078, 0x05680071, 0x05690078, 0x05700071, 0x05710083, 
-        0x05720078, 0x057300A8, 0x057400A9, 0x057500AA, 0x057600AB, 0x057700AC, 0x05780078, 0x058100A7, 
-        0x05820078, 0x05830071, 0x05870078, 0x05880071, 0x05890078, 0x058A0071, 0x059A0078, 0x059B0071, 
-        0x059D0078, 0x059E0083, 0x059F00A7, 0x05A10083, 0x05A20078, 0x05A408A7, 0x05A50078, 0x05A608A7, 
-        0x05A70078, 0x05AB0083, 0x05AC0078, 0x05AE0871, 0x05AF0078, 0x05B00071, 0x05B10078, 0x05B300A8, 
-        0x05B400A9, 0x05B500AA, 0x05B600AB, 0x05B700AC, 0x05B80094, 0x05B90078, 0x05C10083, 0x05C20078, 
-        0x05C30071, 0x05C60078, 0x05C70071, 0x05CA0871, 0x05CB0078, 0x05CD0071, 0x05D00078, 0x05D20071, 
-        0x05D30078, 0x05D40071, 0x05D60078, 0x05D70071, 0x05DD0078, 0x05DF00A7, 0x05E00083, 0x05E100A7, 
-        0x05E20078, 0x05E300A7, 0x05E508A7, 0x05E70078, 0x05F300A8, 0x05F400A9, 0x05F500AA, 0x05F600AB, 
-        0x05F700AC, 0x05F800B0, 0x05F900B1, 0x05FA0054, 0x05FE0078, 0x060100A7, 0x06020078, 0x06030071, 
-        0x061A0078, 0x061B0071, 0x061D0078, 0x061F0083, 0x062100A7, 0x06230083, 0x06240883, 0x06250083, 
-        0x06270078, 0x062B0083, 0x062C0078, 0x06300071, 0x06310078, 0x063300A8, 0x063400A9, 0x063500AA, 
-        0x063600AB, 0x063700AC, 0x06380078, 0x064100A7, 0x06420078, 0x06430071, 0x065A0078, 0x065B0071, 
-        0x065D0078, 0x065E0083, 0x065F00A7, 0x066008A7, 0x066100A7, 0x066300B2, 0x066408A7, 0x06660083, 
-        0x06670078, 0x066B00A7, 0x066C0078, 0x066F0071, 0x06710078, 0x067300A8, 0x067400A9, 0x067500AA, 
-        0x067600AB, 0x067700AC, 0x06780078, 0x068100A7, 0x06820078, 0x06830071, 0x069D0078, 0x069F00A7, 
-        0x06A10083, 0x06A20078, 0x06A300A7, 0x06A508A7, 0x06A70078, 0x06B00071, 0x06B10078, 0x06B300A8, 
-        0x06B400A9, 0x06B500AA, 0x06B600AB, 0x06B700AC, 0x06B80078, 0x06C100A7, 0x06C20078, 0x06C30071, 
-        0x06CC0078, 0x06CD0071, 0x06D90078, 0x06DA0071, 0x06DE0078, 0x06E00071, 0x06E40078, 0x06E50083, 
-        0x06E60078, 0x06E800A7, 0x06E90083, 0x06EC00A7, 0x06ED08A7, 0x06F00078, 0x06F900A7, 0x06FA0097, 
-        0x06FB0078, 0x07010071, 0x071A0083, 0x071E0078, 0x07200071, 0x07230081, 0x07240083, 0x072800A8, 
-        0x072900A9, 0x072A00AA, 0x072B00AB, 0x072C00AC, 0x072D0097, 0x072E0078, 0x07410071, 0x07430078, 
-        0x07440071, 0x07460078, 0x074A0071, 0x074C0078, 0x074D0071, 0x07500078, 0x07510071, 0x07520078, 
-        0x07550071, 0x07560078, 0x07570071, 0x075A0083, 0x075D0078, 0x075E0083, 0x075F0078, 0x07600071, 
-        0x07630081, 0x07640083, 0x07670078, 0x076800A8, 0x076900A9, 0x076A00AA, 0x076B00AB, 0x076C00AC, 
-        0x076D0078, 0x076E1071, 0x076F0078, 0x07800071, 0x07810094, 0x07820097, 0x07865897, 0x07870097, 
-        0x078A0094, 0x078C0083, 0x078D0094, 0x079000A8, 0x079100A9, 0x079200AA, 0x079300AB, 0x079400AC, 
-        0x079500B3, 0x079A0094, 0x079D00B4, 0x079F00A7, 0x07A00071, 0x07A40078, 0x07A50071, 0x07A90871, 
-        0x07AA0071, 0x07AE0871, 0x07AF0071, 0x07B60078, 0x07B90083, 0x07BB0883, 0x07BD0083, 0x07C40071, 
-        0x07C60078, 0x07C80083, 0x07CC0078, 0x07CD0083, 0x07D10883, 0x07D20083, 0x07D60883, 0x07D70083, 
-        0x07DF0094, 0x07E30083, 0x07E40094, 0x07E70078, 0x07E80097, 0x07E90078, 0x08000071, 0x08110078, 
-        0x08120071, 0x08130871, 0x08140078, 0x08150071, 0x081600A7, 0x08170083, 0x081A0078, 0x081B0083, 
-        0x081C00A7, 0x081D0078, 0x082000A8, 0x082100A9, 0x082200AA, 0x082300AB, 0x082400AC, 0x08250097, 
-        0x08280071, 0x082B00A7, 0x082C0083, 0x082D0078, 0x085000B5, 0x08630078, 0x08680071, 0x087E7881, 
-        0x087F0078, 0x08800071, 0x08AD0078, 0x08B00071, 0x08D20078, 0x08D40071, 0x08FD0078, 0x09000071, 
-        0x09270078, 0x09280071, 0x092F0078, 0x09300071, 0x09470078, 0x09480071, 0x095B0078, 0x095C0071, 
-        0x09630078, 0x09640071, 0x098B0078, 0x098C0071, 0x09AE0078, 0x09B00094, 0x09B10097, 0x09B500B6, 
-        0x09B600B7, 0x09B700B8, 0x09B800B9, 0x09B900B0, 0x09BA00BA, 0x09BB00BB, 0x09BC00BC, 0x09BD00BD, 
-        0x09BE00BE, 0x09BF0078, 0x09C00071, 0x09C80054, 0x09CD0078, 0x09D00071, 0x09FB0078, 0x0A010071, 
-        0x0B370097, 0x0B380071, 0x0B3C0078, 0x0B400005, 0x0B410071, 0x0B4E00BF, 0x0B4F0078, 0x0B500071, 
-        0x0B760097, 0x0B7700C0, 0x0B7800C1, 0x0B790078, 0x0B800071, 0x0B890083, 0x0B8B0078, 0x0B900071, 
-        0x0B990083, 0x0B9B0097, 0x0B9C0078, 0x0BA00071, 0x0BA90083, 0x0BAA0078, 0x0BB00071, 0x0BB90083, 
-        0x0BBA0078, 0x0BC00071, 0x0BDA00C2, 0x0BDB00A7, 0x0BDC0083, 0x0BDF00A7, 0x0BE30083, 0x0BE400A7, 
-        0x0BE50083, 0x0BEA0097, 0x0BEE0071, 0x0BEF0078, 0x0BF000A8, 0x0BF100A9, 0x0BF200AA, 0x0BF300AB, 
-        0x0BF400AC, 0x0BF50078, 0x0BF800C3, 0x0BF900C4, 0x0BFA00C5, 0x0BFB00C6, 0x0BFC00C7, 0x0BFD0078, 
-        0x0C000006, 0x0C030099, 0x0C040006, 0x0C060083, 0x0C070005, 0x0C0800A8, 0x0C0900A9, 0x0C0A00AA, 
-        0x0C0B00AB, 0x0C0C00AC, 0x0C0D0078, 0x0C100071, 0x0C3C0078, 0x0C400071, 0x0C550078, 0x0C800071, 
-        0x0C8F0078, 0x0C900083, 0x0C9200A7, 0x0C940083, 0x0C9500C8, 0x0C960078, 0x0C9800A7, 0x0C990083, 
-        0x0C9A00A7, 0x0C9D0083, 0x0C9E0078, 0x0CA00054, 0x0CA10078, 0x0CA20006, 0x0CA300A8, 0x0CA400A9, 
-        0x0CA500AA, 0x0CA600AB, 0x0CA700AC, 0x0CA80071, 0x0CB70078, 0x0CB80071, 0x0CBB0078, 0x0CC00071, 
-        0x0CD50078, 0x0CD800A7, 0x0CE10071, 0x0CE400A7, 0x0CE50078, 0x0CE800A8, 0x0CE900A9, 0x0CEA00AA, 
-        0x0CEB00AB, 0x0CEC00AC, 0x0CED0078, 0x0CEF0006, 0x0CF00054, 0x0D000071, 0x0D0C0083, 0x0D0D00A7, 
-        0x0D0E0078, 0x0D0F0097, 0x0D100078, 0x0E800055, 0x0E967881, 0x0EA70081, 0x0EA87881, 0x0EB17055, 
-        0x0EB60055, 0x0EBC7881, 0x0EBD0055, 0x0ECE7881, 0x0EE00083, 0x0EE20078, 0x0F000863, 0x0F4B0855, 
-        0x0F4D1055, 0x0F4E0078, 0x0F500863, 0x0F7D0078, 0x0F8008C9, 0x0F8408CA, 0x0F8808C9, 0x0F8B0078, 
-        0x0F8C08CA, 0x0F8F0078, 0x0F9008C9, 0x0F9408CA, 0x0F9808C9, 0x0F9C08CA, 0x0FA008C9, 0x0FA30078, 
-        0x0FA408CA, 0x0FA70078, 0x0FA80855, 0x0FAC0078, 0x0FB008C9, 0x0FB408CA, 0x0FB808CB, 0x0FB908CC, 
-        0x0FBB08CD, 0x0FBC08CE, 0x0FBD08CF, 0x0FBE08D0, 0x0FBF0078, 0x0FC008C9, 0x0FC408D1, 0x0FC808C9, 
-        0x0FCC08D1, 0x0FD008C9, 0x0FD408D1, 0x0FD808C9, 0x0FD90855, 0x0FDC08CA, 0x0FDD08D2, 0x0FDE08D3, 
-        0x0FDF08D4, 0x0FE01037, 0x0FE10855, 0x0FE408D5, 0x0FE608D3, 0x0FE70837, 0x0FE808C9, 0x0FE90855, 
-        0x0FEA0078, 0x0FEB0855, 0x0FEC08CA, 0x0FED08D6, 0x0FEE0078, 0x0FEF0837, 0x0FF008C9, 0x0FF10855, 
-        0x0FF408CA, 0x0FF508D7, 0x0FF608D8, 0x0FF70837, 0x0FF80078, 0x0FF90855, 0x0FFC08D9, 0x0FFD08DA, 
-        0x0FFE08D3, 0x0FFF1037, 0x10000805, 0x10011005, 0x10060057, 0x100700C2, 0x10080099, 0x100B0006, 
-        0x100C00DB, 0x100D00B4, 0x100E00DB, 0x100F00B4, 0x10100006, 0x10121006, 0x101400DC, 0x101500DD, 
-        0x101600DE, 0x101700DF, 0x10180007, 0x101A1007, 0x101B1006, 0x101C0006, 0x101D00E0, 0x101E1006, 
-        0x10200038, 0x10210006, 0x102200E1, 0x1023000A, 0x10241006, 0x10250006, 0x10290019, 0x102A0038, 
-        0x102B0006, 0x10300057, 0x10320078, 0x10350057, 0x103878E2, 0x10390078, 0x103A78E3, 0x103B78E4, 
-        0x103C78E5, 0x103D780B, 0x103E7819, 0x103F780A, 0x104070E2, 0x1041705A, 0x104270E3, 0x104370E4, 
-        0x104470E5, 0x1045700B, 0x10467019, 0x1047700A, 0x10487081, 0x104B0078, 0x10500008, 0x10541008, 
-        0x10550008, 0x105B0078, 0x10680083, 0x106F0095, 0x10730083, 0x10760078, 0x10801054, 0x10812877, 
-        0x10820054, 0x10831054, 0x10840054, 0x10852855, 0x10862877, 0x10872855, 0x10882877, 0x108A0054, 
-        0x108B1054, 0x108C0054, 0x108D2877, 0x108F0054, 0x10907854, 0x10922877, 0x109308E6, 0x10942877, 
-        0x109508E7, 0x10962877, 0x10970058, 0x10982877, 0x10990054, 0x109A2855, 0x109B1071, 0x109D0054, 
-        0x109E2855, 0x109F2877, 0x10A028E8, 0x10A10019, 0x10A32855, 0x10A50054, 0x10A70078, 0x10AA305F, 
-        0x10B010E9, 0x10B110EA, 0x10B210EB, 0x10B310EC, 0x10B410ED, 0x10B510EE, 0x10B610EF, 0x10B710F0, 
-        0x10B810F1, 0x10B910F2, 0x10BA10F3, 0x10BB10F4, 0x10BC10F5, 0x10BD10F6, 0x10BE10F7, 0x10BF10F8, 
-        0x10C000F9, 0x10C100FA, 0x10C20078, 0x10C80019, 0x10CB0054, 0x10CD0819, 0x10CE0054, 0x10D00019, 
-        0x10D10054, 0x10D30019, 0x10D40054, 0x10D70819, 0x10D80054, 0x10E70819, 0x10E80054, 0x10E90019, 
-        0x10EB0054, 0x10FA0019, 0x110100E8, 0x110208E8, 0x11030019, 0x110400FB, 0x110608FC, 0x11070019, 
-        0x1109000B, 0x110A0019, 0x110B00E8, 0x110C0019, 0x110D00E8, 0x110F0019, 0x111000E8, 0x111208E8, 
-        0x11140019, 0x111610E8, 0x111700E8, 0x111810E8, 0x111900E8, 0x111A0019, 0x111E00FD, 0x111F00E8, 
-        0x112208E8, 0x112300E8, 0x11270019, 0x112900FD, 0x112B0019, 0x113008E8, 0x113200FD, 0x11360019, 
-        0x113708FD, 0x113900FD, 0x113A08FD, 0x113B00FD, 0x113C08FD, 0x113D00FD, 0x114008FD, 0x114100FD, 
-        0x114208FD, 0x114300FD, 0x114408FD, 0x114500FD, 0x114600E8, 0x11470019, 0x114800FE, 0x114A0019, 
-        0x114C00FF, 0x114D0019, 0x115100FD, 0x11520019, 0x11530100, 0x11540101, 0x115500E8, 0x115608E8, 
-        0x115800FD, 0x115C00E8, 0x115D0019, 0x115F00E8, 0x11600019, 0x116500FE, 0x11670019, 0x116800FD, 
-        0x11690019, 0x116B00FD, 0x117008FD, 0x117200FD, 0x117508FD, 0x11770019, 0x117800FD, 0x11790102, 
-        0x117B0103, 0x117C00E8, 0x117D0104, 0x117F0105, 0x11800054, 0x118400FD, 0x11860054, 0x119000E8, 
-        0x11910054, 0x1195080A, 0x11960054, 0x119B0094, 0x11BE0019, 0x11BF0054, 0x11CE0019, 0x11DA00B4, 
-        0x11DB0006, 0x11DC0054, 0x11EE0078, 0x12000054, 0x12140078, 0x12200054, 0x12260078, 0x12301906, 
-        0x12311907, 0x12321908, 0x12331909, 0x1234190A, 0x1235190B, 0x1236190C, 0x1237190D, 0x1238190E, 
-        0x1239190F, 0x123A1106, 0x123B1107, 0x123C1108, 0x123D1109, 0x123E110A, 0x123F110B, 0x1240110C, 
-        0x1241110D, 0x1242110E, 0x1243110F, 0x1244105D, 0x1245105B, 0x12461110, 0x12471111, 0x12481112, 
-        0x12491113, 0x124A1114, 0x124B1115, 0x124C1116, 0x124D1117, 0x124E1094, 0x125B1918, 0x12681919, 
-        0x127518C3, 0x1276011A, 0x1277011B, 0x1278011C, 0x1279011D, 0x127A011E, 0x127B00C4, 0x127C00C5, 
-        0x127D00C6, 0x127E00C7, 0x127F011F, 0x12800054, 0x12FC0019, 0x13000054, 0x134F0078, 0x13500054, 
-        0x13560094, 0x13570054, 0x13590078, 0x13810054, 0x13850078, 0x13860054, 0x13940078, 0x13950054, 
-        0x13A60078, 0x13A80054, 0x13AA0078, 0x13AB0054, 0x13B00078, 0x13B10054, 0x13B40009, 0x13BB0106, 
-        0x13BC0107, 0x13BD0108, 0x13BE0109, 0x13BF010A, 0x13C00106, 0x13C10107, 0x13C20108, 0x13C30109, 
-        0x13C4010A, 0x13C50106, 0x13C60107, 0x13C70108, 0x13C80109, 0x13C9010A, 0x13CA0054, 0x13CB0078, 
-        0x13CC0054, 0x13D80078, 0x13D90054, 0x13E000E8, 0x13E10019, 0x13E200FE, 0x13E3000A, 0x13E40078, 
-        0x13E80019, 0x13EA00E8, 0x13EB00FE, 0x13EC0019, 0x13EE00E8, 0x13EF00FE, 0x13F00019, 0x13F100FD, 
-        0x13F30009, 0x13F60078, 0x13F80019, 0x14000094, 0x14800019, 0x14C2000A, 0x14C70120, 0x14C80121, 
-        0x14C9000A, 0x14CD0019, 0x14CE00E8, 0x14D80019, 0x14DC0122, 0x14DD0019, 0x14E000FD, 0x14E100E8, 
-        0x14E200FD, 0x14E30019, 0x14E700E8, 0x14E800FE, 0x14EA00FD, 0x14EB0019, 0x14EC0009, 0x14EE00E8, 
-        0x14EF0019, 0x14F200E8, 0x14F30019, 0x14F400E8, 0x14F50019, 0x14FA00E8, 0x14FC00FD, 0x14FD0019, 
-        0x14FE0009, 0x14FF0019, 0x150500E8, 0x150610E8, 0x150700E8, 0x15110019, 0x151200E8, 0x15140019, 
-        0x151600FE, 0x15180019, 0x151A00FD, 0x151B0019, 0x151E00FD, 0x151F00E8, 0x15200019, 0x152C00E8, 
-        0x152D0019, 0x153200FD, 0x15330019, 0x153500E8, 0x15370019, 0x153800E8, 0x15390019, 0x153A10E8, 
-        0x153B1019, 0x153C0019, 0x153D00FE, 0x153E00E8, 0x153F00FE, 0x154300E8, 0x154600FE, 0x154700E8, 
-        0x154900FE, 0x154F00E8, 0x155100FE, 0x15520019, 0x155300FD, 0x15570019, 0x155800FE, 0x155900E8, 
-        0x155A00FE, 0x155B00E8, 0x155E00FE, 0x156400E8, 0x156700FE, 0x156C0019, 0x156E08E8, 0x156F0123, 
-        0x15700019, 0x157100E8, 0x15720124, 0x157300E8, 0x15740019, 0x157600FD, 0x157700E8, 0x15780019, 
-        0x157C00FE, 0x157E0019, 0x15800054, 0x158A0078, 0x16000096, 0x16180098, 0x16300078, 0x16400063, 
-        0x16720055, 0x16730054, 0x16760078, 0x167D0006, 0x16800125, 0x16930078, 0x16980071, 0x16B30078, 
-        0x16C00071, 0x16CC0078, 0x16D00071, 0x16F00078, 0x17000006, 0x17010126, 0x17030006, 0x170500E0, 
-        0x17060126, 0x17070006, 0x170C0078, 0x170E0126, 0x170F0078, 0x17400054, 0x174D0078, 0x174E0054, 
-        0x177A0078, 0x17801054, 0x17EB0078, 0x17F80054, 0x17FE0078, 0x18008805, 0x18010006, 0x18020054, 
-        0x18030071, 0x18040009, 0x18090054, 0x180A0009, 0x180E0099, 0x180F00BF, 0x18100054, 0x18110127, 
-        0x18120128, 0x18130129, 0x1814012A, 0x18150083, 0x18180099, 0x18190081, 0x181B1054, 0x181C112B, 
-        0x181D112C, 0x181E0071, 0x181F0054, 0x18200078, 0x18210071, 0x18260871, 0x18320071, 0x18380871, 
-        0x18390071, 0x183A0871, 0x183C0071, 0x183D0871, 0x183F0071, 0x184A0871, 0x184B0071, 0x184C0078, 
-        0x184D0083, 0x184E1037, 0x184F0881, 0x18500099, 0x18510071, 0x18560871, 0x18620071, 0x18680871, 
-        0x18690071, 0x186A0871, 0x186C0071, 0x186D0871, 0x186F0071, 0x187A0871, 0x187B0071, 0x187C0871, 
-        0x187E0081, 0x187F0881, 0x18800078, 0x18830071, 0x18970078, 0x18991071, 0x18C80094, 0x18C978AD, 
-        0x18CA78AE, 0x18CB7894, 0x18D00071, 0x18DC0078, 0x18E00054, 0x18E80078, 0x18F80071, 0x19001094, 
-        0x190F1054, 0x191010AD, 0x191110AE, 0x1912112D, 0x1913112E, 0x1914112F, 0x19151094, 0x19220078, 
-        0x19286854, 0x19291930, 0x192A1931, 0x192B1932, 0x192C1933, 0x192D1934, 0x192E1935, 0x192F1936, 
-        0x19301894, 0x193E1854, 0x194018AD, 0x194118AE, 0x1942192D, 0x1943192E, 0x1944192F, 0x19451894, 
-        0x19591937, 0x195A1938, 0x195B1939, 0x195C193A, 0x195D193B, 0x195E193C, 0x195F193D, 0x19601094, 
-        0x19666854, 0x19681894, 0x19806894, 0x19AC1094, 0x19B96894, 0x19BC6854, 0x19BE6894, 0x19EF6854, 
-        0x19F01094, 0x1A000071, 0x26DB0078, 0x26E00054, 0x27000071, 0x4FDE0078, 0x50000071, 0x52470078, 
-        0x52480054, 0x52640078, 0x53800037, 0x538C0078, 0x54000071, 0x540100C8, 0x54020071, 0x54030083, 
-        0x54040071, 0x541200A7, 0x54130083, 0x54140054, 0x54160078, 0x56000071, 0x6BD20078, 0x6C00013E, 
-        0x7000013F, 0x7C800871, 0x7D070071, 0x7D080871, 0x7D0A0071, 0x7D0B0871, 0x7D120071, 0x7D130871, 
-        0x7D140071, 0x7D150871, 0x7D170078, 0x7D180871, 0x7D360078, 0x7D380871, 0x7D6D0078, 0x7D801055, 
-        0x7D840078, 0x7D8A1055, 0x7D8C0078, 0x7D8F0083, 0x7D90289B, 0x7D95089B, 0x7DA10078, 0x7DA2089B, 
-        0x7DA8409E, 0x7DAA389E, 0x7DAB409E, 0x7DAC389E, 0x7DAD409E, 0x7DAE389E, 0x7DAF409E, 0x7DB0389E, 
-        0x7DB1409E, 0x7DB2389E, 0x7DB3409E, 0x7DB4389E, 0x7DB5409E, 0x7DB6389E, 0x7DB7409E, 0x7DB8389E, 
-        0x7DB9409E, 0x7DBA389E, 0x7DBB409E, 0x7DBC389E, 0x7DBD409E, 0x7DBE389E, 0x7DBF409E, 0x7DC0389E, 
-        0x7DC1409E, 0x7DC8389E, 0x7DC9409E, 0x7DCA389E, 0x7DCB409E, 0x7DCC389E, 0x7DCD409E, 0x7DCE389E, 
-        0x7DCF409E, 0x7DD1389E, 0x7DD2409E, 0x7DD4389E, 0x7DD5409E, 0x7DD6389E, 0x7DD7409E, 0x7DD90078, 
-        0x7DEA209E, 0x7DEB489E, 0x7DEC209E, 0x7DEF409E, 0x7DF3389E, 0x7DF5409E, 0x7DFC389E, 0x7DFD209E, 
-        0x7DFE409E, 0x7DFF389E, 0x7E00409E, 0x7E32209E, 0x7E4C389E, 0x7E70489E, 0x7E7B409E, 0x7E89209E, 
-        0x7E97389E, 0x7E9A489E, 0x7E9E209E, 0x7E9F00B4, 0x7EA00078, 0x7EA8389E, 0x7EAC209E, 0x7EAE389E, 
-        0x7EAF209E, 0x7EB0389E, 0x7EB1209E, 0x7EB4389E, 0x7EB5209E, 0x7EB8389E, 0x7EBA209E, 0x7EC3389E, 
-        0x7EC80078, 0x7EC9389E, 0x7ECB209E, 0x7ECC389E, 0x7ECD209E, 0x7EDA389E, 0x7EDB209E, 0x7EDC389E, 
-        0x7EDE209E, 0x7EE2389E, 0x7EE3209E, 0x7EE40078, 0x7EF8409E, 0x7EFE4140, 0x7EFF0078, 0x7F000083, 
-        0x7F088006, 0x7F0C80BF, 0x7F0D0078, 0x7F100083, 0x7F120078, 0x7F188006, 0x7F198099, 0x7F1A8038, 
-        0x7F1B80BF, 0x7F230006, 0x7F2480BF, 0x7F251006, 0x7F271038, 0x7F28600C, 0x7F2A6006, 0x7F2C6099, 
-        0x7F2D60BF, 0x7F306006, 0x7F31600B, 0x7F326019, 0x7F346006, 0x7F356007, 0x7F360078, 0x7F38409E, 
-        0x7F41209E, 0x7F46489E, 0x7F47209E, 0x7F49489E, 0x7F4A209E, 0x7F4C489E, 0x7F4D209E, 0x7F4E489E, 
-        0x7F4F209E, 0x7F50489E, 0x7F51209E, 0x7F52489E, 0x7F53209E, 0x7F54489E, 0x7F55209E, 0x7F5A489E, 
-        0x7F5B209E, 0x7F5C489E, 0x7F5D209E, 0x7F5E489E, 0x7F5F209E, 0x7F60489E, 0x7F61209E, 0x7F62489E, 
-        0x7F63209E, 0x7F64489E, 0x7F65209E, 0x7F66489E, 0x7F67209E, 0x7F68489E, 0x7F69209E, 0x7F6A489E, 
-        0x7F6B209E, 0x7F6C489E, 0x7F6D209E, 0x7F6E489E, 0x7F6F209E, 0x7F70489E, 0x7F71209E, 0x7F72489E, 
-        0x7F73209E, 0x7F74489E, 0x7F75209E, 0x7F76489E, 0x7F77209E, 0x7F7A489E, 0x7F7B209E, 0x7F7F0078, 
-        0x7F818806, 0x7F828808, 0x7F838806, 0x7F848809, 0x7F858806, 0x7F86880C, 0x7F88880E, 0x7F898810, 
-        0x7F8A8812, 0x7F8B8814, 0x7F8C8816, 0x7F8D880C, 0x7F8E8818, 0x7F8F881A, 0x7F908806, 0x7F918860, 
-        0x7F9E8806, 0x7F9F8837, 0x7FA18861, 0x7FAE8819, 0x7FB0880A, 0x7FB15009, 0x7FB25006, 0x7FB35071, 
-        0x7FB85081, 0x7FB95071, 0x7FCF5081, 0x7FD05071, 0x7FE00078, 0x7FE15071, 0x7FE40078, 0x7FE55071, 
-        0x7FE80078, 0x7FE95071, 0x7FEC0078, 0x7FED5071, 0x7FEF0078, 0x7FF08808, 0x7FF18819, 0x7FF28854, 
-        0x7FF38808, 0x7FF45054, 0x7FF55019, 0x7FF75054, 0x7FF80078, 0x7FFD0141, 0x7FFE0054, 0x7FFF0078, 
-        0x80000071, 0x80060078, 0x80070071, 0x801F0078, 0x80200071, 0x80270078, 0x80280071, 0x802F0078, 
-        0x80400071, 0x807E0078, 0x80800097, 0x80810094, 0x80820078, 0x808400B6, 0x808500B7, 0x808600B8, 
-        0x808700B9, 0x808800B0, 0x808900BA, 0x808A00BB, 0x808B00BC, 0x808C00BD, 0x808D0142, 0x808E0143, 
-        0x808F0144, 0x80900145, 0x809100B1, 0x80920146, 0x80930147, 0x80940148, 0x80950149, 0x8096014A, 
-        0x8097014B, 0x8098014C, 0x8099014D, 0x809A0078, 0x809C0094, 0x80A0014E, 0x80A1014F, 0x80A20150, 
-        0x80A30151, 0x80A40152, 0x80A50150, 0x80A60153, 0x80A70151, 0x80A80154, 0x80A90155, 0x80AA0156, 
-        0x80AB0157, 0x80AC014F, 0x80AE0158, 0x80B00154, 0x80B30150, 0x80B50155, 0x80B60153, 0x80B90151, 
-        0x80BA0150, 0x80BB005F, 0x80BD0054, 0x80C500C3, 0x80C60078, 0x81800071, 0x819000AD, 0x819100B0, 
-        0x81920078, 0x81980071, 0x81A50159, 0x81A60078, 0x81C00071, 0x81CF0078, 0x81D00071, 0x81E20078, 
-        0x81E40071, 0x81E80094, 0x81E90158, 0x81EA015A, 0x81EB0078, 0x8200015B, 0x8214015C, 0x82280071, 
-        0x824F0078, 0x825000A8, 0x825100A9, 0x825200AA, 0x825300AB, 0x825400AC, 0x82550078, 0x8400009B, 
-        0x84030078, 0x8404009B, 0x841B0078, 0x841C009B, 0x841D0078, 0x841E009B, 0x841F0078, 0x8500009B, 
-        0x85010083, 0x85020078, 0x85030083, 0x85040078, 0x85060083, 0x8508009B, 0x850A0078, 0x850B009B, 
-        0x850C0078, 0x850D009B, 0x851A0078, 0x851C0083, 0x851E0078, 0x8520015D, 0x8521015E, 0x8522015F, 
-        0x85230160, 0x85240078, 0x8528009A, 0x852D0078, 0xE8000094, 0xE87B0078, 0xE8800094, 0xE8940078, 
-        0xE8950094, 0xE8AF0894, 0xE8B300A7, 0xE8B40083, 0xE8B50094, 0xE8B700A7, 0xE8BA0057, 0xE8BE0083, 
-        0xE8C20094, 0xE8C30083, 0xE8C60094, 0xE8D50083, 0xE8D70094, 0xE8DE0894, 0xE8E10094, 0xE8EF0078, 
-        0xE9000054, 0xE9210083, 0xE9230078, 0xE9800054, 0xE9AC0078, 0xEA002877, 0xEA0D2855, 0xEA1A2877, 
-        0xEA272855, 0xEA342877, 0xEA412855, 0xEA4E2877, 0xEA500078, 0xEA512877, 0xEA520078, 0xEA532877, 
-        0xEA540078, 0xEA552877, 0xEA5B2855, 0xEA5D0078, 0xEA5F2855, 0xEA620078, 0xEA632855, 0xEA682877, 
-        0xEA752855, 0xEA822877, 0xEA830078, 0xEA842877, 0xEA860078, 0xEA872877, 0xEA8F2855, 0xEA9C2877, 
-        0xEA9D0078, 0xEA9E2877, 0xEAA40078, 0xEAA52877, 0xEAA92855, 0xEAB62877, 0xEAC32855, 0xEAD02877, 
-        0xEADD2855, 0xEAEA2877, 0xEAF72855, 0xEB042877, 0xEB112855, 0xEB1E2877, 0xEB2B2855, 0xEB382877, 
-        0xEB452855, 0xEB530078, 0xEB542877, 0xEB612855, 0xEB712877, 0xEB7E2855, 0xEB8E2877, 0xEB9B2855, 
-        0xEBAB2877, 0xEBB82855, 0xEBC82877, 0xEBD52855, 0xEBE50078, 0xEBE7280E, 0xEBE82810, 0xEBE92812, 
-        0xEBEA2814, 0xEBEB2816, 0xEBEC280E, 0xEBED2810, 0xEBEE2812, 0xEBEF2814, 0xEBF02816, 0xEBF1280E, 
-        0xEBF22810, 0xEBF32812, 0xEBF42814, 0xEBF52816, 0xEBF6280E, 0xEBF72810, 0xEBF82812, 0xEBF92814, 
-        0xEBFA2816, 0xEBFB280E, 0xEBFC2810, 0xEBFD2812, 0xEBFE2814, 0xEBFF2816, 0xEC000078
-    };
-
-    static const uint32_t a1[] = {
-        0x00000071, 0x536C0078, 0x7C000871, 0x7D0F0078
-    };
-
-    static const uint32_t a7[] = {
-        0x00100057, 0x00400078, 0x00800083, 0x00F80078, 0x8000013F, 0xFFFF0078
-    };
-
-    static const uint32_t a8[] = {
-        0x0000013F, 0x7FFF0078
-    };
-
-    static const uint32_t a16[] = {
-        0x00800865, 0x00880065, 0x00890865, 0x00930065, 0x00940865, 0x00980161, 0x00991065, 0x009A0865, 
-        0x009C0863, 0x009F1063, 0x00A00063, 0x00A10863, 0x00A41055, 0x00A50065, 0x00A60865, 0x00A90065, 
-        0x00AA0865, 0x00B30065, 0x00B40865, 0x00BC0863, 0x00BF1162, 0x00C00163, 0x00C10065, 0x00C30063, 
-        0x00C40068, 0x00C50063, 0x00C60055, 0x00C70164, 0x00C80063, 0x00C90068, 0x00CA0165, 0x00CB0166, 
-        0x00CC0065, 0x00CD0055, 0x00CE0167, 0x00CF0168, 0x00D00865, 0x00D10065, 0x00D30063, 0x00D4006F, 
-        0x00D50055, 0x00D60065, 0x00D70863, 0x00D80070, 0x00D90063, 0x00DB0169, 0x00DC0065, 0x00DD0071, 
-        0x00DE0065, 0x00DF016A, 0x00E00071, 0x00E21074, 0x00E31072, 0x00E41073, 0x00E51074, 0x00E60863, 
-        0x00EE016B, 0x00EF0865, 0x00F20065, 0x00F30865, 0x00F81072, 0x00F91073, 0x00FA0865, 0x00FB016C, 
-        0x00FC0865, 0x010E0065, 0x010F0865, 0x01100055, 0x01110065, 0x01130865, 0x011A0055, 0x011D0063, 
-        0x011E016D, 0x011F0055, 0x0120016E, 0x01210078, 0x01280055, 0x0129016F, 0x012A0055, 0x012B007A, 
-        0x012C0170, 0x012D0171, 0x012E0055, 0x01310172, 0x01320055, 0x01340173, 0x01350055, 0x01370173, 
-        0x01380055, 0x013A0174, 0x013B0055, 0x0141007D, 0x01420055, 0x0145007E, 0x01460055, 0x01587881, 
-        0x015C0082, 0x015D0081, 0x01610037, 0x01630082, 0x01680081, 0x01690037, 0x016C1037, 0x016F0037, 
-        0x01707881, 0x01720037, 0x01800083, 0x01A00883, 0x01A20175, 0x01A30083, 0x01B80078, 0x01BA0037, 
-        0x01BB0078, 0x01C20837, 0x01C30806, 0x01C40885, 0x01C50078, 0x01C70887, 0x01C80060, 0x01D50860, 
-        0x01D60889, 0x01D80061, 0x01E50861, 0x01E6088C, 0x01E70078, 0x01E81176, 0x01E90877, 0x01EA1177, 
-        0x01EB0055, 0x01EC0065, 0x01F81093, 0x01F90055, 0x01FA1178, 0x01FB0063, 0x01FC10D8, 0x01FD0065, 
-        0x01FE0077, 0x02000892, 0x02020092, 0x02030892, 0x02040092, 0x02060892, 0x02070092, 0x02080060, 
-        0x020C0860, 0x020D0060, 0x02180061, 0x021C0861, 0x021D0061, 0x02280893, 0x022A0093, 0x022B0893, 
-        0x022C0093, 0x022E0893, 0x022F0093, 0x02300065, 0x023B0865, 0x023C0065, 0x02410083, 0x02430078, 
-        0x02440095, 0x02450065, 0x02600863, 0x02610063, 0x02670078, 0x02680865, 0x026A0065, 0x026B0865, 
-        0x026C0065, 0x026D0865, 0x02700065, 0x02710865, 0x02740065, 0x02750865, 0x027B0065, 0x027C0865, 
-        0x027D0078, 0x02800065, 0x02880078, 0x02980096, 0x02AB0078, 0x02AC0081, 0x02AD0097, 0x02B00098, 
-        0x02C31055, 0x02C40097, 0x02C50078, 0x02C80083, 0x02E1009A, 0x02E20083, 0x02E40078, 0x02E8009B, 
-        0x02F50078, 0x02F8009B, 0x02F9009A, 0x02FA0078, 0x0300009C, 0x03020078, 0x03050140, 0x0306009D, 
-        0x03070054, 0x03080083, 0x030B0078, 0x030D009D, 0x030E0078, 0x030F009D, 0x0310009E, 0x0311089E, 
-        0x0313009E, 0x031D0078, 0x0320009E, 0x03250083, 0x032F0078, 0x03300179, 0x0331017A, 0x0332017B, 
-        0x0333017C, 0x0334017D, 0x033500A5, 0x0336009D, 0x0337009E, 0x033A109E, 0x033C009E, 0x0369089E, 
-        0x036A009E, 0x036B0083, 0x036E009C, 0x036F0083, 0x0372009F, 0x03730083, 0x03740054, 0x03750083, 
-        0x0377009E, 0x0378000F, 0x03790011, 0x037A0013, 0x037B0015, 0x037C0017, 0x037D009E, 0x037E00A6, 
-        0x037F009E, 0x0380009D, 0x03870057, 0x03880083, 0x0389009E, 0x03980083, 0x03A50078, 0x03A6009E, 
-        0x03B70078, 0x03C0009E, 0x03D30083, 0x03D8009E, 0x03D90078, 0x04800083, 0x048100A7, 0x04820071, 
-        0x04940871, 0x04950071, 0x04980871, 0x04990071, 0x049D0078, 0x049E0071, 0x049F00A7, 0x04A00083, 
-        0x04A400A7, 0x04A60083, 0x04A70078, 0x04A80083, 0x04AA0078, 0x04AC0871, 0x04B00071, 0x04B10083, 
-        0x04B20097, 0x04B3017E, 0x04B4017F, 0x04B50180, 0x04B60181, 0x04B70182, 0x04B80078, 0x04BE0071, 
-        0x04BF0078, 0x04C00083, 0x04C100A7, 0x04C20071, 0x04C60078, 0x04C70071, 0x04C80078, 0x04C90071, 
-        0x04D40078, 0x04D50071, 0x04D80078, 0x04DB0071, 0x04DD0078, 0x04DE0071, 0x04DF00A7, 0x04E00083, 
-        0x04E20078, 0x04E300A7, 0x04E40078, 0x04E508A7, 0x04E60083, 0x04E70078, 0x04EB00A7, 0x04EC0078, 
-        0x04EE0871, 0x04F00071, 0x04F10083, 0x04F20078, 0x04F3017E, 0x04F4017F, 0x04F50180, 0x04F60181, 
-        0x04F70182, 0x04F80071, 0x04F90008, 0x04FA00B6, 0x04FB00B7, 0x04FC0183, 0x04FD0078, 0x05000083, 
-        0x050100A7, 0x05020071, 0x05050078, 0x05070071, 0x05080078, 0x05090071, 0x05140078, 0x05150071, 
-        0x05180078, 0x05190871, 0x051A0071, 0x051B0078, 0x051C0071, 0x051D0078, 0x051F00A7, 0x05200083, 
-        0x05210078, 0x05230083, 0x05240078, 0x05250083, 0x05270078, 0x052C0871, 0x052E0078, 0x0533017E, 
-        0x0534017F, 0x05350180, 0x05360181, 0x05370182, 0x05380083, 0x05390071, 0x053A0078, 0x05400083, 
-        0x054100A7, 0x05420071, 0x05540078, 0x05550071, 0x05580078, 0x05590071, 0x055D0078, 0x055E0071, 
-        0x055F00A7, 0x05600083, 0x056400A7, 0x05660083, 0x05670078, 0x05700071, 0x05710083, 0x05720078, 
-        0x0573017E, 0x0574017F, 0x05750180, 0x05760181, 0x05770182, 0x05780008, 0x05790078, 0x05800083, 
-        0x058100A7, 0x05820071, 0x05860078, 0x05870071, 0x05880078, 0x05890071, 0x05940078, 0x05950071, 
-        0x05980078, 0x05990071, 0x059D0078, 0x059E0071, 0x059F0083, 0x05A20078, 0x05A300A7, 0x05A40078, 
-        0x05A508A7, 0x05A60083, 0x05A70078, 0x05AB00A7, 0x05AC0078, 0x05AE0871, 0x05AF0071, 0x05B10078, 
-        0x05B3017E, 0x05B4017F, 0x05B50180, 0x05B60181, 0x05B70182, 0x05B80071, 0x05B90078, 0x05C10071, 
-        0x05C50078, 0x05C70071, 0x05C80078, 0x05C90071, 0x05CB0078, 0x05CC0071, 0x05CD0078, 0x05CF0071, 
-        0x05D00078, 0x05D10071, 0x05D20078, 0x05D40071, 0x05D50078, 0x05D70071, 0x05DD0078, 0x05DF00A7, 
-        0x05E10078, 0x05E300A7, 0x05E40078, 0x05E508A7, 0x05E60083, 0x05E70078, 0x05EB00A7, 0x05EC0078, 
-        0x05F3017E, 0x05F4017F, 0x05F50180, 0x05F60181, 0x05F70182, 0x05F80184, 0x05F90054, 0x05FC0008, 
-        0x05FD0078, 0x060000A7, 0x06020071, 0x06060078, 0x06070071, 0x06080078, 0x06090071, 0x06140078, 
-        0x06150071, 0x061D0078, 0x061F0083, 0x062000A7, 0x06220078, 0x06230083, 0x06240078, 0x06250083, 
-        0x06270078, 0x062A0083, 0x062B0078, 0x06300071, 0x06310078, 0x0633017E, 0x0634017F, 0x06350180, 
-        0x06360181, 0x06370182, 0x06380078, 0x064100A7, 0x06420071, 0x06460078, 0x06470071, 0x06480078, 
-        0x06490071, 0x06540078, 0x06550071, 0x065D0078, 0x065E0071, 0x065F00B2, 0x066000A7, 0x06620078, 
-        0x066308A7, 0x06640078, 0x066508A7, 0x06660083, 0x06670078, 0x066A00A7, 0x066B0078, 0x06700071, 
-        0x06710078, 0x0673017E, 0x0674017F, 0x06750180, 0x06760181, 0x06770182, 0x06780078, 0x068100A7, 
-        0x06820071, 0x06860078, 0x06870071, 0x06880078, 0x06890071, 0x06940078, 0x06950071, 0x069D0078, 
-        0x069F00A7, 0x06A00083, 0x06A20078, 0x06A300A7, 0x06A40078, 0x06A508A7, 0x06A60083, 0x06A70078, 
-        0x06AB00A7, 0x06AC0078, 0x06B00071, 0x06B10078, 0x06B3017E, 0x06B4017F, 0x06B50180, 0x06B60181, 
-        0x06B70182, 0x06B80078, 0x06C100A7, 0x06C20071, 0x06CB0078, 0x06CD0071, 0x06DF0078, 0x06E00071, 
-        0x06E30078, 0x06E700A7, 0x06E90083, 0x06EA0078, 0x06EC00A7, 0x06EE08A7, 0x06EF00A7, 0x06F00078, 
-        0x06F900A7, 0x06FA0078, 0x07000071, 0x07180083, 0x07191071, 0x071A0083, 0x071D0078, 0x071F0008, 
-        0x07200071, 0x07230083, 0x07270097, 0x0728017E, 0x0729017F, 0x072A0180, 0x072B0181, 0x072C0182, 
-        0x072D0097, 0x072E0078, 0x07400071, 0x07410078, 0x07430071, 0x07440078, 0x07460071, 0x07470078, 
-        0x074A0071, 0x07540078, 0x07550071, 0x07580083, 0x07591071, 0x075A0083, 0x075E0071, 0x075F0078, 
-        0x07600071, 0x07620078, 0x07640083, 0x07670078, 0x0768017E, 0x0769017F, 0x076A0180, 0x076B0181, 
-        0x076C0182, 0x076D0078, 0x076E1071, 0x076F0078, 0x07800094, 0x07820097, 0x07890094, 0x078C0083, 
-        0x078D0094, 0x0790017E, 0x0791017F, 0x07920180, 0x07930181, 0x07940182, 0x079500B3, 0x079A0083, 
-        0x079D00BF, 0x079F00A7, 0x07A00071, 0x07A10871, 0x07A20071, 0x07A60871, 0x07A70071, 0x07AB0871, 
-        0x07AC0071, 0x07B40871, 0x07B50078, 0x07B80083, 0x07B90883, 0x07BB1083, 0x07BD0083, 0x07BF00A7, 
-        0x07C00883, 0x07C10083, 0x07C20097, 0x07C30083, 0x07C40071, 0x07C60078, 0x07C80083, 0x07C90883, 
-        0x07CA0083, 0x07CE0883, 0x07CF0083, 0x07D30883, 0x07D40083, 0x07DC0883, 0x07DD0083, 0x07DE0078, 
-        0x07DF0094, 0x07E60078, 0x07E70094, 0x07E80097, 0x07E90078, 0x08000071, 0x08150078, 0x08160083, 
-        0x081800A7, 0x08190078, 0x081B0083, 0x081D0078, 0x0820017E, 0x0821017F, 0x08220180, 0x08230181, 
-        0x08240182, 0x08250097, 0x08280071, 0x082B00A7, 0x082C0083, 0x082D0078, 0x085000B5, 0x08630078, 
-        0x08680071, 0x087D0097, 0x087E0078, 0x08800071, 0x08AD0078, 0x08AF0071, 0x08D10078, 0x08D40071, 
-        0x08FD0078, 0x09000071, 0x09240078, 0x09250071, 0x09270078, 0x09280071, 0x092B0078, 0x092D0071, 
-        0x092F0078, 0x09300071, 0x09440078, 0x09450071, 0x09470078, 0x09480071, 0x09580078, 0x09590071, 
-        0x095B0078, 0x095C0071, 0x095F0078, 0x09610071, 0x09630078, 0x09640071, 0x096B0078, 0x096C0071, 
-        0x09880078, 0x09890071, 0x098B0078, 0x098C0071, 0x09AD0078, 0x09AF0083, 0x09B00097, 0x09B400AD, 
-        0x09B500AE, 0x09B6012D, 0x09B7012E, 0x09B8012F, 0x09B90185, 0x09BA0186, 0x09BB0187, 0x09BC0188, 
-        0x09BD0184, 0x09BE0078, 0x09C00071, 0x09C80054, 0x09CD0078, 0x09D00071, 0x09FA0078, 0x0A000071, 
-        0x0B360097, 0x0B370071, 0x0B3B0078, 0x0B400071, 0x0B4D00B4, 0x0B4E0078, 0x0B500071, 0x0B750097, 
-        0x0B770189, 0x0B780078, 0x0B800071, 0x0B860078, 0x0B870071, 0x0B890083, 0x0B8A0078, 0x0B900071, 
-        0x0B990083, 0x0B9A0097, 0x0B9B0078, 0x0BA00071, 0x0BA90083, 0x0BAA0078, 0x0BB00071, 0x0BB60078, 
-        0x0BB70071, 0x0BB80078, 0x0BB90083, 0x0BBA0078, 0x0BC00071, 0x0BDA00C2, 0x0BDB0083, 0x0BDF00A7, 
-        0x0BE40083, 0x0BEA0097, 0x0BEB0081, 0x0BEC0097, 0x0BED0008, 0x0BEE0083, 0x0BEF0078, 0x0BF0017E, 
-        0x0BF1017F, 0x0BF20180, 0x0BF30181, 0x0BF40182, 0x0BF50078, 0x0BF80106, 0x0BF90107, 0x0BFA0108, 
-        0x0BFB0109, 0x0BFC010A, 0x0BFD0078, 0x0C000006, 0x0C050083, 0x0C070078, 0x0C08017E, 0x0C09017F, 
-        0x0C0A0180, 0x0C0B0181, 0x0C0C0182, 0x0C0D0078, 0x0C100071, 0x0C210081, 0x0C220071, 0x0C3C0078, 
-        0x0C400071, 0x0C540083, 0x0C550078, 0x0C800071, 0x0C8E0078, 0x0C900083, 0x0C9100A7, 0x0C930083, 
-        0x0C9400C8, 0x0C960078, 0x0C9800A7, 0x0C9C0083, 0x0C9E0078, 0x0CA20006, 0x0CA3017E, 0x0CA4017F, 
-        0x0CA50180, 0x0CA60181, 0x0CA70182, 0x0CA80071, 0x0CB70078, 0x0CB80071, 0x0CBA0078, 0x0CC00071, 
-        0x0CD50078, 0x0CD800A7, 0x0CE00071, 0x0CE400A7, 0x0CE50078, 0x0CE8017E, 0x0CE9017F, 0x0CEA0180, 
-        0x0CEB0181, 0x0CEC0182, 0x0CED0078, 0x0CEF0006, 0x0CF00054, 0x0D000071, 0x0D0B0083, 0x0D0C00A7, 
-        0x0D0E0078, 0x0D0F0097, 0x0D100078, 0x0E800055, 0x0E967881, 0x0E970081, 0x0E987881, 0x0E9D0081, 
-        0x0E9E7881, 0x0EB17055, 0x0EB50055, 0x0ECD7881, 0x0EE00083, 0x0EE20078, 0x0F000865, 0x0F4B0855, 
-        0x0F4D098A, 0x0F4E0078, 0x0F500865, 0x0F7D0078, 0x0F8008C9, 0x0F8408CA, 0x0F8808C9, 0x0F8B0078, 
-        0x0F8C08CA, 0x0F8F0078, 0x0F9008C9, 0x0F9408CA, 0x0F9808C9, 0x0F9C08CA, 0x0FA008C9, 0x0FA30078, 
-        0x0FA408CA, 0x0FA70078, 0x0FA808C9, 0x0FAC08CA, 0x0FB008C9, 0x0FB408CA, 0x0FB808CB, 0x0FB908CC, 
-        0x0FBB08CD, 0x0FBC08CE, 0x0FBD08CF, 0x0FBE08D0, 0x0FBF0078, 0x0FC008C9, 0x0FC408D1, 0x0FC808C9, 
-        0x0FCC08D1, 0x0FD008C9, 0x0FD408D1, 0x0FD808C9, 0x0FD9098B, 0x0FDA0078, 0x0FDB0855, 0x0FDC08CA, 
-        0x0FDD08D2, 0x0FDE1037, 0x0FE00837, 0x0FE1098B, 0x0FE20078, 0x0FE30855, 0x0FE408D5, 0x0FE60837, 
-        0x0FE808C9, 0x0FE90855, 0x0FEA0078, 0x0FEB0855, 0x0FEC08CA, 0x0FED08D6, 0x0FEE0837, 0x0FF008C9, 
-        0x0FF10855, 0x0FF20890, 0x0FF30855, 0x0FF408CA, 0x0FF508D7, 0x0FF60837, 0x0FF80078, 0x0FF9098B, 
-        0x0FFA0078, 0x0FFB0855, 0x0FFC08D9, 0x0FFD08DA, 0x0FFE0837, 0x0FFF0078, 0x10000805, 0x10011005, 
-        0x10035805, 0x10041005, 0x10050057, 0x1007018C, 0x10085899, 0x10090099, 0x100B1006, 0x100C018D, 
-        0x100D00DB, 0x100E018D, 0x100F00DB, 0x10100006, 0x10121006, 0x10130006, 0x1014018E, 0x1015018F, 
-        0x10160190, 0x10175853, 0x10180007, 0x10191007, 0x101A0006, 0x101B1006, 0x101C0126, 0x101D0006, 
-        0x101F0038, 0x10200006, 0x10220009, 0x10231006, 0x10250006, 0x102B1006, 0x102C0006, 0x102F1005, 
-        0x10300057, 0x10320078, 0x10350057, 0x10387855, 0x10390078, 0x103A7910, 0x103B7911, 0x103C7912, 
-        0x103D780B, 0x103E7809, 0x103F7855, 0x1040705D, 0x1041705B, 0x10427110, 0x10437111, 0x10447112, 
-        0x1045700B, 0x10467009, 0x10470078, 0x10487081, 0x104A0078, 0x10500008, 0x105B0078, 0x10680083, 
-        0x106E0095, 0x10700083, 0x10710095, 0x10720083, 0x10760078, 0x10801054, 0x10831077, 0x10841054, 
-        0x10852877, 0x10872855, 0x10882877, 0x10892855, 0x108A2877, 0x108B0054, 0x108C2877, 0x108F0054, 
-        0x10901054, 0x10910054, 0x10950991, 0x10962877, 0x10972855, 0x10982877, 0x109A1071, 0x109C2855, 
-        0x109D1054, 0x109E2855, 0x109F2877, 0x10A00019, 0x10A22877, 0x10A32855, 0x10A50019, 0x10A60078, 
-        0x10A9305F, 0x10AF3106, 0x10B01192, 0x10B11193, 0x10B21194, 0x10B31195, 0x10B41196, 0x10B51197, 
-        0x10B61198, 0x10B71199, 0x10B8119A, 0x10B9119B, 0x10BA119C, 0x10BB119D, 0x10BC119E, 0x10BD119F, 
-        0x10BE11A0, 0x10BF11A1, 0x10C001A2, 0x10C101A3, 0x10C20078, 0x10C80019, 0x10CA0054, 0x10CD0819, 
-        0x10CE0054, 0x10D10019, 0x10D20054, 0x10E60854, 0x10E70819, 0x10E80054, 0x10FA0019, 0x110000E8, 
-        0x11020019, 0x110408FB, 0x110500FC, 0x11070019, 0x110800E8, 0x11090059, 0x110A01A4, 0x110B0019, 
-        0x110D00E8, 0x11110019, 0x111500E8, 0x111610E8, 0x111800E8, 0x111A0019, 0x111C00E8, 0x111E00FE, 
-        0x111F00E8, 0x112008E8, 0x112101A5, 0x112200E8, 0x112308E8, 0x112500E8, 0x11260019, 0x112900FE, 
-        0x112B0019, 0x112F00E8, 0x11300019, 0x113200FE, 0x11360819, 0x113708FE, 0x113900FE, 0x113A08FE, 
-        0x113B00FE, 0x113C08FE, 0x113D00FE, 0x114008FE, 0x114100FE, 0x114208FE, 0x114300FE, 0x114408FE, 
-        0x114500FE, 0x11460019, 0x114700FD, 0x11490019, 0x115100FE, 0x11520019, 0x115300E8, 0x115401A6, 
-        0x115608E8, 0x115800FE, 0x115C0019, 0x115F00E8, 0x11600019, 0x116400FD, 0x116601A7, 0x11670019, 
-        0x116800FE, 0x11690019, 0x116B00FE, 0x117008FE, 0x117200FE, 0x117508FE, 0x11770019, 0x117800FE, 
-        0x11790102, 0x117A00E8, 0x117B0103, 0x117C00E8, 0x117D0104, 0x117E0105, 0x117F00E8, 0x11800054, 
-        0x118400FE, 0x11860054, 0x119000E8, 0x11910054, 0x11940809, 0x11950054, 0x119B0094, 0x11BD0054, 
-        0x11CA0094, 0x11CB0054, 0x11CD0019, 0x11DA00BF, 0x11DB0054, 0x11EE0078, 0x12000054, 0x12130078, 
-        0x12200054, 0x12250078, 0x123018C4, 0x123118C5, 0x123218C6, 0x123318C7, 0x1234191F, 0x1235191A, 
-        0x1236191B, 0x1237191C, 0x1238191D, 0x1239191E, 0x123A10C4, 0x123B10C5, 0x123C10C6, 0x123D10C7, 
-        0x123E111F, 0x123F111A, 0x1240111B, 0x1241111C, 0x1242111D, 0x1243111E, 0x1244105A, 0x124510E3, 
-        0x124610E4, 0x124710E5, 0x124811A8, 0x124911A9, 0x124A11AA, 0x124B11AB, 0x124C11AC, 0x124D11AD, 
-        0x124E1094, 0x125B1918, 0x12681919, 0x1275010B, 0x1276010C, 0x1277010D, 0x1278010E, 0x1279010F, 
-        0x127A0106, 0x127B0107, 0x127C0108, 0x127D0109, 0x127E010A, 0x127F00C3, 0x12800054, 0x12DB0019, 
-        0x12DC0054, 0x12E00019, 0x12E10054, 0x12FC0019, 0x13000054, 0x13370019, 0x13380054, 0x134E0078, 
-        0x13500054, 0x13590078, 0x13800054, 0x13820078, 0x13830054, 0x13850078, 0x13860054, 0x13A90078, 
-        0x13AC0054, 0x13AF0078, 0x13B00054, 0x13B4000A, 0x13BB00C4, 0x13BC00C5, 0x13BD00C6, 0x13BE00C7, 
-        0x13BF011F, 0x13C000C4, 0x13C100C5, 0x13C200C6, 0x13C300C7, 0x13C4011F, 0x13C500C4, 0x13C600C5, 
-        0x13C700C6, 0x13C800C7, 0x13C9011F, 0x13CA0078, 0x13CC0054, 0x13DF0078, 0x13E00019, 0x13E100FD, 
-        0x13E20009, 0x13E30078, 0x13E80019, 0x13E900E8, 0x13EA00FD, 0x13EB0019, 0x13EE00FD, 0x13EF0019, 
-        0x13F100FE, 0x13F3000A, 0x13F60078, 0x13F80019, 0x14000094, 0x14800019, 0x14C10009, 0x14C601AE, 
-        0x14C701AF, 0x14C80009, 0x14CC0019, 0x14CD00E8, 0x14D80019, 0x14E000FE, 0x14E100E8, 0x14E200FE, 
-        0x14E30019, 0x14E400E8, 0x14E50019, 0x14E700FD, 0x14E90019, 0x14EA00FE, 0x14EB0019, 0x14EC000A, 
-        0x14EE0019, 0x14F000E8, 0x14F30019, 0x14F400E8, 0x14F50019, 0x14FA01B0, 0x14FB00E8, 0x14FC00FE, 
-        0x14FD0019, 0x14FE000A, 0x14FF0019, 0x150500E8, 0x150E0019, 0x150F00E8, 0x15110019, 0x151400E8, 
-        0x151500FD, 0x15170019, 0x151A00FE, 0x151B0019, 0x151E00FE, 0x151F0019, 0x152B00E8, 0x152C0019, 
-        0x153200FE, 0x15330019, 0x153500E8, 0x15380019, 0x153900E8, 0x153A1019, 0x153B0019, 0x153C00FD, 
-        0x153D00E8, 0x153E00FD, 0x154200E8, 0x154500FD, 0x154600E8, 0x154800FD, 0x154E00E8, 0x155000FD, 
-        0x155100E8, 0x15520019, 0x155300FE, 0x155700FD, 0x155800E8, 0x155900FD, 0x155A00E8, 0x155D00FD, 
-        0x156300E8, 0x156600FD, 0x156B0019, 0x157101B1, 0x15730019, 0x157600FE, 0x15770019, 0x157900E8, 
-        0x157A0019, 0x157B00FD, 0x157D00E8, 0x157F0019, 0x15800054, 0x158A0078, 0x16000096, 0x16170078, 
-        0x16180098, 0x162F0078, 0x16400065, 0x16720054, 0x16750078, 0x167C0006, 0x167E005F, 0x167F0006, 
-        0x16800125, 0x16930078, 0x16980071, 0x16B30078, 0x16B77881, 0x16B80078, 0x16C00071, 0x16CB0078, 
-        0x16D00071, 0x16D30078, 0x16D40071, 0x16D70078, 0x16D80071, 0x16DB0078, 0x16DC0071, 0x16DF0078, 
-        0x16E00071, 0x16E30078, 0x16E40071, 0x16E70078, 0x16E80071, 0x16EB0078, 0x16EC0071, 0x16EF0078, 
-        0x17000006, 0x170100E0, 0x17030006, 0x17040126, 0x17050006, 0x170600E0, 0x17070006, 0x170B0099, 
-        0x170C0078, 0x170E00E0, 0x170F0078, 0x17400054, 0x174F1054, 0x17500054, 0x17791054, 0x177A0078, 
-        0x17801054, 0x17EB0078, 0x17F80054, 0x17FE0078, 0x18000006, 0x18020081, 0x180301B2, 0x1804000A, 
-        0x18090054, 0x180A000A, 0x180E00B4, 0x180F00BF, 0x181001B3, 0x181101B4, 0x181201B5, 0x181301B6, 
-        0x181401B7, 0x18150083, 0x18180081, 0x181B0054, 0x181C11B8, 0x181D0081, 0x181E0006, 0x181F0054, 
-        0x18200071, 0x18320871, 0x18350071, 0x18380871, 0x183A0071, 0x183B0871, 0x183D0071, 0x183E0871, 
-        0x183F0071, 0x184B0078, 0x184C0083, 0x184D1037, 0x184E0081, 0x184F8071, 0x18500071, 0x18620871, 
-        0x18650071, 0x18680871, 0x186A0071, 0x186B0871, 0x186D0071, 0x186E0871, 0x186F0071, 0x187B0871, 
-        0x187D0006, 0x187E0081, 0x187F8071, 0x18800078, 0x18820071, 0x18960078, 0x18981071, 0x18C70078, 
-        0x18C80094, 0x18C978B6, 0x18CA78B7, 0x18CB7894, 0x18D00071, 0x18DC0078, 0x18E00054, 0x18E80078, 
-        0x18F80071, 0x19001094, 0x190E1054, 0x190F0078, 0x191010B6, 0x191110B7, 0x191210B8, 0x191310B9, 
-        0x191410B0, 0x19151094, 0x19220078, 0x192819B9, 0x192919BA, 0x192A19BB, 0x192B19BC, 0x192C19BD, 
-        0x192D19BE, 0x192E19BF, 0x192F19C0, 0x19301894, 0x193E1854, 0x193F0094, 0x194018B6, 0x194118B7, 
-        0x194218B8, 0x194318B9, 0x194418B0, 0x19451894, 0x195819C1, 0x195919C2, 0x195A19C3, 0x195B19C4, 
-        0x195C19C5, 0x195D19C6, 0x195E19C7, 0x195F19C8, 0x19601094, 0x19666854, 0x19681894, 0x197F0078, 
-        0x19806894, 0x19AC1094, 0x19B86894, 0x19BB6854, 0x19BD6894, 0x19EF6854, 0x19F01094, 0x19FF6854, 
-        0x1A000071, 0x26DB0078, 0x26E00054, 0x27000071, 0x4FDE0078, 0x50000071, 0x500A0081, 0x500B0071, 
-        0x52460078, 0x52480054, 0x52630078, 0x53800037, 0x538B0078, 0x54000071, 0x54050083, 0x54060071, 
-        0x541100A7, 0x54120083, 0x541300A7, 0x54140054, 0x54160078, 0x56000071, 0x6BD20078, 0x6C00013E, 
-        0x7000013F, 0x7C800871, 0x7D070071, 0x7D0A0871, 0x7D0F0071, 0x7D120871, 0x7D130071, 0x7D150871, 
-        0x7D170078, 0x7D180871, 0x7D350078, 0x7D380871, 0x7D6D0078, 0x7D801055, 0x7D830078, 0x7D891055, 
-        0x7D8C0078, 0x7D8E089B, 0x7D90289B, 0x7D94280B, 0x7D95089B, 0x7D9B0078, 0x7D9C089B, 0x7D9E0078, 
-        0x7DA0089B, 0x7DA20078, 0x7DA3089B, 0x7DA7109B, 0x7DA8209E, 0x7DAA489E, 0x7DAB209E, 0x7DAC489E, 
-        0x7DAD209E, 0x7DAE489E, 0x7DAF209E, 0x7DB0489E, 0x7DB1209E, 0x7DB2489E, 0x7DB3209E, 0x7DB4489E, 
-        0x7DB5209E, 0x7DB6489E, 0x7DB7209E, 0x7DB8489E, 0x7DB9209E, 0x7DBA489E, 0x7DBB209E, 0x7DBC489E, 
-        0x7DBD209E, 0x7DBE489E, 0x7DBF209E, 0x7DC0489E, 0x7DC1209E, 0x7DC8489E, 0x7DC9209E, 0x7DCA489E, 
-        0x7DCB209E, 0x7DCC489E, 0x7DCD209E, 0x7DCE489E, 0x7DCF209E, 0x7DD1489E, 0x7DD2209E, 0x7DD4489E, 
-        0x7DD5209E, 0x7DD6489E, 0x7DD7209E, 0x7DD90078, 0x7DE9409E, 0x7DEA389E, 0x7DEB409E, 0x7DEF209E, 
-        0x7DF3489E, 0x7DF5209E, 0x7DFC409E, 0x7DFD389E, 0x7DFE209E, 0x7DFF489E, 0x7E00409E, 0x7E32209E, 
-        0x7E4B389E, 0x7E6F489E, 0x7E7A409E, 0x7E88209E, 0x7E96389E, 0x7E9A489E, 0x7E9E409E, 0x7E9F00BF, 
-        0x7EA00078, 0x7EA8209E, 0x7EA9389E, 0x7EAD209E, 0x7EAE389E, 0x7EAF209E, 0x7EB0389E, 0x7EB3209E, 
-        0x7EB5389E, 0x7EB7209E, 0x7EB9389E, 0x7EBA209E, 0x7EBB389E, 0x7EBC209E, 0x7EBE389E, 0x7EBF209E, 
-        0x7EC1389E, 0x7EC2209E, 0x7EC4389E, 0x7EC5209E, 0x7EC6389E, 0x7EC80078, 0x7EC9389E, 0x7ECB209E, 
-        0x7ECE389E, 0x7ECF209E, 0x7EDA389E, 0x7EDB209E, 0x7EE1389E, 0x7EE3209E, 0x7EE40078, 0x7EF8409E, 
-        0x7EFE0054, 0x7EFF0078, 0x7F000083, 0x7F088006, 0x7F0B80B4, 0x7F0C8006, 0x7F0D0078, 0x7F100083, 
-        0x7F120078, 0x7F188099, 0x7F198038, 0x7F1A80B4, 0x7F220006, 0x7F2380B4, 0x7F241006, 0x7F261038, 
-        0x7F286006, 0x7F290078, 0x7F2A600C, 0x7F2B6006, 0x7F2C60B4, 0x7F2F6007, 0x7F306006, 0x7F31600D, 
-        0x7F326019, 0x7F330078, 0x7F346008, 0x7F356006, 0x7F360078, 0x7F38489E, 0x7F39009E, 0x7F3A0078, 
-        0x7F3B489E, 0x7F40409E, 0x7F45389E, 0x7F46409E, 0x7F48389E, 0x7F49409E, 0x7F4B389E, 0x7F4C409E, 
-        0x7F4D389E, 0x7F4E409E, 0x7F4F389E, 0x7F50409E, 0x7F51389E, 0x7F52409E, 0x7F53389E, 0x7F54409E, 
-        0x7F59389E, 0x7F5A409E, 0x7F5B389E, 0x7F5C409E, 0x7F5D389E, 0x7F5E409E, 0x7F5F389E, 0x7F60409E, 
-        0x7F61389E, 0x7F62409E, 0x7F63389E, 0x7F64409E, 0x7F65389E, 0x7F66409E, 0x7F67389E, 0x7F68409E, 
-        0x7F69389E, 0x7F6A409E, 0x7F6B389E, 0x7F6C409E, 0x7F6D389E, 0x7F6E409E, 0x7F6F389E, 0x7F70409E, 
-        0x7F71389E, 0x7F72409E, 0x7F73389E, 0x7F74409E, 0x7F75389E, 0x7F76409E, 0x7F79389E, 0x7F7A409E, 
-        0x7F7E0078, 0x7F7F0057, 0x7F808806, 0x7F818807, 0x7F838806, 0x7F84880A, 0x7F85880B, 0x7F86880D, 
-        0x7F87880C, 0x7F88880F, 0x7F898811, 0x7F8A8813, 0x7F8B8815, 0x7F8C8817, 0x7F8D8806, 0x7F8E8819, 
-        0x7F8F8806, 0x7F908860, 0x7F9D8835, 0x7F9E8836, 0x7F9F8838, 0x7FA08861, 0x7FAD8835, 0x7FAE8836, 
-        0x7FAF8809, 0x7FB05006, 0x7FB1500A, 0x7FB25006, 0x7FB35071, 0x7FCF5081, 0x7FD05071, 0x7FDF0078, 
-        0x7FE15071, 0x7FE40078, 0x7FE55071, 0x7FE80078, 0x7FE95071, 0x7FEC0078, 0x7FED5071, 0x7FEE0078, 
-        0x7FF08808, 0x7FF18837, 0x7FF28808, 0x7FF30078, 0x7FF45019, 0x7FF65054, 0x7FF70078, 0x7FFC0141, 
-        0x7FFE0054, 0x7FFF0078, 0x80000071, 0x80130078, 0x80140071, 0x801D0078, 0x801E0071, 0x80270078, 
-        0x80280071, 0x802F0078, 0x80400071, 0x807D0078, 0x80800006, 0x80810078, 0x808300AD, 0x808400AE, 
-        0x8085012D, 0x8086012E, 0x8087012F, 0x80880185, 0x80890186, 0x808A0187, 0x808B0188, 0x808C0184, 
-        0x808D01C9, 0x808E01CA, 0x808F01CB, 0x809001CC, 0x809101CD, 0x809201CE, 0x809301CF, 0x809401D0, 
-        0x809500BE, 0x809601D1, 0x809701D2, 0x809801D3, 0x809901D4, 0x809A0078, 0x809B0094, 0x80A0014E, 
-        0x80A10152, 0x80A20153, 0x80A30157, 0x80A40154, 0x80A50155, 0x80A60156, 0x80A70152, 0x80A80150, 
-        0x80A90153, 0x80AA01D5, 0x80AB0154, 0x80AC014F, 0x80AD0158, 0x80AF0152, 0x80B00154, 0x80B201D6, 
-        0x80B30150, 0x80B501D7, 0x80B60153, 0x80B80156, 0x80B90152, 0x80BA005F, 0x80BC0054, 0x80C50078, 
-        0x81800071, 0x818F0078, 0x8190012D, 0x819100BB, 0x81920078, 0x81980071, 0x81A50078, 0x81C00071, 
-        0x81CF0097, 0x81D00071, 0x81E20078, 0x81E40071, 0x81E8014F, 0x81E90154, 0x81EA0155, 0x81EB0078, 
-        0x8200015B, 0x8214015C, 0x82280071, 0x824F0078, 0x8250017E, 0x8251017F, 0x82520180, 0x82530181, 
-        0x82540182, 0x82550078, 0x8400009B, 0x84030078, 0x8405009B, 0x841C0078, 0x841F009B, 0x84200078, 
-        0x85000083, 0x85030078, 0x85060083, 0x8508009B, 0x851A0078, 0x851C0083, 0x851D0078, 0x851F0083, 
-        0x852001D8, 0x852101D9, 0x852201DA, 0x852301DB, 0x85240078, 0x8528009A, 0x852C0078, 0xE8000094, 
-        0xE87B0078, 0xE8800094, 0xE8930078, 0xE8950094, 0xE8AF0894, 0xE8B200A7, 0xE8B30083, 0xE8B50094, 
-        0xE8B600A7, 0xE8B90057, 0xE8BD0083, 0xE8C10094, 0xE8C20083, 0xE8C60094, 0xE8D50083, 0xE8D70094, 
-        0xE8DD0894, 0xE8E00094, 0xE8EF0078, 0xE9000054, 0xE9210083, 0xE9220054, 0xE9230078, 0xE9800054, 
-        0xE9AB0078, 0xEA002877, 0xEA0D2855, 0xEA1A2877, 0xEA272855, 0xEA2A0078, 0xEA2B2855, 0xEA342877, 
-        0xEA412855, 0xEA4E0078, 0xEA4F2877, 0xEA500078, 0xEA522877, 0xEA530078, 0xEA542877, 0xEA560078, 
-        0xEA572877, 0xEA5B2855, 0xEA682877, 0xEA752855, 0xEA822877, 0xEA850078, 0xEA862877, 0xEA8A0078, 
-        0xEA8B2877, 0xEA8E0078, 0xEA8F2855, 0xEA9C2877, 0xEA9F0078, 0xEAA02877, 0xEAA20078, 0xEAA52877, 
-        0xEAA80078, 0xEAA92855, 0xEAB62877, 0xEAC32855, 0xEAD02877, 0xEADD2855, 0xEAEA2877, 0xEAF72855, 
-        0xEB042877, 0xEB112855, 0xEB1E2877, 0xEB2B2855, 0xEB382877, 0xEB452855, 0xEB530078, 0xEB542877, 
-        0xEB6029DC, 0xEB612855, 0xEB6D29DC, 0xEB6E2855, 0xEB712877, 0xEB7D29DC, 0xEB7E2855, 0xEB8A29DC, 
-        0xEB8B2855, 0xEB8E2877, 0xEB9A29DC, 0xEB9B2855, 0xEBA729DC, 0xEBA82855, 0xEBAB2877, 0xEBB729DC, 
-        0xEBB82855, 0xEBC429DC, 0xEBC52855, 0xEBC82877, 0xEBD429DC, 0xEBD52855, 0xEBE129DC, 0xEBE22855, 
-        0xEBE50078, 0xEBE7280F, 0xEBE82811, 0xEBE92813, 0xEBEA2815, 0xEBEB2817, 0xEBEC280F, 0xEBED2811, 
-        0xEBEE2813, 0xEBEF2815, 0xEBF02817, 0xEBF1280F, 0xEBF22811, 0xEBF32813, 0xEBF42815, 0xEBF52817, 
-        0xEBF6280F, 0xEBF72811, 0xEBF82813, 0xEBF92815, 0xEBFA2817, 0xEBFB280F, 0xEBFC2811, 0xEBFD2813, 
-        0xEBFE2815, 0xEBFF2817, 0xEC000078
-    };
-
-    static const uint32_t a17[] = {
-        0x00000071, 0x536B0078, 0x7C000871, 0x7D0F0078
-    };
-
-    static const uint32_t a23[] = {
-        0x00000057, 0x00010078, 0x00100057, 0x00400078, 0x00800083, 0x00F80078, 0x8000013F, 0xFFFF0078
-    };
-
-    static const uint32_t a24[] = {
-        0x0000013F, 0x7FFF0078
-    };
-
-
-    // The full set of all arrays to be searched.
-    static const Range FULL_DATA[] = {
-        {sizeof(a0)/sizeof(uint32_t), a0},
-        {sizeof(a1)/sizeof(uint32_t), a1},
-        {0, 0},
-        {0, 0},
-        {0, 0},
-        {0, 0},
-        {0, 0},
-        {sizeof(a7)/sizeof(uint32_t), a7},
-        {sizeof(a8)/sizeof(uint32_t), a8},
-        {0, 0},
-        {0, 0},
-        {0, 0},
-        {0, 0},
-        {0, 0},
-        {0, 0},
-        {0, 0},
-        {sizeof(a16)/sizeof(uint32_t), a16},
-        {sizeof(a17)/sizeof(uint32_t), a17},
-        {0, 0},
-        {0, 0},
-        {0, 0},
-        {0, 0},
-        {0, 0},
-        {sizeof(a23)/sizeof(uint32_t), a23},
-        {sizeof(a24)/sizeof(uint32_t), a24},
-        {0, 0},
-        {0, 0},
-        {0, 0},
-        {0, 0},
-        {0, 0},
-        {0, 0},
-        {0, 0}
-    };
-
-    // Array of uppercase differences
-    static const short UCDIFF[] = {
-            0,   -32,   743,   121,    -1,  -232,  -300,    97, 
-          163,   130,    56,    -2,   -79,  -210,  -206,  -205, 
-         -202,  -203,  -207,  -209,  -211,  -213,  -214,  -218, 
-         -217,  -219,   -83,    84,   -38,   -37,   -31,   -64, 
-          -63,   -62,   -57,   -47,   -54,   -86,   -80,     7, 
-          -96,   -48,   -59,     8,    74,    86,   100,   128, 
-          112,   126,     9, -7205,   -16,   -26, -7264,   -40
-    };
-
-    // Array of lowercase differences
-    static const short LCDIFF[] = {
-            0,    32,     1,  -199,  -121,   210,   206,   205, 
-           79,   202,   203,   207,   211,   209,   213,   214, 
-          218,   217,   219,     2,   -97,   -56,  -130,  -163, 
-           83,    38,    37,    64,    63,   -60,    -7,    80, 
-           48,  7264,    -8,   -74,    -9,   -86,  -100,  -112, 
-         -128,  -126, -7517, -8383, -8262,    16,    26,    40
-    };
-
-    // Array of titlecase differences
-    static const short TCDIFF[] = {
-            3,     1,     0,    -1
-    };
-
-    // Array of mirrored character differences
-    static const short MIRROR_DIFF[] = {
-            0,     1,    -1,     2,    -2,    16,   -16,     3, 
-           -3,  2016,   138,  1824,  2104,  2108,  2106,  -138, 
-            8,     7,    -8,    -7, -1824, -2016, -2104, -2106, 
-        -2108
-    };
-
-   // Array of all possible numeric values
-   static const int NUMERICS[] = {
-            -1,      0,      1,      2,      3,      4,      5,      6, 
-             7,      8,      9,     10,     11,     12,     13,     14, 
-            15,     16,     17,     18,     19,     20,     21,     22, 
-            23,     24,     25,     26,     27,     28,     29,     30, 
-            31,     32,     33,     34,     35,     -2,    100,   1000, 
-            40,     50,     60,     70,     80,     90,  10000,    500, 
-          5000,     36,     37,     38,     39,     41,     42,     43, 
-            44,     45,     46,     47,     48,     49,    200,    300, 
-           400,    600,    700,    800,    900,   2000,   3000,   4000, 
-          6000,   7000,   8000,   9000,  20000,  30000,  40000,  50000, 
-         60000,  70000,  80000,  90000
-    };
-
-    // All possible packed data values, no duplicates
-    static const uint32_t PACKED_DATA[] = {
-        0x00000000, 0x0000012F, 0x0000016F, 0x0000014F, 0x0000018F, 0x0000018C, 0x000001B8, 0x000000B8, 
-        0x000000BA, 0x020005B5, 0x040005B6, 0x00000099, 0x000000F8, 0x00000094, 0x02000069, 0x04000069, 
-        0x06000069, 0x08000069, 0x0A000069, 0x0C000069, 0x0E000069, 0x10000069, 0x12000069, 0x14000069, 
-        0x060005B9, 0x000001B9, 0x080005B9, 0x16020001, 0x18020001, 0x1A020001, 0x1C020001, 0x1E020001, 
-        0x20020001, 0x22020001, 0x24020001, 0x26020001, 0x28020001, 0x2A020001, 0x2C020001, 0x2E020001, 
-        0x30020001, 0x32020001, 0x34020001, 0x36020001, 0x38020001, 0x3A020001, 0x3C020001, 0x3E020001, 
-        0x40020001, 0x42020001, 0x44020001, 0x46020001, 0x48020001, 0x060005B5, 0x080005B6, 0x000001BB, 
-        0x000001B7, 0x16000802, 0x18000802, 0x1A000802, 0x1C000802, 0x1E000802, 0x20000802, 0x22000802, 
-        0x24000802, 0x26000802, 0x28000802, 0x2A000802, 0x2C000802, 0x2E000802, 0x30000802, 0x32000802, 
-        0x34000802, 0x36000802, 0x38000802, 0x3A000802, 0x3C000802, 0x3E000802, 0x40000802, 0x42000802, 
-        0x44000802, 0x46000802, 0x48000802, 0x000000EC, 0x000001BC, 0x00000002, 0x0A0005BD, 0x00000130, 
-        0x000000BC, 0x000000B9, 0x0600006B, 0x0800006B, 0x00001002, 0x0400006B, 0x0C0005BE, 0x4A0001AB, 
-        0x00020001, 0x00000802, 0x00001802, 0x00040001, 0x00060001, 0x00002002, 0x00080001, 0x000C0001, 
-        0x000E0001, 0x00100001, 0x00140001, 0x00160001, 0x00180001, 0x00004002, 0x00004802, 0x00200001, 
-        0x00220001, 0x00000005, 0x00A60001, 0x01805802, 0x01042003, 0x00280001, 0x002C0001, 0x00000001, 
-        0x00000000, 0x00007002, 0x00007802, 0x00009802, 0x0000A802, 0x0000B802, 0x0000C002, 0x0000C802, 
-        0x0000D002, 0x00000004, 0x000001A4, 0x00000106, 0x00320001, 0x00340001, 0x00360001, 0x00380001, 
-        0x0000E002, 0x0000E802, 0x0000F002, 0x0000F802, 0x00010002, 0x00010802, 0x00012002, 0x00012802, 
-        0x00013802, 0x003A0001, 0x003E0001, 0x00013002, 0x0000001C, 0x00000107, 0x00400001, 0x00000018, 
-        0x00014802, 0x000001B4, 0x00000038, 0x00000025, 0x00000050, 0x00000058, 0x00000045, 0x00000044, 
-        0x020000C9, 0x060000C9, 0x0A0000C9, 0x0E0000C9, 0x120000C9, 0x000000D8, 0x0000005C, 0x00000008, 
-        0x02000009, 0x06000009, 0x0A000009, 0x0E000009, 0x12000009, 0x0400000B, 0x0800000B, 0x0000000B, 
-        0x1600000B, 0x4E00000B, 0x00000006, 0x4A00000B, 0x000001B5, 0x00420001, 0x0600000B, 0x0A00000B, 
-        0x0E00000B, 0x1200000B, 0x3E00000B, 0x5200000B, 0x5600000B, 0x5A00000B, 0x5C00000B, 0x000001B6, 
-        0x2400000A, 0x2800000A, 0x00000010, 0x020001AB, 0x060001AB, 0x0A0001AB, 0x0E0001AB, 0x120001AB, 
-        0x00000108, 0x00015802, 0x00440001, 0x00016002, 0x00016802, 0x00017002, 0x00017802, 0x00018002, 
-        0x00018802, 0x00440003, 0x00460001, 0x00480003, 0x00019802, 0x004A0001, 0x004C0001, 0x004E0001, 
-        0x003C0001, 0x00500001, 0x00520001, 0x000001BD, 0x0000018D, 0x000001D0, 0x00000250, 0x00000230, 
-        0x040005BE, 0x000000F9, 0x0200006B, 0x0A00006B, 0x0E00006B, 0x1200006B, 0x00540001, 0x00560001, 
-        0x000005B9, 0x045A000A, 0x085A000A, 0x0C5A000A, 0x105A000A, 0x145A000A, 0x185A000A, 0x525A000A, 
-        0x5E5A000A, 0x0401A00A, 0x0801A00A, 0x0C01A00A, 0x1001A00A, 0x1401A00A, 0x1801A00A, 0x5201A00A, 
-        0x5E01A00A, 0x4E00000A, 0x5C00000A, 0x0E0005B9, 0x100005B9, 0x020005B9, 0x040005B9, 0x160005B9, 
-        0x180005B9, 0x1A0005B9, 0x200005B9, 0x220005B9, 0x240005B9, 0x260005B9, 0x040001AB, 0x080001AB, 
-        0x0C0001AB, 0x100001AB, 0x140001AB, 0x180001AB, 0x1C0001AB, 0x200001AB, 0x240001AB, 0x280001AB, 
-        0x0C00006B, 0x1000006B, 0x1400006B, 0x1800006B, 0x1C00006B, 0x2000006B, 0x2400006B, 0x2800006B, 
-        0x005C001C, 0x0001A81C, 0x1A0001AB, 0x1E0001AB, 0x220001AB, 0x260001AB, 0x2A0001AB, 0x160001AB, 
-        0x020005B6, 0x100005B6, 0x280005B9, 0x2C0005B9, 0x300005B9, 0x0001B002, 0x020005BD, 0x0600000A, 
-        0x0A00000A, 0x0E00000A, 0x1200000A, 0x1600000A, 0x3E00000A, 0x0C00000B, 0x1000000B, 0x1400000B, 
-        0x2E0001AB, 0x320001AB, 0x360001AB, 0x3A0001AB, 0x3E0001AB, 0x420001AB, 0x460001AB, 0x640001AB, 
-        0x680001AB, 0x6A0001AB, 0x6E0001AB, 0x720001AB, 0x760001AB, 0x7A0001AB, 0x00000013, 0x00000012, 
-        0x0000005A, 0x000001B0, 0x7C00000B, 0x8000000B, 0x8200000B, 0x8600000B, 0x8C00000B, 0x6000000B, 
-        0x9200000B, 0x9600000B, 0x9800000B, 0x9C00000B, 0xA000000B, 0xA400000B, 0x4A0001AA, 0x040001AA, 
-        0x520001AA, 0x600001AA, 0x0C0001AA, 0x5E0001AA, 0x160001AA, 0x4C0001AA, 0x4E0001AA, 0x9E0001AA, 
-        0x060001AA, 0x8800000A, 0x2A0001AA, 0x005E0001, 0x0001B802, 0x0400002B, 0x0800002B, 0x1600002B, 
-        0x4C00002B, 0x00002802, 0x00003002, 0x000A0001, 0x00120001, 0x00003802, 0x001A0001, 0x001C0001, 
-        0x001E0001, 0x00240001, 0x00005002, 0x00006002, 0x002A0001, 0x002E0001, 0x00300001, 0x00006802, 
-        0x00008002, 0x00008802, 0x00009002, 0x0000A002, 0x0000B002, 0x0000D906, 0x00011002, 0x00011802, 
-        0x00014002, 0x040000C9, 0x080000C9, 0x0C0000C9, 0x100000C9, 0x140000C9, 0x04000009, 0x08000009, 
-        0x0C000009, 0x10000009, 0x14000009, 0x2200000B, 0x4C00000B, 0x2A00000B, 0x5000000B, 0x5400000B, 
-        0x5800000B, 0x2600000A, 0x00015002, 0x00019002, 0x00000030, 0x000001BE, 0x0000014E, 0x00000210, 
-        0x000001F0, 0x00580001, 0x065A000A, 0x0A5A000A, 0x0E5A000A, 0x125A000A, 0x165A000A, 0x1A5A000A, 
-        0x4C5A000A, 0x4E5A000A, 0x0601A00A, 0x0A01A00A, 0x0E01A00A, 0x1201A00A, 0x1601A00A, 0x1A01A00A, 
-        0x4C01A00A, 0x4E01A00A, 0x6000000A, 0x0000000A, 0x120005B9, 0x140005B9, 0x1C0005B9, 0x1E0005B9, 
-        0x1600006B, 0x1A00006B, 0x1E00006B, 0x2200006B, 0x2600006B, 0x2A00006B, 0x0E0005B5, 0x040005B5, 
-        0x2A0005B9, 0x2E0005B9, 0x0200000A, 0x0400000A, 0x0800000A, 0x0C00000A, 0x1000000A, 0x1400000A, 
-        0x2A00000A, 0x2C0001AB, 0x300001AB, 0x340001AB, 0x380001AB, 0x3C0001AB, 0x400001AB, 0x440001AB, 
-        0x480001AB, 0x620001AB, 0x660001AB, 0x500001AB, 0x6C0001AB, 0x700001AB, 0x740001AB, 0x780001AB, 
-        0x520001AB, 0x7E00000B, 0x5E00000B, 0x8400000B, 0x8800000B, 0x8A00000B, 0x8E00000B, 0x9000000B, 
-        0x9400000B, 0x9A00000B, 0x9E00000B, 0xA200000B, 0xA600000B, 0x5C0001AA, 0x3E0001AA, 0x7E0001AA, 
-        0x0600002B, 0x0A00002B, 0x2A00002B, 0x4E00002B, 0x00000019
-    };
-}
diff --git a/libs/utils/Unicode.cpp b/libs/utils/Unicode.cpp
deleted file mode 100644
index f92703e..0000000
--- a/libs/utils/Unicode.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#include <utils/AndroidUnicode.h>
-#include "CharacterData.h"
-
-#define LOG_TAG "Unicode"
-#include <utils/Log.h>
-
-// ICU headers for using macros
-#include <unicode/utf16.h>
-
-#define MIN_RADIX 2
-#define MAX_RADIX 36
-
-#define TYPE_SHIFT 0
-#define TYPE_MASK ((1<<5)-1)
-
-#define DIRECTION_SHIFT (TYPE_SHIFT+5)
-#define DIRECTION_MASK ((1<<5)-1)
-
-#define MIRRORED_SHIFT (DIRECTION_SHIFT+5)
-#define MIRRORED_MASK ((1<<1)-1)
-
-#define TOUPPER_SHIFT (MIRRORED_SHIFT+1)
-#define TOUPPER_MASK ((1<<6)-1)
-
-#define TOLOWER_SHIFT (TOUPPER_SHIFT+6)
-#define TOLOWER_MASK ((1<<6)-1)
-
-#define TOTITLE_SHIFT (TOLOWER_SHIFT+6)
-#define TOTITLE_MASK ((1<<2)-1)
-
-#define MIRROR_SHIFT (TOTITLE_SHIFT+2)
-#define MIRROR_MASK ((1<<5)-1)
-
-#define NUMERIC_SHIFT (TOTITLE_SHIFT+2)
-#define NUMERIC_MASK ((1<<7)-1)
-
-#define DECOMPOSITION_SHIFT (11)
-#define DECOMPOSITION_MASK ((1<<5)-1)
-
-/*
- * Returns the value stored in the CharacterData tables that contains
- * an index into the packed data table and the decomposition type.
- */
-static uint16_t findCharacterValue(UChar32 c)
-{
-    LOG_ASSERT(c >= 0 && c <= 0x10FFFF, "findCharacterValue received an invalid codepoint");
-    if (c < 256)
-        return CharacterData::LATIN1_DATA[c];
-
-    // Rotate the bits because the tables are separated into even and odd codepoints
-    c = (c >> 1) | ((c & 1) << 20);
-
-    CharacterData::Range search = CharacterData::FULL_DATA[c >> 16];
-    const uint32_t* array = search.array;
- 
-    // This trick is so that that compare in the while loop does not
-    // need to shift the array entry down by 16
-    c <<= 16;
-    c |= 0xFFFF;
-
-    int high = (int)search.length - 1;
-    int low = 0;
-
-    if (high < 0)
-        return 0;
-    
-    while (low < high - 1)
-    {
-        int probe = (high + low) >> 1;
-
-        // The entries contain the codepoint in the high 16 bits and the index
-        // into PACKED_DATA in the low 16.
-        if (array[probe] > (unsigned)c)
-            high = probe;
-        else
-            low = probe;
-    }
-
-    LOG_ASSERT((array[low] <= (unsigned)c), "A suitable range was not found");
-    return array[low] & 0xFFFF;
-}
-
-uint32_t android::Unicode::getPackedData(UChar32 c)
-{
-    // findCharacterValue returns a 16-bit value with the top 5 bits containing a decomposition type
-    // and the remaining bits containing an index.
-    return CharacterData::PACKED_DATA[findCharacterValue(c) & 0x7FF];
-}
-
-android::Unicode::CharType android::Unicode::getType(UChar32 c)
-{
-    if (c < 0 || c >= 0x10FFFF)
-        return CHARTYPE_UNASSIGNED;
-    return (CharType)((getPackedData(c) >> TYPE_SHIFT) & TYPE_MASK);
-}
-
-android::Unicode::DecompositionType android::Unicode::getDecompositionType(UChar32 c)
-{
-    // findCharacterValue returns a 16-bit value with the top 5 bits containing a decomposition type
-    // and the remaining bits containing an index.
-    return (DecompositionType)((findCharacterValue(c) >> DECOMPOSITION_SHIFT) & DECOMPOSITION_MASK);
-}
-
-int android::Unicode::getDigitValue(UChar32 c, int radix)
-{
-    if (radix < MIN_RADIX || radix > MAX_RADIX)
-        return -1;
-
-    int tempValue = radix;
-    
-    if (c >= '0' && c <= '9')
-        tempValue = c - '0';
-    else if (c >= 'a' && c <= 'z')
-        tempValue = c - 'a' + 10;
-    else if (c >= 'A' && c <= 'Z')
-        tempValue = c - 'A' + 10;
-    
-    return tempValue < radix ? tempValue : -1;
-}
-
-int android::Unicode::getNumericValue(UChar32 c)
-{
-    if (isMirrored(c))
-        return -1;
-    
-    return (int) CharacterData::NUMERICS[((getPackedData(c) >> NUMERIC_SHIFT) & NUMERIC_MASK)];
-}
-
-UChar32 android::Unicode::toLower(UChar32 c)
-{
-    return c + CharacterData::LCDIFF[(getPackedData(c) >> TOLOWER_SHIFT) & TOLOWER_MASK];
-}
-
-UChar32 android::Unicode::toUpper(UChar32 c)
-{
-    return c + CharacterData::UCDIFF[(getPackedData(c) >> TOUPPER_SHIFT) & TOUPPER_MASK];
-}
-
-android::Unicode::Direction android::Unicode::getDirectionality(UChar32 c)
-{
-    uint32_t data = getPackedData(c);
-
-    if (0 == data)
-        return DIRECTIONALITY_UNDEFINED;
-
-    Direction d = (Direction) ((data >> DIRECTION_SHIFT) & DIRECTION_MASK);
-
-    if (DIRECTION_MASK == d)
-        return DIRECTIONALITY_UNDEFINED;
-    
-    return d;
-}
-
-bool android::Unicode::isMirrored(UChar32 c)
-{
-    return ((getPackedData(c) >> MIRRORED_SHIFT) & MIRRORED_MASK) != 0;
-}
-
-UChar32 android::Unicode::toMirror(UChar32 c)
-{
-    if (!isMirrored(c))
-        return c;
-
-    return c + CharacterData::MIRROR_DIFF[(getPackedData(c) >> MIRROR_SHIFT) & MIRROR_MASK];
-}
-
-UChar32 android::Unicode::toTitle(UChar32 c)
-{
-    int32_t diff = CharacterData::TCDIFF[(getPackedData(c) >> TOTITLE_SHIFT) & TOTITLE_MASK];
-
-    if (TOTITLE_MASK == diff)
-        return toUpper(c);
-    
-    return c + diff;
-}
-
-
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 628cb6b7..8c24ee1 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -22,7 +22,6 @@
 import android.location.IGeocodeProvider;
 import android.location.IGpsStatusListener;
 import android.location.ILocationListener;
-import android.location.ILocationProvider;
 import android.location.Location;
 import android.os.Bundle;
 
diff --git a/location/java/android/location/ILocationProvider.aidl b/location/java/android/location/ILocationProvider.aidl
index 9fe6ab4..5529b11 100644
--- a/location/java/android/location/ILocationProvider.aidl
+++ b/location/java/android/location/ILocationProvider.aidl
@@ -21,7 +21,7 @@
 import android.os.Bundle;
 
 /**
- * Binder interface for location providers.
+ * Binder interface for services that implement location providers.
  *
  * {@hide}
  */
diff --git a/location/java/android/location/LocationProviderInterface.java b/location/java/android/location/LocationProviderInterface.java
new file mode 100644
index 0000000..98beffe
--- /dev/null
+++ b/location/java/android/location/LocationProviderInterface.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location;
+
+import android.location.Location;
+import android.net.NetworkInfo;
+import android.os.Bundle;
+
+/**
+ * Location Manager's interface for location providers.
+ *
+ * {@hide}
+ */
+public interface LocationProviderInterface {
+    String getName();
+    boolean requiresNetwork();
+    boolean requiresSatellite();
+    boolean requiresCell();
+    boolean hasMonetaryCost();
+    boolean supportsAltitude();
+    boolean supportsSpeed();
+    boolean supportsBearing();
+    int getPowerRequirement();
+    int getAccuracy();
+    boolean isEnabled();
+    void enable();
+    void disable();
+    int getStatus(Bundle extras);
+    long getStatusUpdateTime();
+    void enableLocationTracking(boolean enable);
+    void setMinTime(long minTime);
+    void updateNetworkState(int state, NetworkInfo info);
+    void updateLocation(Location location);
+    boolean sendExtraCommand(String command, Bundle extras);
+    void addListener(int uid);
+    void removeListener(int uid);
+}
diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java
index 8b5f702..dce3b27 100755
--- a/location/java/com/android/internal/location/GpsLocationProvider.java
+++ b/location/java/com/android/internal/location/GpsLocationProvider.java
@@ -26,11 +26,11 @@
 import android.location.IGpsStatusListener;
 import android.location.IGpsStatusProvider;
 import android.location.ILocationManager;
-import android.location.ILocationProvider;
 import android.location.INetInitiatedListener;
 import android.location.Location;
 import android.location.LocationManager;
 import android.location.LocationProvider;
+import android.location.LocationProviderInterface;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.net.SntpClient;
@@ -65,7 +65,7 @@
  *
  * {@hide}
  */
-public class GpsLocationProvider extends ILocationProvider.Stub {
+public class GpsLocationProvider implements LocationProviderInterface {
 
     private static final String TAG = "GpsLocationProvider";
 
@@ -374,6 +374,13 @@
     }
 
     /**
+     * Returns the name of this provider.
+     */
+    public String getName() {
+        return LocationManager.GPS_PROVIDER;
+    }
+
+    /**
      * Returns true if the provider requires access to a
      * data network (e.g., the Internet), false otherwise.
      */
@@ -576,6 +583,10 @@
         }
     }
 
+    public boolean isEnabled() {
+        return mEnabled;
+    }
+
     public int getStatus(Bundle extras) {
         if (extras != null) {
             extras.putInt("satellites", mSvCount);
diff --git a/location/java/com/android/internal/location/LocationProviderProxy.java b/location/java/com/android/internal/location/LocationProviderProxy.java
index 361104f..abb90b7 100644
--- a/location/java/com/android/internal/location/LocationProviderProxy.java
+++ b/location/java/com/android/internal/location/LocationProviderProxy.java
@@ -22,6 +22,7 @@
 import android.content.ServiceConnection;
 import android.location.ILocationProvider;
 import android.location.Location;
+import android.location.LocationProviderInterface;
 import android.net.NetworkInfo;
 import android.os.Bundle;
 import android.os.Handler;
@@ -31,18 +32,17 @@
 import android.util.Log;
 
 /**
- * A class for proxying ILocationProvider implementations.
+ * A class for proxying location providers implemented as services.
  *
  * {@hide}
  */
-public class LocationProviderProxy {
+public class LocationProviderProxy implements LocationProviderInterface {
 
     private static final String TAG = "LocationProviderProxy";
 
     private final Context mContext;
     private final String mName;
     private ILocationProvider mProvider;
-    private Intent mIntent;
     private Handler mHandler;
     private final Connection mServiceConnection = new Connection();
 
@@ -56,21 +56,13 @@
     // for caching requiresNetwork, requiresSatellite, etc.
     private DummyLocationProvider mCachedAttributes;
 
-    // constructor for proxying built-in location providers
-    public LocationProviderProxy(Context context, String name, ILocationProvider provider) {
-        mContext = context;
-        mName = name;
-        mProvider = provider;
-    }
-
     // constructor for proxying location providers implemented in a separate service
     public LocationProviderProxy(Context context, String name, String serviceName,
             Handler handler) {
         mContext = context;
         mName = name;
-        mIntent = new Intent(serviceName);
         mHandler = handler;
-        mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
+        mContext.bindService(new Intent(serviceName), mServiceConnection, Context.BIND_AUTO_CREATE);
     }
 
     private class Connection implements ServiceConnection {
diff --git a/location/java/com/android/internal/location/MockProvider.java b/location/java/com/android/internal/location/MockProvider.java
index 7d9e86c..2f6fdee 100644
--- a/location/java/com/android/internal/location/MockProvider.java
+++ b/location/java/com/android/internal/location/MockProvider.java
@@ -17,9 +17,9 @@
 package com.android.internal.location;
 
 import android.location.ILocationManager;
-import android.location.ILocationProvider;
 import android.location.Location;
 import android.location.LocationProvider;
+import android.location.LocationProviderInterface;
 import android.net.NetworkInfo;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -33,7 +33,7 @@
  *
  * {@hide}
  */
-public class MockProvider extends ILocationProvider.Stub {
+public class MockProvider implements LocationProviderInterface {
     private final String mName;
     private final ILocationManager mLocationManager;
     private final boolean mRequiresNetwork;
@@ -73,6 +73,10 @@
         mLocation = new Location(name);
     }
 
+    public String getName() {
+        return mName;
+    }
+
     public void disable() {
         mEnabled = false;
     }
@@ -81,6 +85,10 @@
         mEnabled = true;
     }
 
+    public boolean isEnabled() {
+        return mEnabled;
+    }
+
     public int getStatus(Bundle extras) {
         if (mHasStatus) {
             extras.clear();
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 171881f..70c27c2 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -751,6 +751,8 @@
      */
     public boolean isWiredHeadsetOn() {
         if (AudioSystem.getDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADSET,"")
+                == AudioSystem.DEVICE_STATE_UNAVAILABLE &&
+            AudioSystem.getDeviceConnectionState(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE,"")
                 == AudioSystem.DEVICE_STATE_UNAVAILABLE) {
             return false;
         } else {
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 04f8b5d..681751b 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -21,10 +21,10 @@
 import android.content.res.AssetFileDescriptor;
 import android.graphics.Bitmap;
 import android.net.Uri;
-import android.os.ParcelFileDescriptor;
+
 import java.io.FileDescriptor;
-import java.io.IOException;
 import java.io.FileNotFoundException;
+import java.io.IOException;
 
 /**
  * MediaMetadataRetriever class provides a unified interface for retrieving
@@ -256,5 +256,7 @@
     public static final int METADATA_KEY_VIDEO_WIDTH     = 20;
     public static final int METADATA_KEY_WRITER          = 21;
     public static final int METADATA_KEY_MIMETYPE        = 22;
+    public static final int METADATA_KEY_DISCNUMBER      = 23;
+    public static final int METADATA_KEY_ALBUMARTIST     = 24;
     // Add more here...
 }
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 89ee7d3..e8b89e0 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1064,6 +1064,53 @@
     private native void _reset();
 
     /**
+     * Suspends the MediaPlayer. The only methods that may be called while
+     * suspended are {@link #reset()}, {@link #release()} and {@link #resume()}.
+     * MediaPlayer will release its hardware resources as far as
+     * possible and reasonable. A successfully suspended MediaPlayer will
+     * cease sending events.
+     * If suspension is successful, this method returns true, otherwise
+     * false is returned and the player's state is not affected.
+     * @hide
+     */
+    public boolean suspend() {
+        if (native_suspend_resume(true) < 0) {
+            return false;
+        }
+
+        stayAwake(false);
+
+        // make sure none of the listeners get called anymore
+        mEventHandler.removeCallbacksAndMessages(null);
+
+        return true;
+    }
+
+    /**
+     * Resumes the MediaPlayer. Only to be called after a previous (successful)
+     * call to {@link #suspend()}.
+     * MediaPlayer will return to a state close to what it was in before
+     * suspension.
+     * @hide
+     */
+    public boolean resume() {
+        if (native_suspend_resume(false) < 0) {
+            return false;
+        }
+
+        if (isPlaying()) {
+            stayAwake(true);
+        }
+
+        return true;
+    }
+
+    /**
+     * @hide
+     */
+    private native int native_suspend_resume(boolean isSuspend);
+
+    /**
      * Sets the audio stream type for this MediaPlayer. See {@link AudioManager}
      * for a list of stream types.
      *
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 8c1b0ea..34252ab 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -16,10 +16,14 @@
 
 package android.media;
 
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.IContentProvider;
-import android.content.ContentUris;
 import android.database.Cursor;
 import android.database.SQLException;
 import android.graphics.BitmapFactory;
@@ -42,11 +46,12 @@
 import android.util.Log;
 import android.util.Xml;
 
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -586,6 +591,9 @@
                     }
                     if (genreCode >= 0 && genreCode < ID3_GENRES.length) {
                         value = ID3_GENRES[genreCode];
+                    } else if (genreCode == 255) {
+                        // 255 is defined to be unknown
+                        value = null;
                     }
                 }
                 mGenre = value;
diff --git a/media/java/android/media/ThumbnailUtils.java b/media/java/android/media/ThumbnailUtils.java
index 225d4b6..30d95e3 100644
--- a/media/java/android/media/ThumbnailUtils.java
+++ b/media/java/android/media/ThumbnailUtils.java
@@ -46,41 +46,32 @@
     private static final String TAG = "ThumbnailUtils";
 
     /* Maximum pixels size for created bitmap. */
-    private static final int THUMBNAIL_MAX_NUM_PIXELS = 512 * 384;
-    private static final int MINI_THUMB_MAX_NUM_PIXELS = 128 * 128;
+    private static final int MAX_NUM_PIXELS_THUMBNAIL = 512 * 384;
+    private static final int MAX_NUM_PIXELS_MICRO_THUMBNAIL = 128 * 128;
     private static final int UNCONSTRAINED = -1;
 
-    /* Whether we should rotate the resulting bitmap. */
-    private static final boolean ROTATE_AS_NEEDED = true;
-    private static final boolean NO_ROTATE = false;
-
-    /* Whether we should create bitmap in native memory. */
-    private static final boolean USE_NATIVE = true;
-    private static final boolean NO_NATIVE = false;
+    /* Options used internally. */
+    private static final int OPTIONS_NONE = 0x0;
+    private static final int OPTIONS_DO_NOT_USE_NATIVE = 0x1;
+    private static final int OPTIONS_SCALE_UP = 0x2;
 
     /**
      * Constant used to indicate we should recycle the input in
-     * {@link #extractMiniThumb(Bitmap, int, int, boolean)} unless the output is the input.
+     * {@link #extractThumbnail(Bitmap, int, int, int)} unless the output is the input.
      */
-    public static final boolean RECYCLE_INPUT = true;
-
-    /**
-     * Constant used to indicate we should not recycle the input in
-     * {@link #extractMiniThumb(Bitmap, int, int, boolean)}.
-     */
-    public static final boolean NO_RECYCLE_INPUT = false;
+    public static final int OPTIONS_RECYCLE_INPUT = 0x4;
 
     /**
      * Constant used to indicate the dimension of normal thumbnail in
-     * {@link #extractMiniThumb(Bitmap, int, int, boolean)}.
+     * {@link #extractThumbnail(Bitmap, int, int, int)}.
      */
-    public static final int THUMBNAIL_TARGET_SIZE = 320;
+    public static final int TARGET_SIZE_NORMAL_THUMBNAIL = 320;
 
     /**
-     * Constant used to indicate the dimension of mini thumbnail in
-     * {@link #extractMiniThumb(Bitmap, int, int, boolean)}.
+     * Constant used to indicate the dimension of micro thumbnail in
+     * {@link #extractThumbnail(Bitmap, int, int, int)}.
      */
-    public static final int MINI_THUMB_TARGET_SIZE = 96;
+    public static final int TARGET_SIZE_MICRO_THUMBNAIL = 96;
 
     /**
      * This method first examines if the thumbnail embedded in EXIF is bigger than our target
@@ -97,14 +88,16 @@
      * @param kind either MINI_KIND or MICRO_KIND
      * @param saveMini Whether to save MINI_KIND thumbnail obtained in this method.
      * @return Bitmap
+     *
+     * @hide This method is only used by media framework and media provider internally.
      */
     public static Bitmap createImageThumbnail(ContentResolver cr, String filePath, Uri uri,
             long origId, int kind, boolean saveMini) {
         boolean wantMini = (kind == Images.Thumbnails.MINI_KIND || saveMini);
         int targetSize = wantMini ?
-                THUMBNAIL_TARGET_SIZE : MINI_THUMB_TARGET_SIZE;
+                TARGET_SIZE_NORMAL_THUMBNAIL : TARGET_SIZE_MICRO_THUMBNAIL;
         int maxPixels = wantMini ?
-                THUMBNAIL_MAX_NUM_PIXELS : MINI_THUMB_MAX_NUM_PIXELS;
+                MAX_NUM_PIXELS_THUMBNAIL : MAX_NUM_PIXELS_MICRO_THUMBNAIL;
         SizedThumbnailBitmap sizedThumbnailBitmap = new SizedThumbnailBitmap();
         Bitmap bitmap = null;
         MediaFileType fileType = MediaFile.getFileType(filePath);
@@ -134,16 +127,16 @@
 
         if (kind == Images.Thumbnails.MICRO_KIND) {
             // now we make it a "square thumbnail" for MICRO_KIND thumbnail
-            bitmap = extractMiniThumb(bitmap,
-                    MINI_THUMB_TARGET_SIZE,
-                    MINI_THUMB_TARGET_SIZE, RECYCLE_INPUT);
+            bitmap = extractThumbnail(bitmap,
+                    TARGET_SIZE_MICRO_THUMBNAIL,
+                    TARGET_SIZE_MICRO_THUMBNAIL, OPTIONS_RECYCLE_INPUT);
         }
         return bitmap;
     }
 
     /**
      * Create a video thumbnail for a video. May return null if the video is
-     * corrupt.
+     * corrupt or the format is not supported.
      *
      * @param filePath
      */
@@ -174,10 +167,22 @@
      * @param source original bitmap source
      * @param width targeted width
      * @param height targeted height
-     * @param recycle whether we want to recycle the input
      */
-    public static Bitmap extractMiniThumb(
-            Bitmap source, int width, int height, boolean recycle) {
+    public static Bitmap extractThumbnail(
+            Bitmap source, int width, int height) {
+        return extractThumbnail(source, width, height, OPTIONS_NONE);
+    }
+
+    /**
+     * Creates a centered bitmap of the desired size.
+     *
+     * @param source original bitmap source
+     * @param width targeted width
+     * @param height targeted height
+     * @param options options used during thumbnail extraction
+     */
+    public static Bitmap extractThumbnail(
+            Bitmap source, int width, int height, int options) {
         if (source == null) {
             return null;
         }
@@ -190,8 +195,9 @@
         }
         Matrix matrix = new Matrix();
         matrix.setScale(scale, scale);
-        Bitmap miniThumbnail = transform(matrix, source, width, height, true, recycle);
-        return miniThumbnail;
+        Bitmap thumbnail = transform(matrix, source, width, height,
+                OPTIONS_SCALE_UP | options);
+        return thumbnail;
     }
 
     /*
@@ -272,7 +278,7 @@
     private static Bitmap makeBitmap(int minSideLength, int maxNumOfPixels,
             Uri uri, ContentResolver cr) {
         return makeBitmap(minSideLength, maxNumOfPixels, uri, cr,
-                NO_NATIVE);
+            OPTIONS_DO_NOT_USE_NATIVE);
     }
 
     /**
@@ -281,7 +287,8 @@
      * whether they want the Bitmap be created in native memory.
      */
     private static Bitmap makeBitmap(int minSideLength, int maxNumOfPixels,
-            Uri uri, ContentResolver cr, boolean useNative) {
+            Uri uri, ContentResolver cr, int opt) {
+        boolean useNative = (opt & OPTIONS_DO_NOT_USE_NATIVE) != 0;
         ParcelFileDescriptor input = null;
         try {
             input = cr.openFileDescriptor(uri, "r");
@@ -340,29 +347,6 @@
         return b;
     }
 
-    /**
-     * Rotates the bitmap by the specified degree.
-     * If a new bitmap is created, the original bitmap is recycled.
-     */
-    private static Bitmap rotate(Bitmap b, int degrees) {
-        if (degrees != 0 && b != null) {
-            Matrix m = new Matrix();
-            m.setRotate(degrees,
-                    (float) b.getWidth() / 2, (float) b.getHeight() / 2);
-            try {
-                Bitmap b2 = Bitmap.createBitmap(
-                        b, 0, 0, b.getWidth(), b.getHeight(), m, true);
-                if (b != b2) {
-                    b.recycle();
-                    b = b2;
-                }
-            } catch (OutOfMemoryError ex) {
-                // We have no memory to rotate. Return the original bitmap.
-            }
-        }
-        return b;
-    }
-
     private static void closeSilently(ParcelFileDescriptor c) {
       if (c == null) return;
       try {
@@ -388,8 +372,9 @@
             Bitmap source,
             int targetWidth,
             int targetHeight,
-            boolean scaleUp,
-            boolean recycle) {
+            int options) {
+        boolean scaleUp = (options & OPTIONS_SCALE_UP) != 0;
+        boolean recycle = (options & OPTIONS_RECYCLE_INPUT) != 0;
 
         int deltaX = source.getWidth() - targetWidth;
         int deltaY = source.getHeight() - targetHeight;
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index d83f493..a6a25cd 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -21,7 +21,9 @@
     libmedia \
     libskia \
     libui \
-    libcutils
+    libcutils \
+    libsurfaceflinger_client \
+    libcamera_client
 
 ifneq ($(BUILD_WITHOUT_PV),true)
 
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 76d1674..8ed3730 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -35,7 +35,7 @@
 #include "utils/String8.h"
 #include "android_util_Binder.h"
 #include <binder/Parcel.h>
-
+#include <surfaceflinger/Surface.h>
 
 // ----------------------------------------------------------------------------
 
@@ -692,6 +692,19 @@
     return ret;
 }
 
+static jint
+android_media_MediaPlayer_native_suspend_resume(
+        JNIEnv *env, jobject thiz, jboolean isSuspend) {
+    LOGV("suspend_resume(%d)", isSuspend);
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return UNKNOWN_ERROR;
+    }
+
+    return isSuspend ? mp->suspend() : mp->resume();
+}
+
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gMethods[] = {
@@ -724,6 +737,7 @@
     {"native_setup",        "(Ljava/lang/Object;)V",            (void *)android_media_MediaPlayer_native_setup},
     {"native_finalize",     "()V",                              (void *)android_media_MediaPlayer_native_finalize},
     {"snoop",               "([SI)I",                           (void *)android_media_MediaPlayer_snoop},
+    {"native_suspend_resume", "(Z)I",                           (void *)android_media_MediaPlayer_native_suspend_resume},
 };
 
 static const char* const kClassPathName = "android/media/MediaPlayer";
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index cad65b3..3063f15 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -18,9 +18,9 @@
 #define LOG_TAG "MediaRecorderJNI"
 #include <utils/Log.h>
 
-#include <ui/SurfaceComposerClient.h>
-#include <ui/ICameraService.h>
-#include <ui/Camera.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
+#include <camera/ICameraService.h>
+#include <camera/Camera.h>
 #include <media/mediarecorder.h>
 #include <stdio.h>
 #include <assert.h>
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index c59d323..3adabcc 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -29,7 +29,7 @@
     MediaProfiles.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-	libui libcutils libutils libbinder libsonivox libicuuc libexpat
+	libui libcutils libutils libbinder libsonivox libicuuc libexpat libsurfaceflinger_client libcamera_client
 
 LOCAL_MODULE:= libmedia
 
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index 5d9db10..ed792b3 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -21,7 +21,7 @@
 #include <binder/Parcel.h>
 
 #include <media/IMediaPlayer.h>
-#include <ui/ISurface.h>
+#include <surfaceflinger/ISurface.h>
 
 namespace android {
 
@@ -43,6 +43,8 @@
     INVOKE,
     SET_METADATA_FILTER,
     GET_METADATA,
+    SUSPEND,
+    RESUME,
 };
 
 class BpMediaPlayer: public BpInterface<IMediaPlayer>
@@ -199,6 +201,26 @@
         remote()->transact(GET_METADATA, request, reply);
         return reply->readInt32();
     }
+
+    status_t suspend() {
+        Parcel request;
+        request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+
+        Parcel reply;
+        remote()->transact(SUSPEND, request, &reply);
+
+        return reply.readInt32();
+    }
+
+    status_t resume() {
+        Parcel request;
+        request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+
+        Parcel reply;
+        remote()->transact(RESUME, request, &reply);
+
+        return reply.readInt32();
+    }
 };
 
 IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
@@ -299,6 +321,16 @@
             reply->writeInt32(setMetadataFilter(data));
             return NO_ERROR;
         } break;
+        case SUSPEND: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            reply->writeInt32(suspend());
+            return NO_ERROR;
+        } break;
+        case RESUME: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            reply->writeInt32(resume());
+            return NO_ERROR;
+        } break;
         case GET_METADATA: {
             CHECK_INTERFACE(IMediaPlayer, data, reply);
             const status_t retcode = getMetadata(data.readInt32(), data.readInt32(), reply);
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index df7d301..2bc2a7e 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -19,8 +19,8 @@
 #define LOG_TAG "IMediaRecorder"
 #include <utils/Log.h>
 #include <binder/Parcel.h>
-#include <ui/ISurface.h>
-#include <ui/ICamera.h>
+#include <surfaceflinger/ISurface.h>
+#include <camera/ICamera.h>
 #include <media/IMediaPlayerClient.h>
 #include <media/IMediaRecorder.h>
 
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 0469fd5..01b6737 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -5,8 +5,8 @@
 #include <binder/IMemory.h>
 #include <binder/Parcel.h>
 #include <media/IOMX.h>
-#include <ui/ISurface.h>
-#include <ui/Surface.h>
+#include <surfaceflinger/ISurface.h>
+#include <surfaceflinger/Surface.h>
 
 namespace android {
 
diff --git a/media/libmedia/MediaScannerClient.cpp b/media/libmedia/MediaScannerClient.cpp
index bd3596e..bb3717f 100644
--- a/media/libmedia/MediaScannerClient.cpp
+++ b/media/libmedia/MediaScannerClient.cpp
@@ -64,29 +64,27 @@
 
 bool MediaScannerClient::addStringTag(const char* name, const char* value)
 {
-    if (mLocaleEncoding != kEncodingNone) {
-        // don't bother caching strings that are all ASCII.
-        // call handleStringTag directly instead.
-        // check to see if value (which should be utf8) has any non-ASCII characters
-        bool nonAscii = false;
-        const char* chp = value;
-        char ch;
-        while ((ch = *chp++)) {
-            if (ch & 0x80) {
-                nonAscii = true;
-                break;
-            }
+    // don't bother caching strings that are all ASCII.
+    // call handleStringTag directly instead.
+    // check to see if value (which should be utf8) has any non-ASCII characters
+    bool nonAscii = false;
+    const char* chp = value;
+    char ch;
+    while ((ch = *chp++)) {
+        if (ch & 0x80) {
+            nonAscii = true;
+            break;
         }
-
-        if (nonAscii) {
-            // save the strings for later so they can be used for native encoding detection
-            mNames->push_back(name);
-            mValues->push_back(value);
-            return true;
-        }
-        // else fall through
     }
 
+    if (nonAscii) {
+        // save the strings for later so they can be used for native encoding detection
+        mNames->push_back(name);
+        mValues->push_back(value);
+        return true;
+    }
+    // else fall through
+
     // autodetection is not necessary, so no need to cache the values
     // pass directly to the client instead
     return handleStringTag(name, value);
@@ -198,23 +196,29 @@
 
 void MediaScannerClient::endFile()
 {
-    if (mLocaleEncoding != kEncodingNone) {
-        int size = mNames->size();
-        uint32_t encoding = kEncodingAll;
+    int size = mNames->size();
+    uint32_t encoding = kEncodingAll;
 
-        // compute a bit mask containing all possible encodings
-        for (int i = 0; i < mNames->size(); i++)
-            encoding &= possibleEncodings(mValues->getEntry(i));
+    // compute a bit mask containing all possible encodings
+    for (int i = 0; i < mNames->size(); i++)
+        encoding &= possibleEncodings(mValues->getEntry(i));
 
-        // if the locale encoding matches, then assume we have a native encoding.
-        if (encoding & mLocaleEncoding)
-            convertValues(mLocaleEncoding);
+    // If one of the possible encodings matches the locale encoding, use that.
+    // Otherwise, if there is only one possible encoding, use that.
+    if (encoding & mLocaleEncoding)
+        convertValues(mLocaleEncoding);
+    else if ((encoding & (encoding - 1)) == 0)
+        convertValues(encoding);
+    else {
+        // TODO: try harder to disambiguate the encoding, perhaps by looking at
+        // other files by same artist, or even the user's entire collection.
+        // For now, fall through and insert the strings as they are.
+    }
 
-        // finally, push all name/value pairs to the client
-        for (int i = 0; i < mNames->size(); i++) {
-            if (!handleStringTag(mNames->getEntry(i), mValues->getEntry(i)))
-                break;
-        }
+    // finally, push all name/value pairs to the client
+    for (int i = 0; i < mNames->size(); i++) {
+        if (!handleStringTag(mNames->getEntry(i), mValues->getEntry(i)))
+            break;
     }
     // else addStringTag() has done all the work so we have nothing to do
 
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index cb5ee4b..2157814 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -30,6 +30,8 @@
 #include <media/mediaplayer.h>
 #include <media/AudioTrack.h>
 
+#include <surfaceflinger/Surface.h>
+
 #include <binder/MemoryBase.h>
 
 #include <utils/KeyedVector.h>
@@ -165,6 +167,16 @@
     return INVALID_OPERATION;
 }
 
+status_t MediaPlayer::suspend() {
+    Mutex::Autolock _l(mLock);
+    return mPlayer->suspend();
+}
+
+status_t MediaPlayer::resume() {
+    Mutex::Autolock _l(mLock);
+    return mPlayer->resume();
+}
+
 status_t MediaPlayer::setMetadataFilter(const Parcel& filter)
 {
     LOGD("setMetadataFilter");
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 7b5dabb..23024e9 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -18,7 +18,7 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "MediaRecorder"
 #include <utils/Log.h>
-#include <ui/Surface.h>
+#include <surfaceflinger/Surface.h>
 #include <media/mediarecorder.h>
 #include <binder/IServiceManager.h>
 #include <utils/String8.h>
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index 12872bc..cf97b23 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -13,7 +13,7 @@
     TestPlayerStub.cpp          \
     VorbisPlayer.cpp            \
     VorbisMetadataRetriever.cpp \
-    MidiMetadataRetriever.cpp \
+    MidiMetadataRetriever.cpp 	\
     MidiFile.cpp
 
 ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
@@ -30,17 +30,18 @@
 LOCAL_LDLIBS += -ldl -lpthread
 endif
 
-LOCAL_SHARED_LIBRARIES :=     \
-	libcutils             \
-	libutils              \
-	libbinder             \
-	libvorbisidec         \
-	libsonivox            \
-	libmedia              \
-	libandroid_runtime    \
-	libstagefright        \
-	libstagefright_omx    \
-	libstagefright_color_conversion
+LOCAL_SHARED_LIBRARIES :=     		\
+	libcutils             			\
+	libutils              			\
+	libbinder             			\
+	libvorbisidec         			\
+	libsonivox            			\
+	libmedia              			\
+	libandroid_runtime    			\
+	libstagefright        			\
+	libstagefright_omx    			\
+	libstagefright_color_conversion \
+	libsurfaceflinger_client
 
 ifneq ($(BUILD_WITHOUT_PV),true)
 LOCAL_SHARED_LIBRARIES += \
@@ -54,19 +55,12 @@
 LOCAL_SHARED_LIBRARIES += libdl
 endif
 
-LOCAL_C_INCLUDES :=                                                     \
+LOCAL_C_INCLUDES :=                                                 \
 	$(JNI_H_INCLUDE)                                                \
 	$(call include-path-for, graphics corecg)                       \
 	$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
-	$(TOP)/frameworks/base/media/libstagefright/include
-
-ifeq ($(TARGET_ARCH),arm)
-    LOCAL_C_INCLUDES += \
+	$(TOP)/frameworks/base/media/libstagefright/include             \
         $(TOP)/external/tremolo/Tremolo
-else
-    LOCAL_C_INCLUDES += \
-        $(TOP)/external/tremor/Tremor
-endif
 
 LOCAL_MODULE:= libmediaplayerservice
 
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 8e61011..b4fc035 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -970,6 +970,20 @@
     return OK;
 }
 
+status_t MediaPlayerService::Client::suspend() {
+    sp<MediaPlayerBase> p = getPlayer();
+    if (p == 0) return UNKNOWN_ERROR;
+
+    return p->suspend();
+}
+
+status_t MediaPlayerService::Client::resume() {
+    sp<MediaPlayerBase> p = getPlayer();
+    if (p == 0) return UNKNOWN_ERROR;
+
+    return p->resume();
+}
+
 status_t MediaPlayerService::Client::prepareAsync()
 {
     LOGV("[%d] prepareAsync", mConnId);
@@ -1597,9 +1611,12 @@
     AudioOutput *me = (AudioOutput *)cookie;
     AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
 
-    (*me->mCallback)(
+    size_t actualSize = (*me->mCallback)(
             me, buffer->raw, buffer->size, me->mCallbackCookie);
-    me->snoopWrite(buffer->raw, buffer->size);
+
+    if (actualSize > 0) {
+        me->snoopWrite(buffer->raw, actualSize);
+    }
 }
 
 #undef LOG_TAG
@@ -1629,14 +1646,75 @@
     return NO_ERROR;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+
+struct CallbackThread : public Thread {
+    CallbackThread(const wp<MediaPlayerBase::AudioSink> &sink,
+                   MediaPlayerBase::AudioSink::AudioCallback cb,
+                   void *cookie);
+
+protected:
+    virtual ~CallbackThread();
+
+    virtual bool threadLoop();
+
+private:
+    wp<MediaPlayerBase::AudioSink> mSink;
+    MediaPlayerBase::AudioSink::AudioCallback mCallback;
+    void *mCookie;
+    void *mBuffer;
+    size_t mBufferSize;
+
+    CallbackThread(const CallbackThread &);
+    CallbackThread &operator=(const CallbackThread &);
+};
+
+CallbackThread::CallbackThread(
+        const wp<MediaPlayerBase::AudioSink> &sink,
+        MediaPlayerBase::AudioSink::AudioCallback cb,
+        void *cookie)
+    : mSink(sink),
+      mCallback(cb),
+      mCookie(cookie),
+      mBuffer(NULL),
+      mBufferSize(0) {
+}
+
+CallbackThread::~CallbackThread() {
+    if (mBuffer) {
+        free(mBuffer);
+        mBuffer = NULL;
+    }
+}
+
+bool CallbackThread::threadLoop() {
+    sp<MediaPlayerBase::AudioSink> sink = mSink.promote();
+    if (sink == NULL) {
+        return false;
+    }
+
+    if (mBuffer == NULL) {
+        mBufferSize = sink->bufferSize();
+        mBuffer = malloc(mBufferSize);
+    }
+
+    size_t actualSize =
+        (*mCallback)(sink.get(), mBuffer, mBufferSize, mCookie);
+
+    if (actualSize > 0) {
+        sink->write(mBuffer, actualSize);
+    }
+
+    return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
 status_t MediaPlayerService::AudioCache::open(
         uint32_t sampleRate, int channelCount, int format, int bufferCount,
         AudioCallback cb, void *cookie)
 {
     LOGV("open(%u, %d, %d, %d)", sampleRate, channelCount, format, bufferCount);
-    if (cb != NULL) {
-        return UNKNOWN_ERROR;  // TODO: implement this.
-    }
     if (mHeap->getHeapID() < 0) {
         return NO_INIT;
     }
@@ -1645,9 +1723,25 @@
     mChannelCount = (uint16_t)channelCount;
     mFormat = (uint16_t)format;
     mMsecsPerFrame = 1.e3 / (float) sampleRate;
+
+    if (cb != NULL) {
+        mCallbackThread = new CallbackThread(this, cb, cookie);
+    }
     return NO_ERROR;
 }
 
+void MediaPlayerService::AudioCache::start() {
+    if (mCallbackThread != NULL) {
+        mCallbackThread->run("AudioCache callback");
+    }
+}
+
+void MediaPlayerService::AudioCache::stop() {
+    if (mCallbackThread != NULL) {
+        mCallbackThread->requestExitAndWait();
+    }
+}
+
 ssize_t MediaPlayerService::AudioCache::write(const void* buffer, size_t size)
 {
     LOGV("write(%p, %u)", buffer, size);
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index ffe1ba0..2408c62 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -25,7 +25,6 @@
 #include <utils/KeyedVector.h>
 #include <utils/String8.h>
 #include <utils/Vector.h>
-#include <ui/SurfaceComposerClient.h>
 
 #include <media/IMediaPlayerService.h>
 #include <media/MediaPlayerInterface.h>
@@ -139,9 +138,9 @@
                 int bufferCount = 1,
                 AudioCallback cb = NULL, void *cookie = NULL);
 
-        virtual void            start() {}
+        virtual void            start();
         virtual ssize_t         write(const void* buffer, size_t size);
-        virtual void            stop() {}
+        virtual void            stop();
         virtual void            flush() {}
         virtual void            pause() {}
         virtual void            close() {}
@@ -171,6 +170,8 @@
         uint32_t            mSize;
         int                 mError;
         bool                mCommandComplete;
+
+        sp<Thread>          mCallbackThread;
     };
 
 public:
@@ -221,6 +222,8 @@
         virtual status_t        getMetadata(bool update_only,
                                             bool apply_filter,
                                             Parcel *reply);
+        virtual status_t        suspend();
+        virtual status_t        resume();
 
         sp<MediaPlayerBase>     createPlayer(player_type playerType);
 
diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp
index 1bfcf65..7776b4e 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.cpp
+++ b/media/libmediaplayerservice/StagefrightPlayer.cpp
@@ -136,6 +136,16 @@
     return STAGEFRIGHT_PLAYER;
 }
 
+status_t StagefrightPlayer::suspend() {
+    LOGV("suspend");
+    return mPlayer->suspend();
+}
+
+status_t StagefrightPlayer::resume() {
+    LOGV("resume");
+    return mPlayer->resume();
+}
+
 status_t StagefrightPlayer::invoke(const Parcel &request, Parcel *reply) {
     return INVALID_OPERATION;
 }
diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h
index 9e6674a..4446582 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.h
+++ b/media/libmediaplayerservice/StagefrightPlayer.h
@@ -50,6 +50,8 @@
     virtual player_type playerType();
     virtual status_t invoke(const Parcel &request, Parcel *reply);
     virtual void setAudioSink(const sp<AudioSink> &audioSink);
+    virtual status_t suspend();
+    virtual status_t resume();
 
 private:
     AwesomePlayer *mPlayer;
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 6383f0c..531fd11 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -29,8 +29,8 @@
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/OMXClient.h>
 #include <media/stagefright/OMXCodec.h>
-#include <ui/ICamera.h>
-#include <ui/ISurface.h>
+#include <camera/ICamera.h>
+#include <surfaceflinger/ISurface.h>
 #include <utils/Errors.h>
 
 namespace android {
@@ -185,6 +185,11 @@
             mAudioEncoder == AUDIO_ENCODER_AMR_NB
                 ? MEDIA_MIMETYPE_AUDIO_AMR_NB : MEDIA_MIMETYPE_AUDIO_AMR_WB);
 
+    int32_t maxInputSize;
+    CHECK(audioSource->getFormat()->findInt32(
+                kKeyMaxInputSize, &maxInputSize));
+
+    encMeta->setInt32(kKeyMaxInputSize, maxInputSize);
     encMeta->setInt32(kKeyChannelCount, 1);
     encMeta->setInt32(kKeySampleRate, sampleRate);
 
diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp
index caff452..bf4424b 100644
--- a/media/libstagefright/AMRWriter.cpp
+++ b/media/libstagefright/AMRWriter.cpp
@@ -173,12 +173,15 @@
                 buffer->range_length(),
                 mFile);
 
-        buffer->release();
-        buffer = NULL;
-
         if (n < (ssize_t)buffer->range_length()) {
+            buffer->release();
+            buffer = NULL;
+
             break;
         }
+
+        buffer->release();
+        buffer = NULL;
     }
 
     Mutex::Autolock autoLock(mLock);
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 58eb12e..071bb9e 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -48,15 +48,8 @@
 LOCAL_C_INCLUDES:= \
 	$(JNI_H_INCLUDE) \
         $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
-        $(TOP)/external/opencore/android
-
-ifeq ($(TARGET_ARCH),arm)
-    LOCAL_C_INCLUDES += \
+        $(TOP)/external/opencore/android \
         $(TOP)/external/tremolo/Tremolo
-else
-    LOCAL_C_INCLUDES += \
-        $(TOP)/external/tremor/Tremor
-endif
 
 LOCAL_SHARED_LIBRARIES := \
         libbinder         \
@@ -65,7 +58,9 @@
         libcutils         \
         libui             \
         libsonivox        \
-        libvorbisidec
+        libvorbisidec     \
+        libsurfaceflinger_client \
+        libcamera_client
 
 LOCAL_STATIC_LIBRARIES := \
         libstagefright_aacdec \
@@ -88,6 +83,14 @@
 LOCAL_SHARED_LIBRARIES += \
         libstagefright_color_conversion
 
+ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
+        LOCAL_LDLIBS += -lpthread -ldl
+endif
+
+ifneq ($(TARGET_SIMULATOR),true)
+LOCAL_SHARED_LIBRARIES += libdl
+endif
+
 endif
 
 ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index 4926920..12d7ee2 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -187,12 +187,12 @@
 }
 
 // static
-void AudioPlayer::AudioSinkCallback(
+size_t AudioPlayer::AudioSinkCallback(
         MediaPlayerBase::AudioSink *audioSink,
         void *buffer, size_t size, void *cookie) {
     AudioPlayer *me = (AudioPlayer *)cookie;
 
-    me->fillBuffer(buffer, size);
+    return me->fillBuffer(buffer, size);
 }
 
 void AudioPlayer::AudioCallback(int event, void *info) {
@@ -201,17 +201,18 @@
     }
 
     AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info;
-    fillBuffer(buffer->raw, buffer->size);
+    size_t numBytesWritten = fillBuffer(buffer->raw, buffer->size);
+
+    buffer->size = numBytesWritten;
 }
 
-void AudioPlayer::fillBuffer(void *data, size_t size) {
+size_t AudioPlayer::fillBuffer(void *data, size_t size) {
     if (mNumFramesPlayed == 0) {
         LOGV("AudioCallback");
     }
 
     if (mReachedEOS) {
-        memset(data, 0, size);
-        return;
+        return 0;
     }
 
     size_t size_done = 0;
@@ -244,7 +245,6 @@
 
             if (err != OK) {
                 mReachedEOS = true;
-                memset((char *)data + size_done, 0, size_remaining);
                 break;
             }
 
@@ -285,7 +285,9 @@
     }
 
     Mutex::Autolock autoLock(mLock);
-    mNumFramesPlayed += size / mFrameSize;
+    mNumFramesPlayed += size_done / mFrameSize;
+
+    return size_done;
 }
 
 int64_t AudioPlayer::getRealTimeUs() {
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index c0a2f5b..1c9f4fd 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -18,6 +18,8 @@
 #define LOG_TAG "AwesomePlayer"
 #include <utils/Log.h>
 
+#include <dlfcn.h>
+
 #include "include/AwesomePlayer.h"
 #include "include/Prefetcher.h"
 #include "include/SoftwareRenderer.h"
@@ -34,6 +36,8 @@
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/OMXCodec.h>
 
+#include <surfaceflinger/ISurface.h>
+
 namespace android {
 
 struct AwesomeEvent : public TimedEventQueue::Event {
@@ -80,39 +84,107 @@
 
 struct AwesomeLocalRenderer : public AwesomeRenderer {
     AwesomeLocalRenderer(
+            bool previewOnly,
+            const char *componentName,
             OMX_COLOR_FORMATTYPE colorFormat,
             const sp<ISurface> &surface,
             size_t displayWidth, size_t displayHeight,
             size_t decodedWidth, size_t decodedHeight)
-        : mTarget(new SoftwareRenderer(
-                    colorFormat, surface, displayWidth, displayHeight,
-                    decodedWidth, decodedHeight)) {
+        : mTarget(NULL),
+          mLibHandle(NULL) {
+            init(previewOnly, componentName,
+                 colorFormat, surface, displayWidth,
+                 displayHeight, decodedWidth, decodedHeight);
     }
 
     virtual void render(MediaBuffer *buffer) {
-        mTarget->render(
-                (const uint8_t *)buffer->data() + buffer->range_offset(),
-                buffer->range_length(), NULL);
+        render((const uint8_t *)buffer->data() + buffer->range_offset(),
+               buffer->range_length());
+    }
+
+    void render(const void *data, size_t size) {
+        mTarget->render(data, size, NULL);
     }
 
 protected:
     virtual ~AwesomeLocalRenderer() {
         delete mTarget;
         mTarget = NULL;
+
+        if (mLibHandle) {
+            dlclose(mLibHandle);
+            mLibHandle = NULL;
+        }
     }
 
 private:
-    SoftwareRenderer *mTarget;
+    VideoRenderer *mTarget;
+    void *mLibHandle;
+
+    void init(
+            bool previewOnly,
+            const char *componentName,
+            OMX_COLOR_FORMATTYPE colorFormat,
+            const sp<ISurface> &surface,
+            size_t displayWidth, size_t displayHeight,
+            size_t decodedWidth, size_t decodedHeight);
 
     AwesomeLocalRenderer(const AwesomeLocalRenderer &);
     AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
 };
 
+void AwesomeLocalRenderer::init(
+        bool previewOnly,
+        const char *componentName,
+        OMX_COLOR_FORMATTYPE colorFormat,
+        const sp<ISurface> &surface,
+        size_t displayWidth, size_t displayHeight,
+        size_t decodedWidth, size_t decodedHeight) {
+    if (!previewOnly) {
+        // We will stick to the vanilla software-color-converting renderer
+        // for "previewOnly" mode, to avoid unneccessarily switching overlays
+        // more often than necessary.
+
+        mLibHandle = dlopen("libstagefrighthw.so", RTLD_NOW);
+
+        if (mLibHandle) {
+            typedef VideoRenderer *(*CreateRendererFunc)(
+                    const sp<ISurface> &surface,
+                    const char *componentName,
+                    OMX_COLOR_FORMATTYPE colorFormat,
+                    size_t displayWidth, size_t displayHeight,
+                    size_t decodedWidth, size_t decodedHeight);
+
+            CreateRendererFunc func =
+                (CreateRendererFunc)dlsym(
+                        mLibHandle,
+                        "_Z14createRendererRKN7android2spINS_8ISurfaceEEEPKc20"
+                        "OMX_COLOR_FORMATTYPEjjjj");
+
+            if (func) {
+                mTarget =
+                    (*func)(surface, componentName, colorFormat,
+                        displayWidth, displayHeight,
+                        decodedWidth, decodedHeight);
+            }
+        }
+    }
+
+    if (mTarget == NULL) {
+        mTarget = new SoftwareRenderer(
+                colorFormat, surface, displayWidth, displayHeight,
+                decodedWidth, decodedHeight);
+    }
+}
+
 AwesomePlayer::AwesomePlayer()
     : mTimeSource(NULL),
+      mVideoRendererIsPreview(false),
       mAudioPlayer(NULL),
+      mFlags(0),
       mLastVideoBuffer(NULL),
-      mVideoBuffer(NULL) {
+      mVideoBuffer(NULL),
+      mSuspensionState(NULL) {
     CHECK_EQ(mClient.connect(), OK);
 
     DataSource::RegisterDefaultSniffers();
@@ -164,26 +236,24 @@
 status_t AwesomePlayer::setDataSource(
         const char *uri, const KeyedVector<String8, String8> *headers) {
     Mutex::Autolock autoLock(mLock);
+    return setDataSource_l(uri, headers);
+}
 
+status_t AwesomePlayer::setDataSource_l(
+        const char *uri, const KeyedVector<String8, String8> *headers) {
     reset_l();
 
-    sp<DataSource> dataSource = DataSource::CreateFromURI(uri, headers);
+    mUri = uri;
 
-    if (dataSource == NULL) {
-        return UNKNOWN_ERROR;
+    if (headers) {
+        mUriHeaders = *headers;
     }
 
-    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+    // The actual work will be done during preparation in the call to
+    // ::finishSetDataSource_l to avoid blocking the calling thread in
+    // setDataSource for any significant time.
 
-    if (extractor == NULL) {
-        return UNKNOWN_ERROR;
-    }
-
-    if (dataSource->flags() & DataSource::kWantsPrefetching) {
-        mPrefetcher = new Prefetcher;
-    }
-
-    return setDataSource_l(extractor);
+    return OK;
 }
 
 status_t AwesomePlayer::setDataSource(
@@ -192,15 +262,22 @@
 
     reset_l();
 
-    sp<DataSource> source = new FileSource(fd, offset, length);
+    sp<DataSource> dataSource = new FileSource(fd, offset, length);
 
-    status_t err = source->initCheck();
+    status_t err = dataSource->initCheck();
 
     if (err != OK) {
         return err;
     }
 
-    sp<MediaExtractor> extractor = MediaExtractor::Create(source);
+    mFileSource = dataSource;
+
+    return setDataSource_l(dataSource);
+}
+
+status_t AwesomePlayer::setDataSource_l(
+        const sp<DataSource> &dataSource) {
+    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
 
     if (extractor == NULL) {
         return UNKNOWN_ERROR;
@@ -242,8 +319,32 @@
 }
 
 void AwesomePlayer::reset_l() {
+    while (mFlags & PREPARING) {
+        mPreparedCondition.wait(mLock);
+    }
+
     cancelPlayerEvents();
 
+    if (mPrefetcher != NULL) {
+        CHECK_EQ(mPrefetcher->getStrongCount(), 1);
+    }
+    mPrefetcher.clear();
+
+    // Shutdown audio first, so that the respone to the reset request
+    // appears to happen instantaneously as far as the user is concerned
+    // If we did this later, audio would continue playing while we
+    // shutdown the video-related resources and the player appear to
+    // not be as responsive to a reset request.
+    mAudioSource.clear();
+
+    if (mTimeSource != mAudioPlayer) {
+        delete mTimeSource;
+    }
+    mTimeSource = NULL;
+
+    delete mAudioPlayer;
+    mAudioPlayer = NULL;
+
     mVideoRenderer.clear();
 
     if (mLastVideoBuffer) {
@@ -270,16 +371,6 @@
         IPCThreadState::self()->flushCommands();
     }
 
-    mAudioSource.clear();
-
-    if (mTimeSource != mAudioPlayer) {
-        delete mTimeSource;
-    }
-    mTimeSource = NULL;
-
-    delete mAudioPlayer;
-    mAudioPlayer = NULL;
-
     mDurationUs = -1;
     mFlags = 0;
     mVideoWidth = mVideoHeight = -1;
@@ -289,7 +380,13 @@
     mSeeking = false;
     mSeekTimeUs = 0;
 
-    mPrefetcher.clear();
+    mUri.setTo("");
+    mUriHeaders.clear();
+
+    mFileSource.clear();
+
+    delete mSuspensionState;
+    mSuspensionState = NULL;
 }
 
 void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
@@ -345,11 +442,22 @@
 
 status_t AwesomePlayer::play() {
     Mutex::Autolock autoLock(mLock);
+    return play_l();
+}
 
+status_t AwesomePlayer::play_l() {
     if (mFlags & PLAYING) {
         return OK;
     }
 
+    if (!(mFlags & PREPARED)) {
+        status_t err = prepare_l();
+
+        if (err != OK) {
+            return err;
+        }
+    }
+
     mFlags |= PLAYING;
     mFlags |= FIRST_FRAME;
 
@@ -438,6 +546,8 @@
             // Other decoders are instantiated locally and as a consequence
             // allocate their buffers in local address space.
             mVideoRenderer = new AwesomeLocalRenderer(
+                false,  // previewOnly
+                component,
                 (OMX_COLOR_FORMATTYPE)format,
                 mISurface,
                 mVideoWidth, mVideoHeight,
@@ -512,7 +622,10 @@
 
 status_t AwesomePlayer::getPosition(int64_t *positionUs) {
     Mutex::Autolock autoLock(mLock);
+    return getPosition_l(positionUs);
+}
 
+status_t AwesomePlayer::getPosition_l(int64_t *positionUs) {
     if (mVideoSource != NULL) {
         *positionUs = mVideoTimeUs;
     } else if (mAudioPlayer != NULL) {
@@ -630,7 +743,11 @@
 
 void AwesomePlayer::onVideoEvent() {
     Mutex::Autolock autoLock(mLock);
-
+    if (!mVideoEventPending) {
+        // The event has been cancelled in reset_l() but had already
+        // been scheduled for execution at that time.
+        return;
+    }
     mVideoEventPending = false;
 
     if (mSeeking) {
@@ -663,6 +780,7 @@
                     LOGV("VideoSource signalled format change.");
 
                     if (mVideoRenderer != NULL) {
+                        mVideoRendererIsPreview = false;
                         initRenderer_l();
                     }
                     continue;
@@ -741,7 +859,9 @@
         return;
     }
 
-    if (mVideoRenderer == NULL) {
+    if (mVideoRendererIsPreview || mVideoRenderer == NULL) {
+        mVideoRendererIsPreview = false;
+
         initRenderer_l();
     }
 
@@ -815,30 +935,49 @@
 
 status_t AwesomePlayer::prepare() {
     Mutex::Autolock autoLock(mLock);
+    return prepare_l();
+}
 
+status_t AwesomePlayer::prepare_l() {
+    if (mFlags & PREPARED) {
+        return OK;
+    }
+
+    if (mFlags & PREPARING) {
+        return UNKNOWN_ERROR;
+    }
+
+    mIsAsyncPrepare = false;
     status_t err = prepareAsync_l();
 
     if (err != OK) {
         return err;
     }
 
-    while (mAsyncPrepareEvent != NULL) {
+    while (mFlags & PREPARING) {
         mPreparedCondition.wait(mLock);
     }
 
-    return OK;
+    return mPrepareResult;
 }
 
 status_t AwesomePlayer::prepareAsync() {
     Mutex::Autolock autoLock(mLock);
+
+    if (mFlags & PREPARING) {
+        return UNKNOWN_ERROR;  // async prepare already pending
+    }
+
+    mIsAsyncPrepare = true;
     return prepareAsync_l();
 }
 
 status_t AwesomePlayer::prepareAsync_l() {
-    if (mAsyncPrepareEvent != NULL) {
-        return UNKNOWN_ERROR;  // async prepare already pending.
+    if (mFlags & PREPARING) {
+        return UNKNOWN_ERROR;  // async prepare already pending
     }
 
+    mFlags |= PREPARING;
     mAsyncPrepareEvent = new AwesomeEvent(
             this, &AwesomePlayer::onPrepareAsyncEvent);
 
@@ -847,7 +986,49 @@
     return OK;
 }
 
+status_t AwesomePlayer::finishSetDataSource_l() {
+    sp<DataSource> dataSource =
+        DataSource::CreateFromURI(mUri.string(), &mUriHeaders);
+
+    if (dataSource == NULL) {
+        return UNKNOWN_ERROR;
+    }
+
+    sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
+
+    if (extractor == NULL) {
+        return UNKNOWN_ERROR;
+    }
+
+    if (dataSource->flags() & DataSource::kWantsPrefetching) {
+        mPrefetcher = new Prefetcher;
+    }
+
+    return setDataSource_l(extractor);
+}
+
 void AwesomePlayer::onPrepareAsyncEvent() {
+    {
+        Mutex::Autolock autoLock(mLock);
+
+        if (mUri.size() > 0) {
+            status_t err = finishSetDataSource_l();
+
+            if (err != OK) {
+                if (mIsAsyncPrepare) {
+                    notifyListener_l(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
+                }
+
+                mPrepareResult = err;
+                mFlags &= ~PREPARING;
+                mAsyncPrepareEvent = NULL;
+                mPreparedCondition.broadcast();
+
+                return;
+            }
+        }
+    }
+
     sp<Prefetcher> prefetcher;
 
     {
@@ -857,20 +1038,134 @@
 
     if (prefetcher != NULL) {
         prefetcher->prepare();
+        prefetcher.clear();
     }
 
     Mutex::Autolock autoLock(mLock);
 
-    if (mVideoWidth < 0 || mVideoHeight < 0) {
-        notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
-    } else {
-        notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);
+    if (mIsAsyncPrepare) {
+        if (mVideoWidth < 0 || mVideoHeight < 0) {
+            notifyListener_l(MEDIA_SET_VIDEO_SIZE, 0, 0);
+        } else {
+            notifyListener_l(MEDIA_SET_VIDEO_SIZE, mVideoWidth, mVideoHeight);
+        }
+
+        notifyListener_l(MEDIA_PREPARED);
     }
 
-    notifyListener_l(MEDIA_PREPARED);
-
+    mPrepareResult = OK;
+    mFlags &= ~PREPARING;
+    mFlags |= PREPARED;
     mAsyncPrepareEvent = NULL;
-    mPreparedCondition.signal();
+    mPreparedCondition.broadcast();
+}
+
+status_t AwesomePlayer::suspend() {
+    LOGI("suspend");
+    Mutex::Autolock autoLock(mLock);
+
+    if (mSuspensionState != NULL) {
+        return INVALID_OPERATION;
+    }
+
+    while (mFlags & PREPARING) {
+        mPreparedCondition.wait(mLock);
+    }
+
+    SuspensionState *state = new SuspensionState;
+    state->mUri = mUri;
+    state->mUriHeaders = mUriHeaders;
+    state->mFileSource = mFileSource;
+
+    state->mFlags = mFlags & (PLAYING | LOOPING);
+    getPosition_l(&state->mPositionUs);
+
+    if (mLastVideoBuffer) {
+        size_t size = mLastVideoBuffer->range_length();
+        if (size) {
+            state->mLastVideoFrameSize = size;
+            state->mLastVideoFrame = malloc(size);
+            memcpy(state->mLastVideoFrame,
+                   (const uint8_t *)mLastVideoBuffer->data()
+                        + mLastVideoBuffer->range_offset(),
+                   size);
+
+            state->mVideoWidth = mVideoWidth;
+            state->mVideoHeight = mVideoHeight;
+
+            sp<MetaData> meta = mVideoSource->getFormat();
+            CHECK(meta->findInt32(kKeyColorFormat, &state->mColorFormat));
+            CHECK(meta->findInt32(kKeyWidth, &state->mDecodedWidth));
+            CHECK(meta->findInt32(kKeyHeight, &state->mDecodedHeight));
+        }
+    }
+
+    reset_l();
+
+    mSuspensionState = state;
+
+    return OK;
+}
+
+status_t AwesomePlayer::resume() {
+    LOGI("resume");
+    Mutex::Autolock autoLock(mLock);
+
+    if (mSuspensionState == NULL) {
+        return INVALID_OPERATION;
+    }
+
+    SuspensionState *state = mSuspensionState;
+    mSuspensionState = NULL;
+
+    status_t err;
+    if (state->mFileSource != NULL) {
+        err = setDataSource_l(state->mFileSource);
+
+        if (err == OK) {
+            mFileSource = state->mFileSource;
+        }
+    } else {
+        err = setDataSource_l(state->mUri, &state->mUriHeaders);
+    }
+
+    if (err != OK) {
+        delete state;
+        state = NULL;
+
+        return err;
+    }
+
+    seekTo_l(state->mPositionUs);
+
+    mFlags = state->mFlags & LOOPING;
+
+    if (state->mLastVideoFrame && mISurface != NULL) {
+        mVideoRenderer =
+            new AwesomeLocalRenderer(
+                    true,  // previewOnly
+                    "",
+                    (OMX_COLOR_FORMATTYPE)state->mColorFormat,
+                    mISurface,
+                    state->mVideoWidth,
+                    state->mVideoHeight,
+                    state->mDecodedWidth,
+                    state->mDecodedHeight);
+
+        mVideoRendererIsPreview = true;
+
+        ((AwesomeLocalRenderer *)mVideoRenderer.get())->render(
+                state->mLastVideoFrame, state->mLastVideoFrameSize);
+    }
+
+    if (state->mFlags & PLAYING) {
+        play_l();
+    }
+
+    delete state;
+    state = NULL;
+
+    return OK;
 }
 
 }  // namespace android
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 8cd572e..075b1e3 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -25,11 +25,11 @@
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/MetaData.h>
-#include <ui/Camera.h>
-#include <ui/CameraParameters.h>
+#include <camera/Camera.h>
+#include <camera/CameraParameters.h>
 #include <ui/GraphicBuffer.h>
-#include <ui/ISurface.h>
 #include <ui/Overlay.h>
+#include <surfaceflinger/ISurface.h>
 #include <utils/String8.h>
 
 namespace android {
diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp
index 79b7674..ab38bca 100644
--- a/media/libstagefright/MP3Extractor.cpp
+++ b/media/libstagefright/MP3Extractor.cpp
@@ -731,6 +731,7 @@
     static const Map kMap[] = {
         { kKeyAlbum, "TALB", "TAL" },
         { kKeyArtist, "TPE1", "TP1" },
+        { kKeyAlbumArtist, "TPE2", "TP2" },
         { kKeyComposer, "TCOM", "TCM" },
         { kKeyGenre, "TCON", "TCO" },
         { kKeyTitle, "TIT2", "TT2" },
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 4458006..16635d3 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -60,6 +60,8 @@
     virtual ~MPEG4Source();
 
 private:
+    Mutex mLock;
+
     sp<MetaData> mFormat;
     sp<DataSource> mDataSource;
     int32_t mTimescale;
@@ -1045,6 +1047,11 @@
             metadataKey = kKeyArtist;
             break;
         }
+        case FOURCC('a', 'A', 'R', 'T'):
+        {
+            metadataKey = kKeyAlbumArtist;
+            break;
+        }
         case FOURCC(0xa9, 'd', 'a', 'y'):
         {
             metadataKey = kKeyYear;
@@ -1295,6 +1302,8 @@
 }
 
 status_t MPEG4Source::start(MetaData *params) {
+    Mutex::Autolock autoLock(mLock);
+
     CHECK(!mStarted);
 
     int32_t val;
@@ -1320,6 +1329,8 @@
 }
 
 status_t MPEG4Source::stop() {
+    Mutex::Autolock autoLock(mLock);
+
     CHECK(mStarted);
 
     if (mBuffer != NULL) {
@@ -1340,6 +1351,8 @@
 }
 
 sp<MetaData> MPEG4Source::getFormat() {
+    Mutex::Autolock autoLock(mLock);
+
     return mFormat;
 }
 
@@ -1364,6 +1377,8 @@
 
 status_t MPEG4Source::read(
         MediaBuffer **out, const ReadOptions *options) {
+    Mutex::Autolock autoLock(mLock);
+
     CHECK(mStarted);
 
     *out = NULL;
@@ -1423,6 +1438,7 @@
                 return ERROR_IO;
             }
 
+            CHECK(mBuffer != NULL);
             mBuffer->set_range(0, size);
             mBuffer->meta_data()->clear();
             mBuffer->meta_data()->setInt64(
@@ -1456,8 +1472,10 @@
         }
 
         MediaBuffer *clone = mBuffer->clone();
+        CHECK(clone != NULL);
         clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
 
+        CHECK(mBuffer != NULL);
         mBuffer->set_range(
                 mBuffer->range_offset() + mNALLengthSize + nal_size,
                 mBuffer->range_length() - mNALLengthSize - nal_size);
@@ -1516,6 +1534,7 @@
         }
         CHECK_EQ(srcOffset, size);
 
+        CHECK(mBuffer != NULL);
         mBuffer->set_range(0, dstOffset);
         mBuffer->meta_data()->clear();
         mBuffer->meta_data()->setInt64(
@@ -1540,7 +1559,7 @@
 
     if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
         || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
-        || !memcmp(header, "ftypM4A ", 8)) {
+        || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)) {
         *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
         *confidence = 0.1;
 
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index c6c6f21..75b7b6f 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -112,7 +112,6 @@
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "OMX.TI.Video.Decoder" },
     { MEDIA_MIMETYPE_VIDEO_MPEG4, "M4vH263Decoder" },
     { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.decoder.h263" },
-    { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.Video.Decoder" },
     { MEDIA_MIMETYPE_VIDEO_H263, "M4vH263Decoder" },
     { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.decoder.avc" },
     { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.Decoder" },
diff --git a/media/libstagefright/Prefetcher.cpp b/media/libstagefright/Prefetcher.cpp
index 835e167..cb03979 100644
--- a/media/libstagefright/Prefetcher.cpp
+++ b/media/libstagefright/Prefetcher.cpp
@@ -31,7 +31,6 @@
 
 struct PrefetchedSource : public MediaSource {
     PrefetchedSource(
-            const sp<Prefetcher> &prefetcher,
             size_t index,
             const sp<MediaSource> &source);
 
@@ -52,13 +51,13 @@
     Mutex mLock;
     Condition mCondition;
 
-    sp<Prefetcher> mPrefetcher;
     sp<MediaSource> mSource;
     size_t mIndex;
     bool mStarted;
     bool mReachedEOS;
     int64_t mSeekTimeUs;
     int64_t mCacheDurationUs;
+    bool mPrefetcherStopped;
 
     List<MediaBuffer *> mCachedBuffers;
 
@@ -69,6 +68,7 @@
     void clearCache_l();
 
     void cacheMore();
+    void onPrefetcherStopped();
 
     PrefetchedSource(const PrefetchedSource &);
     PrefetchedSource &operator=(const PrefetchedSource &);
@@ -88,7 +88,7 @@
     Mutex::Autolock autoLock(mLock);
 
     sp<PrefetchedSource> psource =
-        new PrefetchedSource(this, mSources.size(), source);
+        new PrefetchedSource(mSources.size(), source);
 
     mSources.add(psource);
 
@@ -130,8 +130,6 @@
     for (;;) {
         Mutex::Autolock autoLock(mLock);
         if (mDone) {
-            mThreadExited = true;
-            mCondition.signal();
             break;
         }
         mCondition.waitRelative(mLock, 10000000ll);
@@ -169,6 +167,19 @@
             source->cacheMore();
         }
     }
+
+    for (size_t i = 0; i < mSources.size(); ++i) {
+        sp<PrefetchedSource> source = mSources[i].promote();
+
+        if (source == NULL) {
+            continue;
+        }
+
+        source->onPrefetcherStopped();
+    }
+
+    mThreadExited = true;
+    mCondition.signal();
 }
 
 int64_t Prefetcher::getCachedDurationUs(bool *noMoreData) {
@@ -219,16 +230,15 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 PrefetchedSource::PrefetchedSource(
-        const sp<Prefetcher> &prefetcher,
         size_t index,
         const sp<MediaSource> &source)
-    : mPrefetcher(prefetcher),
-      mSource(source),
+    : mSource(source),
       mIndex(index),
       mStarted(false),
       mReachedEOS(false),
       mSeekTimeUs(0),
-      mCacheDurationUs(0) {
+      mCacheDurationUs(0),
+      mPrefetcherStopped(false) {
 }
 
 PrefetchedSource::~PrefetchedSource() {
@@ -238,6 +248,8 @@
 }
 
 status_t PrefetchedSource::start(MetaData *params) {
+    CHECK(!mStarted);
+
     Mutex::Autolock autoLock(mLock);
 
     status_t err = mSource->start(params);
@@ -252,6 +264,8 @@
 }
 
 status_t PrefetchedSource::stop() {
+    CHECK(mStarted);
+
     Mutex::Autolock autoLock(mLock);
 
     clearCache_l();
@@ -281,7 +295,7 @@
         mSeekTimeUs = seekTimeUs;
     }
 
-    while (!mReachedEOS && mCachedBuffers.empty()) {
+    while (!mPrefetcherStopped && !mReachedEOS && mCachedBuffers.empty()) {
         mCondition.wait(mLock);
     }
 
@@ -390,4 +404,10 @@
     updateCacheDuration_l();
 }
 
+void PrefetchedSource::onPrefetcherStopped() {
+    Mutex::Autolock autoLock(mLock);
+    mPrefetcherStopped = true;
+    mCondition.signal();
+}
+
 }  // namespace android
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index 22f701c..b1eca2b 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -194,6 +194,7 @@
             { "discnumber", METADATA_KEY_DISC_NUMBER },
             { "album", METADATA_KEY_ALBUM },
             { "artist", METADATA_KEY_ARTIST },
+            { "albumartist", METADATA_KEY_ALBUMARTIST },
             { "composer", METADATA_KEY_COMPOSER },
             { "genre", METADATA_KEY_GENRE },
             { "title", METADATA_KEY_TITLE },
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index f617fe8..df6235f 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -308,6 +308,7 @@
         { kKeyDiscNumber, METADATA_KEY_DISC_NUMBER },
         { kKeyAlbum, METADATA_KEY_ALBUM },
         { kKeyArtist, METADATA_KEY_ARTIST },
+        { kKeyAlbumArtist, METADATA_KEY_ALBUMARTIST },
         { kKeyAuthor, METADATA_KEY_AUTHOR },
         { kKeyComposer, METADATA_KEY_COMPOSER },
         { kKeyDate, METADATA_KEY_DATE },
diff --git a/media/libstagefright/colorconversion/Android.mk b/media/libstagefright/colorconversion/Android.mk
index c08ce3a..e7a571a 100644
--- a/media/libstagefright/colorconversion/Android.mk
+++ b/media/libstagefright/colorconversion/Android.mk
@@ -13,7 +13,9 @@
         libmedia                \
         libutils                \
         libui                   \
-        libcutils
+        libcutils				\
+        libsurfaceflinger_client\
+        libcamera_client
 
 LOCAL_PRELINK_MODULE:= false
 
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index ed91eea..4c11c36 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -22,7 +22,7 @@
 #include <binder/MemoryHeapBase.h>
 #include <binder/MemoryHeapPmem.h>
 #include <media/stagefright/MediaDebug.h>
-#include <ui/ISurface.h>
+#include <surfaceflinger/ISurface.h>
 
 namespace android {
 
@@ -40,7 +40,6 @@
       mDecodedHeight(decodedHeight),
       mFrameSize(mDecodedWidth * mDecodedHeight * 2),  // RGB565
       mIndex(0) {
-    // TODO: How do I allocate physical memory on Droid?
     mMemoryHeap = new MemoryHeapBase("/dev/pmem_adsp", 2 * mFrameSize);
     if (mMemoryHeap->heapID() < 0) {
         LOGI("Creating physical memory heap failed, reverting to regular heap.");
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 651b910..114d4c6 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -21,12 +21,14 @@
 #include "TimedEventQueue.h"
 
 #include <media/MediaPlayerInterface.h>
+#include <media/stagefright/DataSource.h>
 #include <media/stagefright/OMXClient.h>
 #include <utils/threads.h>
 
 namespace android {
 
 struct AudioPlayer;
+struct DataSource;
 struct MediaBuffer;
 struct MediaExtractor;
 struct MediaSource;
@@ -58,6 +60,7 @@
     void reset();
 
     status_t prepare();
+    status_t prepare_l();
     status_t prepareAsync();
     status_t prepareAsync_l();
 
@@ -77,6 +80,9 @@
 
     status_t getVideoDimensions(int32_t *width, int32_t *height) const;
 
+    status_t suspend();
+    status_t resume();
+
 private:
     friend struct AwesomeEvent;
 
@@ -84,6 +90,8 @@
         PLAYING     = 1,
         LOOPING     = 2,
         FIRST_FRAME = 4,
+        PREPARING   = 8,
+        PREPARED    = 16,
     };
 
     mutable Mutex mLock;
@@ -97,8 +105,14 @@
 
     TimeSource *mTimeSource;
 
+    String8 mUri;
+    KeyedVector<String8, String8> mUriHeaders;
+
+    sp<DataSource> mFileSource;
+
     sp<MediaSource> mVideoSource;
     sp<AwesomeRenderer> mVideoRenderer;
+    bool mVideoRendererIsPreview;
 
     sp<MediaSource> mAudioSource;
     AudioPlayer *mAudioPlayer;
@@ -127,17 +141,52 @@
 
     sp<TimedEventQueue::Event> mAsyncPrepareEvent;
     Condition mPreparedCondition;
+    bool mIsAsyncPrepare;
+    status_t mPrepareResult;
 
     void postVideoEvent_l(int64_t delayUs = -1);
     void postBufferingEvent_l();
     void postStreamDoneEvent_l();
     void postCheckAudioStatusEvent_l();
+    status_t getPosition_l(int64_t *positionUs);
+    status_t play_l();
 
     MediaBuffer *mLastVideoBuffer;
     MediaBuffer *mVideoBuffer;
 
     sp<Prefetcher> mPrefetcher;
 
+    struct SuspensionState {
+        String8 mUri;
+        KeyedVector<String8, String8> mUriHeaders;
+        sp<DataSource> mFileSource;
+
+        uint32_t mFlags;
+        int64_t mPositionUs;
+
+        void *mLastVideoFrame;
+        size_t mLastVideoFrameSize;
+        int32_t mColorFormat;
+        int32_t mVideoWidth, mVideoHeight;
+        int32_t mDecodedWidth, mDecodedHeight;
+
+        SuspensionState()
+            : mLastVideoFrame(NULL) {
+        }
+
+        ~SuspensionState() {
+            if (mLastVideoFrame) {
+                free(mLastVideoFrame);
+                mLastVideoFrame = NULL;
+            }
+        }
+    } *mSuspensionState;
+
+    status_t setDataSource_l(
+            const char *uri,
+            const KeyedVector<String8, String8> *headers = NULL);
+
+    status_t setDataSource_l(const sp<DataSource> &dataSource);
     status_t setDataSource_l(const sp<MediaExtractor> &extractor);
     void reset_l();
     status_t seekTo_l(int64_t timeUs);
@@ -158,6 +207,7 @@
     void onBufferingUpdate();
     void onCheckAudioStatus();
     void onPrepareAsyncEvent();
+    status_t finishSetDataSource_l();
 
     AwesomePlayer(const AwesomePlayer &);
     AwesomePlayer &operator=(const AwesomePlayer &);
diff --git a/media/tests/SoundPoolTest/src/com/android/SoundPoolTest.java b/media/tests/SoundPoolTest/src/com/android/SoundPoolTest.java
index 6b3093f..1434d3f 100644
--- a/media/tests/SoundPoolTest/src/com/android/SoundPoolTest.java
+++ b/media/tests/SoundPoolTest/src/com/android/SoundPoolTest.java
@@ -43,10 +43,9 @@
     private TestThread mThread;
 
     private static final int[] mTestFiles = new int[] {
-        // FIXME: Restore when Stagefright bug is fixed
         R.raw.organ441,
         R.raw.sine441,
-        //R.raw.test1,
+        R.raw.test1,
         R.raw.test2,
         R.raw.test3,
         R.raw.test4,
diff --git a/mms-common/java/com/android/mmscommon/mms/pdu/Base64.java b/mms-common/java/com/android/mmscommon/mms/pdu/Base64.java
deleted file mode 100644
index 4c95dec..0000000
--- a/mms-common/java/com/android/mmscommon/mms/pdu/Base64.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (C) 2007 Esmertec AG.
- * 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.mmscommon.mms.pdu;
-
-public class Base64 {
-    /**
-     * Used to get the number of Quadruples.
-     */
-    static final int FOURBYTE = 4;
-
-    /**
-     * Byte used to pad output.
-     */
-    static final byte PAD = (byte) '=';
-
-    /**
-     * The base length.
-     */
-    static final int BASELENGTH = 255;
-
-    // Create arrays to hold the base64 characters
-    private static byte[] base64Alphabet = new byte[BASELENGTH];
-
-    // Populating the character arrays
-    static {
-        for (int i = 0; i < BASELENGTH; i++) {
-            base64Alphabet[i] = (byte) -1;
-        }
-        for (int i = 'Z'; i >= 'A'; i--) {
-            base64Alphabet[i] = (byte) (i - 'A');
-        }
-        for (int i = 'z'; i >= 'a'; i--) {
-            base64Alphabet[i] = (byte) (i - 'a' + 26);
-        }
-        for (int i = '9'; i >= '0'; i--) {
-            base64Alphabet[i] = (byte) (i - '0' + 52);
-        }
-
-        base64Alphabet['+'] = 62;
-        base64Alphabet['/'] = 63;
-    }
-
-    /**
-     * Decodes Base64 data into octects
-     *
-     * @param base64Data Byte array containing Base64 data
-     * @return Array containing decoded data.
-     */
-    public static byte[] decodeBase64(byte[] base64Data) {
-        // RFC 2045 requires that we discard ALL non-Base64 characters
-        base64Data = discardNonBase64(base64Data);
-
-        // handle the edge case, so we don't have to worry about it later
-        if (base64Data.length == 0) {
-            return new byte[0];
-        }
-
-        int numberQuadruple = base64Data.length / FOURBYTE;
-        byte decodedData[] = null;
-        byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marker0 = 0, marker1 = 0;
-
-        // Throw away anything not in base64Data
-
-        int encodedIndex = 0;
-        int dataIndex = 0;
-        {
-            // this sizes the output array properly - rlw
-            int lastData = base64Data.length;
-            // ignore the '=' padding
-            while (base64Data[lastData - 1] == PAD) {
-                if (--lastData == 0) {
-                    return new byte[0];
-                }
-            }
-            decodedData = new byte[lastData - numberQuadruple];
-        }
-
-        for (int i = 0; i < numberQuadruple; i++) {
-            dataIndex = i * 4;
-            marker0 = base64Data[dataIndex + 2];
-            marker1 = base64Data[dataIndex + 3];
-
-            b1 = base64Alphabet[base64Data[dataIndex]];
-            b2 = base64Alphabet[base64Data[dataIndex + 1]];
-
-            if (marker0 != PAD && marker1 != PAD) {
-                //No PAD e.g 3cQl
-                b3 = base64Alphabet[marker0];
-                b4 = base64Alphabet[marker1];
-
-                decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
-                decodedData[encodedIndex + 1] =
-                    (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
-                decodedData[encodedIndex + 2] = (byte) (b3 << 6 | b4);
-            } else if (marker0 == PAD) {
-                //Two PAD e.g. 3c[Pad][Pad]
-                decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
-            } else if (marker1 == PAD) {
-                //One PAD e.g. 3cQ[Pad]
-                b3 = base64Alphabet[marker0];
-
-                decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
-                decodedData[encodedIndex + 1] =
-                    (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
-            }
-            encodedIndex += 3;
-        }
-        return decodedData;
-    }
-
-    /**
-     * Check octect wheter it is a base64 encoding.
-     *
-     * @param octect to be checked byte
-     * @return ture if it is base64 encoding, false otherwise.
-     */
-    private static boolean isBase64(byte octect) {
-        if (octect == PAD) {
-            return true;
-        } else if (base64Alphabet[octect] == -1) {
-            return false;
-        } else {
-            return true;
-        }
-    }
-
-    /**
-     * Discards any characters outside of the base64 alphabet, per
-     * the requirements on page 25 of RFC 2045 - "Any characters
-     * outside of the base64 alphabet are to be ignored in base64
-     * encoded data."
-     *
-     * @param data The base-64 encoded data to groom
-     * @return The data, less non-base64 characters (see RFC 2045).
-     */
-    static byte[] discardNonBase64(byte[] data) {
-        byte groomedData[] = new byte[data.length];
-        int bytesCopied = 0;
-
-        for (int i = 0; i < data.length; i++) {
-            if (isBase64(data[i])) {
-                groomedData[bytesCopied++] = data[i];
-            }
-        }
-
-        byte packedData[] = new byte[bytesCopied];
-
-        System.arraycopy(groomedData, 0, packedData, 0, bytesCopied);
-
-        return packedData;
-    }
-}
diff --git a/mms-common/java/com/android/mmscommon/mms/pdu/PduParser.java b/mms-common/java/com/android/mmscommon/mms/pdu/PduParser.java
index 9253f83..6a58ba6 100644
--- a/mms-common/java/com/android/mmscommon/mms/pdu/PduParser.java
+++ b/mms-common/java/com/android/mmscommon/mms/pdu/PduParser.java
@@ -17,14 +17,15 @@
 
 package com.android.mmscommon.mms.pdu;
 
-import com.android.mmscommon.ContentType;
 import com.android.mmscommon.CharacterSets;
+import com.android.mmscommon.ContentType;
 import com.android.mmscommon.EncodedStringValue;
 import com.android.mmscommon.InvalidHeaderValueException;
 import com.android.mmscommon.PduHeaders;
 
 import android.util.Config;
 import android.util.Log;
+import android.util.base64.Base64;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -790,7 +791,7 @@
                     String encoding = new String(partDataEncoding);
                     if (encoding.equalsIgnoreCase(PduPart.P_BASE64)) {
                         // Decode "base64" into "binary".
-                        partData = Base64.decodeBase64(partData);
+                        partData = Base64.decode(partData, Base64.DEFAULT);
                     } else if (encoding.equalsIgnoreCase(PduPart.P_QUOTED_PRINTABLE)) {
                         // Decode "quoted-printable" into "binary".
                         partData = QuotedPrintable.decodeQuotedPrintable(partData);
diff --git a/packages/DefaultContainerService/AndroidManifest.xml b/packages/DefaultContainerService/AndroidManifest.xml
index 5ec72df..078daa7 100755
--- a/packages/DefaultContainerService/AndroidManifest.xml
+++ b/packages/DefaultContainerService/AndroidManifest.xml
@@ -6,6 +6,7 @@
     <uses-permission android:name="android.permission.ASEC_DESTROY"/>
     <uses-permission android:name="android.permission.ASEC_MOUNT_UNMOUNT"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" />
 
     <application android:label="@string/service_name">
 
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index c418ccb..8e030e5 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -1,10 +1,13 @@
 package com.android.defcontainer;
 
 import com.android.internal.app.IMediaContainerService;
-
+import com.android.internal.content.PackageHelper;
 import android.content.Intent;
 import android.content.pm.IPackageManager;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
+import android.content.pm.PackageParser.Package;
 import android.net.Uri;
 import android.os.Debug;
 import android.os.Environment;
@@ -15,8 +18,10 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.StatFs;
 import android.app.IntentService;
 import android.app.Service;
+import android.util.DisplayMetrics;
 import android.util.Log;
 
 import java.io.File;
@@ -28,6 +33,7 @@
 import java.io.OutputStream;
 
 import android.os.FileUtils;
+import android.provider.Settings;
 
 /*
  * This service copies a downloaded apk to a file passed in as
@@ -79,6 +85,44 @@
             autoOut = new ParcelFileDescriptor.AutoCloseOutputStream(outStream);
             return copyFile(packageURI, autoOut);
         }
+
+        /*
+         * Determine the recommended install location for package
+         * specified by file uri location.
+         * @param fileUri the uri of resource to be copied. Should be a
+         * file uri
+         * @return Returns
+         *  PackageHelper.RECOMMEND_INSTALL_INTERNAL to install on internal storage
+         *  PackageHelper.RECOMMEND_INSTALL_EXTERNAL to install on external media
+         *  PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE for storage errors
+         *  PackageHelper.RECOMMEND_FAILED_INVALID_APK for parse errors.
+         */
+        public int getRecommendedInstallLocation(final Uri fileUri) {
+            if (!fileUri.getScheme().equals("file")) {
+                Log.w(TAG, "Falling back to installing on internal storage only");
+                return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
+            }
+            final String archiveFilePath = fileUri.getPath();
+            PackageParser packageParser = new PackageParser(archiveFilePath);
+            File sourceFile = new File(archiveFilePath);
+            DisplayMetrics metrics = new DisplayMetrics();
+            metrics.setToDefaults();
+            PackageParser.Package pkg = packageParser.parsePackage(sourceFile, archiveFilePath, metrics, 0);
+            if (pkg == null) {
+                Log.w(TAG, "Failed to parse package");
+                return PackageHelper.RECOMMEND_FAILED_INVALID_APK;
+            }
+            int loc = recommendAppInstallLocation(pkg);
+            if (loc == PackageManager.INSTALL_EXTERNAL) {
+                return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
+            } else if (loc == ERR_LOC) {
+                Log.i(TAG, "Failed to install insufficient storage");
+                return PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
+            } else {
+                // Implies install on internal storage.
+                return 0;
+            }
+        }
     };
 
     public DefaultContainerService() {
@@ -111,7 +155,6 @@
                 }
             }
         }
-        //Log.i(TAG, "Deleting: " + path);
         path.delete();
     }
     
@@ -341,4 +384,104 @@
         }
         return true;
     }
+
+    // Constants related to app heuristics
+    // No-installation limit for internal flash: 10% or less space available
+    private static final double LOW_NAND_FLASH_TRESHOLD = 0.1;
+
+    // SD-to-internal app size threshold: currently set to 1 MB
+    private static final long INSTALL_ON_SD_THRESHOLD = (1024 * 1024);
+    private static final int ERR_LOC = -1;
+
+    public int recommendAppInstallLocation(Package pkg) {
+        // Initial implementation:
+        // Package size = code size + cache size + data size
+        // If code size > 1 MB, install on SD card.
+        // Else install on internal NAND flash, unless space on NAND is less than 10%
+
+        if (pkg == null) {
+            return ERR_LOC;
+        }
+
+        StatFs internalFlashStats = new StatFs(Environment.getDataDirectory().getPath());
+        StatFs sdcardStats = new StatFs(Environment.getExternalStorageDirectory().getPath());
+
+        long totalInternalFlashSize = (long)internalFlashStats.getBlockCount() *
+                (long)internalFlashStats.getBlockSize();
+        long availInternalFlashSize = (long)internalFlashStats.getAvailableBlocks() *
+                (long)internalFlashStats.getBlockSize();
+        long availSDSize = (long)sdcardStats.getAvailableBlocks() *
+                (long)sdcardStats.getBlockSize();
+
+        double pctNandFree = (double)availInternalFlashSize / (double)totalInternalFlashSize;
+
+        final String archiveFilePath = pkg.mScanPath;
+        File apkFile = new File(archiveFilePath);
+        long pkgLen = apkFile.length();
+
+        boolean auto = true;
+        // To make final copy
+        long reqInstallSize = pkgLen;
+        // For dex files
+        long reqInternalSize = 1 * pkgLen;
+        boolean intThresholdOk = (pctNandFree >= LOW_NAND_FLASH_TRESHOLD);
+        boolean intAvailOk = ((reqInstallSize + reqInternalSize) < availInternalFlashSize);
+        boolean fitsOnSd = (reqInstallSize < availSDSize) && intThresholdOk &&
+                (reqInternalSize < availInternalFlashSize);
+        boolean fitsOnInt = intThresholdOk && intAvailOk;
+
+        // Consider application flags preferences as well...
+        boolean installOnlyOnSd = (pkg.installLocation ==
+                PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+        boolean installOnlyInternal = (pkg.installLocation ==
+                PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
+        if (installOnlyInternal) {
+            // If set explicitly in manifest,
+            // let that override everything else
+            auto = false;
+        } else if (installOnlyOnSd){
+            // Check if this can be accommodated on the sdcard
+            if (fitsOnSd) {
+                auto = false;
+            }
+        } else {
+            // Check if user option is enabled
+            boolean setInstallLoc = Settings.System.getInt(getApplicationContext()
+                    .getContentResolver(),
+                    Settings.System.SET_INSTALL_LOCATION, 0) != 0;
+            if (setInstallLoc) {
+                // Pick user preference
+                int installPreference = Settings.System.getInt(getApplicationContext()
+                        .getContentResolver(),
+                        Settings.System.DEFAULT_INSTALL_LOCATION,
+                        PackageInfo.INSTALL_LOCATION_AUTO);
+                if (installPreference == 1) {
+                    installOnlyInternal = true;
+                    auto = false;
+                } else if (installPreference == 2) {
+                    installOnlyOnSd = true;
+                    auto = false;
+                }
+            }
+        }
+        if (!auto) {
+            if (installOnlyOnSd) {
+                return fitsOnSd ? PackageManager.INSTALL_EXTERNAL : ERR_LOC;
+            } else if (installOnlyInternal){
+                // Check on internal flash
+                return fitsOnInt ? 0 : ERR_LOC;
+            }
+        }
+        // Try to install internally
+        if (fitsOnInt) {
+            return 0;
+        }
+        // Try the sdcard now.
+        if (fitsOnSd) {
+            return PackageManager.INSTALL_EXTERNAL;
+        }
+        // Return error code
+        return ERR_LOC;
+    }
+
 }
diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml
index a542518..c92b9d7 100644
--- a/packages/SettingsProvider/AndroidManifest.xml
+++ b/packages/SettingsProvider/AndroidManifest.xml
@@ -2,8 +2,6 @@
         package="com.android.providers.settings"
         android:sharedUserId="android.uid.system">
 
-    <uses-permission android:name="android.permission.BACKUP_DATA" />
-
     <application android:allowClearUserData="false"
                  android:label="@string/app_label"
                  android:process="system"
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 7686aa0..654ca32 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -56,5 +56,18 @@
     <bool name="def_mount_ums_autostart">false</bool>
     <bool name="def_mount_ums_prompt">true</bool>
     <bool name="def_mount_ums_notify_enabled">true</bool>
+    <bool name="set_install_location">true</bool>
+
+    <!-- user interface sound effects -->
+    <integer name="def_power_sounds_enabled">1</integer>
+    <string name="def_low_battery_sound">/system/media/ui/LowBattery.ogg</string>
+    <integer name="def_dock_sounds_enabled">1</integer>
+    <string name="def_desk_dock_sound">/system/media/audio/ui/dock.ogg</string>
+    <string name="def_desk_undock_sound">/system/media/audio/ui/undock.ogg</string>
+    <string name="def_car_dock_sound">/system/media/audio/ui/Dock.ogg</string>
+    <string name="def_car_undock_sound">/system/media/audio/ui/Undock.ogg</string>
+    <integer name="def_lockscreen_sounds_enabled">1</integer>
+    <string name="def_lock_sound">/system/media/audio/ui/Lock.ogg</string>
+    <string name="def_unlock_sound">/system/media/audio/ui/Unlock.ogg</string>
 
 </resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 015b487..cf34d4e 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -21,7 +21,10 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
 import android.content.res.Resources;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
@@ -35,6 +38,8 @@
 import android.os.Environment;
 import android.os.SystemProperties;
 import android.provider.Settings;
+import android.speech.RecognitionService;
+import android.speech.RecognizerIntent;
 import android.text.TextUtils;
 import android.util.Config;
 import android.util.Log;
@@ -71,7 +76,7 @@
     // database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
     // is properly propagated through your change.  Not doing so will result in a loss of user
     // settings.
-    private static final int DATABASE_VERSION = 48;
+    private static final int DATABASE_VERSION = 50;
 
     private Context mContext;
 
@@ -595,7 +600,7 @@
            upgradeVersion = 47;
        }
 
-        
+
         if (upgradeVersion == 47) {
             /*
              * The password mode constants have changed again; reset back to no
@@ -611,6 +616,41 @@
            upgradeVersion = 48;
        }
 
+       if (upgradeVersion == 48) {
+           /*
+            * Adding a new setting for which voice recognition service to use.
+            */
+           db.beginTransaction();
+           try {
+               SQLiteStatement stmt = db.compileStatement("INSERT OR IGNORE INTO secure(name,value)"
+                       + " VALUES(?,?);");
+               loadVoiceRecognitionServiceSetting(stmt);
+               stmt.close();
+               db.setTransactionSuccessful();
+           } finally {
+               db.endTransaction();
+           }
+           upgradeVersion = 49;
+       }
+
+       if (upgradeVersion == 49) {
+           /*
+            * New settings for new user interface noises.
+            */
+           db.beginTransaction();
+           try {
+                SQLiteStatement stmt = db.compileStatement("INSERT INTO system(name,value)"
+                        + " VALUES(?,?);");
+                loadUISoundEffectsSettings(stmt);
+                stmt.close();
+                db.setTransactionSuccessful();
+            } finally {
+                db.endTransaction();
+            }
+
+           upgradeVersion = 50;
+       }
+
        if (upgradeVersion != currentVersion) {
             Log.w(TAG, "Got stuck trying to upgrade from version " + upgradeVersion
                     + ", must wipe the settings provider");
@@ -626,6 +666,11 @@
             db.execSQL("DROP INDEX IF EXISTS bookmarksIndex2");
             db.execSQL("DROP TABLE IF EXISTS favorites");
             onCreate(db);
+
+            // Added for diagnosing settings.db wipes after the fact
+            String wipeReason = oldVersion + "/" + upgradeVersion + "/" + currentVersion;
+            db.execSQL("INSERT INTO secure(name,value) values('" +
+                    "wiped_db_reason" + "','" + wipeReason + "');");
         }
     }
 
@@ -864,9 +909,40 @@
 
         loadBooleanSetting(stmt, Settings.System.NOTIFICATION_LIGHT_PULSE,
                 R.bool.def_notification_pulse);
+        loadBooleanSetting(stmt, Settings.System.SET_INSTALL_LOCATION, R.bool.set_install_location);
+        loadSetting(stmt, Settings.System.DEFAULT_INSTALL_LOCATION,
+                PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
+
+        loadUISoundEffectsSettings(stmt);
+
         stmt.close();
     }
 
+    private void loadUISoundEffectsSettings(SQLiteStatement stmt) {
+        loadIntegerSetting(stmt, Settings.System.POWER_SOUNDS_ENABLED,
+            R.integer.def_power_sounds_enabled);
+        loadStringSetting(stmt, Settings.System.LOW_BATTERY_SOUND,
+            R.string.def_low_battery_sound);
+
+        loadIntegerSetting(stmt, Settings.System.DOCK_SOUNDS_ENABLED,
+            R.integer.def_dock_sounds_enabled);
+        loadStringSetting(stmt, Settings.System.DESK_DOCK_SOUND,
+            R.string.def_desk_dock_sound);
+        loadStringSetting(stmt, Settings.System.DESK_UNDOCK_SOUND,
+            R.string.def_desk_undock_sound);
+        loadStringSetting(stmt, Settings.System.CAR_DOCK_SOUND,
+            R.string.def_car_dock_sound);
+        loadStringSetting(stmt, Settings.System.CAR_UNDOCK_SOUND,
+            R.string.def_car_undock_sound);
+
+        loadIntegerSetting(stmt, Settings.System.LOCKSCREEN_SOUNDS_ENABLED,
+            R.integer.def_lockscreen_sounds_enabled);
+        loadStringSetting(stmt, Settings.System.LOCK_SOUND,
+            R.string.def_lock_sound);
+        loadStringSetting(stmt, Settings.System.UNLOCK_SOUND,
+            R.string.def_unlock_sound);
+    }
+
     private void loadDefaultAnimationSettings(SQLiteStatement stmt) {
         loadFractionSetting(stmt, Settings.System.WINDOW_ANIMATION_SCALE,
                 R.fraction.def_window_animation_scale, 1);
@@ -952,6 +1028,8 @@
         loadBooleanSetting(stmt, Settings.Secure.MOUNT_UMS_NOTIFY_ENABLED,
                 R.bool.def_mount_ums_notify_enabled);
 
+        loadVoiceRecognitionServiceSetting(stmt);
+
         stmt.close();
     }
 
@@ -963,6 +1041,32 @@
                 R.string.def_backup_transport);
     }
 
+    /**
+     * Introduced in database version 49.
+     */
+    private void loadVoiceRecognitionServiceSetting(SQLiteStatement stmt) {
+        String selectedService = null;
+        List<ResolveInfo> availableRecognitionServices =
+                mContext.getPackageManager().queryIntentServices(
+                        new Intent(RecognitionService.SERVICE_INTERFACE), 0);
+        int numAvailable = availableRecognitionServices.size();
+
+        if (numAvailable == 0) {
+            Log.w(TAG, "no available voice recognition services found");
+        } else {
+            if (numAvailable > 1) {
+                Log.w(TAG, "more than one voice recognition service found, picking first");
+            }
+
+            ServiceInfo serviceInfo = availableRecognitionServices.get(0).serviceInfo;
+            selectedService =
+                    new ComponentName(serviceInfo.packageName, serviceInfo.name).flattenToString();
+        }
+
+        loadSetting(stmt, Settings.Secure.VOICE_RECOGNITION_SERVICE,
+                selectedService == null ? "" : selectedService);
+    }
+
     private void loadSetting(SQLiteStatement stmt, String key, Object value) {
         stmt.bindString(1, key);
         stmt.bindString(2, value.toString());
diff --git a/packages/TtsService/src/android/tts/TtsService.java b/packages/TtsService/src/android/tts/TtsService.java
index bca736a2e..c0e4cc0 100755
--- a/packages/TtsService/src/android/tts/TtsService.java
+++ b/packages/TtsService/src/android/tts/TtsService.java
@@ -824,11 +824,15 @@
                 try {
                     synthAvailable = synthesizerLock.tryLock();
                     if (!synthAvailable) {
-                        mSynthBusy = true;
+                        synchronized (this) {
+                            mSynthBusy = true;
+                        }
                         Thread.sleep(100);
                         Thread synth = (new Thread(new SynthThread()));
                         synth.start();
-                        mSynthBusy = false;
+                        synchronized (this) {
+                            mSynthBusy = false;
+                        }
                         return;
                     }
                     String language = "";
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index f336d1f..0b466f1 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -573,7 +573,7 @@
         List<ResolveInfo> broadcastReceivers = pm.queryBroadcastReceivers(intent,
                 PackageManager.GET_META_DATA);
 
-        final int N = broadcastReceivers.size();
+        final int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
         for (int i=0; i<N; i++) {
             ResolveInfo ri = broadcastReceivers.get(i);
             addProviderLocked(ri);
@@ -1137,7 +1137,7 @@
         List<ResolveInfo> broadcastReceivers = mPackageManager.queryBroadcastReceivers(intent,
                 PackageManager.GET_META_DATA);
 
-        final int N = broadcastReceivers.size();
+        final int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
         for (int i=0; i<N; i++) {
             ResolveInfo ri = broadcastReceivers.get(i);
             ActivityInfo ai = ri.activityInfo;
@@ -1156,7 +1156,7 @@
                 PackageManager.GET_META_DATA);
 
         // add the missing ones and collect which ones to keep
-        int N = broadcastReceivers.size();
+        int N = broadcastReceivers == null ? 0 : broadcastReceivers.size();
         for (int i=0; i<N; i++) {
             ResolveInfo ri = broadcastReceivers.get(i);
             ActivityInfo ai = ri.activityInfo;
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 27055ed..a7a6df5 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -896,9 +896,7 @@
             try {
                 ApplicationInfo app = pkg.applicationInfo;
                 if (((app.flags&ApplicationInfo.FLAG_ALLOW_BACKUP) == 0)
-                        || app.backupAgentName == null
-                        || (mPackageManager.checkPermission(android.Manifest.permission.BACKUP_DATA,
-                                pkg.packageName) != PackageManager.PERMISSION_GRANTED)) {
+                        || app.backupAgentName == null) {
                     packages.remove(a);
                 }
                 else {
@@ -1282,15 +1280,6 @@
             for (BackupRequest request : mQueue) {
                 Log.d(TAG, "starting agent for backup of " + request);
 
-                // Don't run backup, even if requested, if the target app does not have
-                // the requisite permission
-                if (mPackageManager.checkPermission(android.Manifest.permission.BACKUP_DATA,
-                        request.appInfo.packageName) != PackageManager.PERMISSION_GRANTED) {
-                    Log.w(TAG, "Skipping backup of unprivileged package "
-                            + request.appInfo.packageName);
-                    continue;
-                }
-
                 IBackupAgent agent = null;
                 int mode = (request.fullBackup)
                         ? IApplicationThread.BACKUP_MODE_FULL
@@ -1760,12 +1749,6 @@
 
             if (DEBUG) Log.d(TAG, "processOneRestore packageName=" + packageName);
 
-            // Don't restore to unprivileged packages
-            if (mPackageManager.checkPermission(android.Manifest.permission.BACKUP_DATA,
-                    packageName) != PackageManager.PERMISSION_GRANTED) {
-                Log.d(TAG, "Skipping restore of unprivileged package " + packageName);
-            }
-
             // !!! TODO: get the dirs from the transport
             File backupDataName = new File(mDataDir, packageName + ".restore");
             File newStateName = new File(mStateDir, packageName + ".new");
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java
index f435ebc..dc41ff9 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/java/com/android/server/BatteryService.java
@@ -27,11 +27,11 @@
 import android.os.BatteryManager;
 import android.os.Binder;
 import android.os.IBinder;
+import android.os.DropBoxManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UEventObserver;
-import android.provider.Checkin;
 import android.provider.Settings;
 import android.util.EventLog;
 import android.util.Log;
@@ -363,50 +363,39 @@
     }
 
     private final void logBatteryStats() {
-
         IBinder batteryInfoService = ServiceManager.getService(BATTERY_STATS_SERVICE_NAME);
-        if (batteryInfoService != null) {
-            byte[] buffer = new byte[DUMP_MAX_LENGTH];
-            File dumpFile = null;
-            FileOutputStream dumpStream = null;
-            try {
-                // dump the service to a file
-                dumpFile = new File(DUMPSYS_DATA_PATH + BATTERY_STATS_SERVICE_NAME + ".dump");
-                dumpStream = new FileOutputStream(dumpFile);
-                batteryInfoService.dump(dumpStream.getFD(), DUMPSYS_ARGS);
-                dumpStream.getFD().sync();
+        if (batteryInfoService == null) return;
 
-                // read dumped file above into buffer truncated to DUMP_MAX_LENGTH
-                // and insert into events table.
-                int length = (int) Math.min(dumpFile.length(), DUMP_MAX_LENGTH);
-                FileInputStream fileInputStream = new FileInputStream(dumpFile);
-                int nread = fileInputStream.read(buffer, 0, length);
-                if (nread > 0) {
-                    Checkin.logEvent(mContext.getContentResolver(),
-                            Checkin.Events.Tag.BATTERY_DISCHARGE_INFO,
-                            new String(buffer, 0, nread));
-                    if (LOCAL_LOGV) Log.v(TAG, "dumped " + nread + "b from " +
-                            batteryInfoService + "to log");
-                    if (LOCAL_LOGV) Log.v(TAG, "actual dump:" + new String(buffer, 0, nread));
+        DropBoxManager db = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE);
+        if (db == null || !db.isTagEnabled("BATTERY_DISCHARGE_INFO")) return;
+
+        File dumpFile = null;
+        FileOutputStream dumpStream = null;
+        try {
+            // dump the service to a file
+            dumpFile = new File(DUMPSYS_DATA_PATH + BATTERY_STATS_SERVICE_NAME + ".dump");
+            dumpStream = new FileOutputStream(dumpFile);
+            batteryInfoService.dump(dumpStream.getFD(), DUMPSYS_ARGS);
+            dumpStream.getFD().sync();
+
+            // add dump file to drop box
+            db.addFile("BATTERY_DISCHARGE_INFO", dumpFile, DropBoxManager.IS_TEXT);
+        } catch (RemoteException e) {
+            Log.e(TAG, "failed to dump battery service", e);
+        } catch (IOException e) {
+            Log.e(TAG, "failed to write dumpsys file", e);
+        } finally {
+            // make sure we clean up
+            if (dumpStream != null) {
+                try {
+                    dumpStream.close();
+                } catch (IOException e) {
+                    Log.e(TAG, "failed to close dumpsys output stream");
                 }
-            } catch (RemoteException e) {
-                Log.e(TAG, "failed to dump service '" + BATTERY_STATS_SERVICE_NAME +
-                        "':" + e);
-            } catch (IOException e) {
-                Log.e(TAG, "failed to write dumpsys file: " +  e);
-            } finally {
-                // make sure we clean up
-                if (dumpStream != null) {
-                    try {
-                        dumpStream.close();
-                    } catch (IOException e) {
-                        Log.e(TAG, "failed to close dumpsys output stream");
-                    }
-                }
-                if (dumpFile != null && !dumpFile.delete()) {
-                    Log.e(TAG, "failed to delete temporary dumpsys file: "
-                            + dumpFile.getAbsolutePath());
-                }
+            }
+            if (dumpFile != null && !dumpFile.delete()) {
+                Log.e(TAG, "failed to delete temporary dumpsys file: "
+                        + dumpFile.getAbsolutePath());
             }
         }
     }
diff --git a/services/java/com/android/server/BootReceiver.java b/services/java/com/android/server/BootReceiver.java
index 1dbd0ae..5c1af7e 100644
--- a/services/java/com/android/server/BootReceiver.java
+++ b/services/java/com/android/server/BootReceiver.java
@@ -40,8 +40,8 @@
 public class BootReceiver extends BroadcastReceiver {
     private static final String TAG = "BootReceiver";
 
-    // Negative to read the *last* 64K of the file (per FileUtils.readTextFile)
-    private static final int LOG_SIZE = -65536;
+    // Maximum size of a logged event (files get truncated if they're longer)
+    private static final int LOG_SIZE = 65536;
 
     private static final File TOMBSTONE_DIR = new File("/data/tombstones");
 
@@ -92,10 +92,16 @@
             String now = Long.toString(System.currentTimeMillis());
             SystemProperties.set("ro.runtime.firstboot", now);
             db.addText("SYSTEM_BOOT", props);
-            addFileToDropBox(db, prefs, props, "/proc/last_kmsg", "SYSTEM_LAST_KMSG");
-            addFileToDropBox(db, prefs, props, "/cache/recovery/log", "SYSTEM_RECOVERY_LOG");
-            addFileToDropBox(db, prefs, props, "/data/dontpanic/apanic_console", "APANIC_CONSOLE");
-            addFileToDropBox(db, prefs, props, "/data/dontpanic/apanic_threads", "APANIC_THREADS");
+
+            // Negative sizes mean to take the *tail* of the file (see FileUtils.readTextFile())
+            addFileToDropBox(db, prefs, props, "/proc/last_kmsg",
+                    -LOG_SIZE, "SYSTEM_LAST_KMSG");
+            addFileToDropBox(db, prefs, props, "/cache/recovery/log",
+                    -LOG_SIZE, "SYSTEM_RECOVERY_LOG");
+            addFileToDropBox(db, prefs, props, "/data/dontpanic/apanic_console",
+                    -LOG_SIZE, "APANIC_CONSOLE");
+            addFileToDropBox(db, prefs, props, "/data/dontpanic/apanic_threads",
+                    -LOG_SIZE, "APANIC_THREADS");
         } else {
             db.addText("SYSTEM_RESTART", props);
         }
@@ -103,7 +109,8 @@
         // Scan existing tombstones (in case any new ones appeared)
         File[] tombstoneFiles = TOMBSTONE_DIR.listFiles();
         for (int i = 0; tombstoneFiles != null && i < tombstoneFiles.length; i++) {
-            addFileToDropBox(db, prefs, props, tombstoneFiles[i].getPath(), "SYSTEM_TOMBSTONE");
+            addFileToDropBox(db, prefs, props, tombstoneFiles[i].getPath(),
+                    LOG_SIZE, "SYSTEM_TOMBSTONE");
         }
 
         // Start watching for new tombstone files; will record them as they occur.
@@ -113,7 +120,7 @@
             public void onEvent(int event, String path) {
                 try {
                     String filename = new File(TOMBSTONE_DIR, path).getPath();
-                    addFileToDropBox(db, prefs, props, filename, "SYSTEM_TOMBSTONE");
+                    addFileToDropBox(db, prefs, props, filename, LOG_SIZE, "SYSTEM_TOMBSTONE");
                 } catch (IOException e) {
                     Log.e(TAG, "Can't log tombstone", e);
                 }
@@ -125,7 +132,7 @@
 
     private static void addFileToDropBox(
             DropBoxManager db, SharedPreferences prefs,
-            String headers, String filename, String tag) throws IOException {
+            String headers, String filename, int maxSize, String tag) throws IOException {
         if (!db.isTagEnabled(tag)) return;  // Logging disabled
 
         File file = new File(filename);
@@ -137,7 +144,7 @@
         prefs.edit().putLong(filename, fileTime).commit();
 
         StringBuilder report = new StringBuilder(headers).append("\n");
-        report.append(FileUtils.readTextFile(file, LOG_SIZE, "[[TRUNCATED]]\n"));
+        report.append(FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n"));
         db.addText(tag, report.toString());
         Log.i(TAG, "Logging " + filename + " to DropBox (" + tag + ")");
     }
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index 1625d9f..0a6c72e 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -608,7 +608,7 @@
                 throw new NullPointerException("ComponentName is null");
             }
             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
-                    DeviceAdminInfo.USES_POLICY_LIMIT_UNLOCK);
+                    DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
             if (ap.maximumTimeToUnlock != timeMs) {
                 ap.maximumTimeToUnlock = timeMs;
                 
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
index 363e93e..d280475 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -17,15 +17,27 @@
 package com.android.server;
 
 import android.app.Activity;
+import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
+import android.app.IUiModeManager;
 import android.app.KeyguardManager;
+import android.app.StatusBarManager;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.content.ActivityNotFoundException;
 import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Configuration;
+import android.os.Binder;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
 import android.os.Handler;
 import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UEventObserver;
 import android.provider.Settings;
@@ -47,7 +59,16 @@
     private static final String DOCK_UEVENT_MATCH = "DEVPATH=/devices/virtual/switch/dock";
     private static final String DOCK_STATE_PATH = "/sys/class/switch/dock/state";
 
+    public static final int MODE_NIGHT_AUTO = Configuration.UI_MODE_NIGHT_MASK >> 4;
+    public static final int MODE_NIGHT_NO = Configuration.UI_MODE_NIGHT_NO >> 4;
+    public static final int MODE_NIGHT_YES = Configuration.UI_MODE_NIGHT_YES >> 4;
+
     private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
+    private int mPreviousDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
+
+    private int mNightMode = MODE_NIGHT_NO;
+    private boolean mCarModeEnabled = false;
+
     private boolean mSystemReady;
 
     private final Context mContext;
@@ -58,6 +79,8 @@
     private boolean mKeyguardDisabled;
     private LockPatternUtils mLockPatternUtils;
 
+    private StatusBarManager mStatusBarManager;    
+
     // The broadcast receiver which receives the result of the ordered broadcast sent when
     // the dock state changes. The original ordered broadcast is sent with an initial result
     // code of RESULT_OK. If any of the registered broadcast receivers changes this value, e.g.,
@@ -71,16 +94,12 @@
 
             // Launch a dock activity
             String category;
-            switch (mDockState) {
-                case Intent.EXTRA_DOCK_STATE_CAR:
-                    category = Intent.CATEGORY_CAR_DOCK;
-                    break;
-                case Intent.EXTRA_DOCK_STATE_DESK:
-                    category = Intent.CATEGORY_DESK_DOCK;
-                    break;
-                default:
-                    category = null;
-                    break;
+            if (mCarModeEnabled || mDockState == Intent.EXTRA_DOCK_STATE_CAR) {
+                category = Intent.CATEGORY_CAR_DOCK;
+            } else if (mDockState == Intent.EXTRA_DOCK_STATE_DESK) {
+                category = Intent.CATEGORY_DESK_DOCK;
+            } else {
+                category = null;
             }
             if (category != null) {
                 intent = new Intent(Intent.ACTION_MAIN);
@@ -101,6 +120,9 @@
         mPowerManager = pm;
         mLockPatternUtils = new LockPatternUtils(context);
         init();  // set initial status
+
+        ServiceManager.addService("uimode", mBinder);
+
         startObserving(DOCK_UEVENT_MATCH);
     }
 
@@ -114,14 +136,22 @@
             try {
                 int newState = Integer.parseInt(event.get("SWITCH_STATE"));
                 if (newState != mDockState) {
-                    int oldState = mDockState;
+                    mPreviousDockState = mDockState;
                     mDockState = newState;
+                    boolean carModeEnabled = mDockState == Intent.EXTRA_DOCK_STATE_CAR;
+                    if (mCarModeEnabled != carModeEnabled) {
+                        try {
+                            setCarMode(carModeEnabled);
+                        } catch (RemoteException e1) {
+                            Log.w(TAG, "Unable to change car mode.", e1);
+                        }
+                    }
                     if (mSystemReady) {
                         // Don't force screen on when undocking from the desk dock.
                         // The change in power state will do this anyway.
                         // FIXME - we should be configurable.
-                        if (oldState != Intent.EXTRA_DOCK_STATE_DESK ||
-                                newState != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
+                        if (mPreviousDockState != Intent.EXTRA_DOCK_STATE_DESK ||
+                                mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
                             mPowerManager.userActivityWithForce(SystemClock.uptimeMillis(),
                                     false, true);
                         }
@@ -140,7 +170,7 @@
         try {
             FileReader file = new FileReader(DOCK_STATE_PATH);
             int len = file.read(buffer, 0, 1024);
-            mDockState = Integer.valueOf((new String(buffer, 0, len)).trim());
+            mPreviousDockState = mDockState = Integer.valueOf((new String(buffer, 0, len)).trim());
 
         } catch (FileNotFoundException e) {
             Log.w(TAG, "This kernel does not have dock station support");
@@ -172,7 +202,10 @@
         public void handleMessage(Message msg) {
             synchronized (this) {
                 Log.i(TAG, "Dock state changed: " + mDockState);
-                if (Settings.Secure.getInt(mContext.getContentResolver(),
+
+                final ContentResolver cr = mContext.getContentResolver();
+
+                if (Settings.Secure.getInt(cr,
                         Settings.Secure.DEVICE_PROVISIONED, 0) == 0) {
                     Log.i(TAG, "Device not provisioned, skipping dock broadcast");
                     return;
@@ -180,7 +213,13 @@
                 // Pack up the values and broadcast them to everyone
                 Intent intent = new Intent(Intent.ACTION_DOCK_EVENT);
                 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
-                intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
+                if (mCarModeEnabled && mDockState != Intent.EXTRA_DOCK_STATE_CAR) {
+                    // Pretend to be in DOCK_STATE_CAR.
+                    intent.putExtra(Intent.EXTRA_DOCK_STATE, Intent.EXTRA_DOCK_STATE_CAR);
+                } else {
+                    intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
+                }
+                intent.putExtra(Intent.EXTRA_CAR_MODE_ENABLED, mCarModeEnabled);
 
                 // Check if this is Bluetooth Dock
                 String address = BluetoothService.readDockBluetoothAddress();
@@ -188,6 +227,38 @@
                     intent.putExtra(BluetoothDevice.EXTRA_DEVICE,
                             BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address));
 
+                // User feedback to confirm dock connection. Particularly
+                // useful for flaky contact pins...
+                if (Settings.System.getInt(cr,
+                        Settings.System.DOCK_SOUNDS_ENABLED, 1) == 1)
+                {
+                    String whichSound = null;
+                    if (mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
+                        if (mPreviousDockState == Intent.EXTRA_DOCK_STATE_DESK) {
+                            whichSound = Settings.System.DESK_UNDOCK_SOUND;
+                        } else if (mPreviousDockState == Intent.EXTRA_DOCK_STATE_CAR) {
+                            whichSound = Settings.System.CAR_UNDOCK_SOUND;
+                        }
+                    } else {
+                        if (mDockState == Intent.EXTRA_DOCK_STATE_DESK) {
+                            whichSound = Settings.System.DESK_DOCK_SOUND;
+                        } else if (mDockState == Intent.EXTRA_DOCK_STATE_CAR) {
+                            whichSound = Settings.System.CAR_DOCK_SOUND;
+                        }
+                    }
+
+                    if (whichSound != null) {
+                        final String soundPath = Settings.System.getString(cr, whichSound);
+                        if (soundPath != null) {
+                            final Uri soundUri = Uri.parse("file://" + soundPath);
+                            if (soundUri != null) {
+                                final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
+                                if (sfx != null) sfx.play();
+                            }
+                        }
+                    }
+                }
+
                 // Send the ordered broadcast; the result receiver will receive after all
                 // broadcasts have been sent. If any broadcast receiver changes the result
                 // code from the initial value of RESULT_OK, then the result receiver will
@@ -199,4 +270,91 @@
             }
         }
     };
+
+    private void setCarMode(boolean enabled) throws RemoteException {
+        mCarModeEnabled = enabled;
+        if (enabled) {
+            setMode(Configuration.UI_MODE_TYPE_CAR, mNightMode);
+        } else {
+            // Disabling the car mode clears the night mode.
+            setMode(Configuration.UI_MODE_TYPE_NORMAL, MODE_NIGHT_NO);
+        }
+
+        if (mStatusBarManager == null) {
+            mStatusBarManager = (StatusBarManager) mContext.getSystemService(Context.STATUS_BAR_SERVICE);
+        }
+
+        // Fear not: StatusBarService manages a list of requests to disable
+        // features of the status bar; these are ORed together to form the
+        // active disabled list. So if (for example) the device is locked and
+        // the status bar should be totally disabled, the calls below will
+        // have no effect until the device is unlocked.
+        if (mStatusBarManager != null) {
+            mStatusBarManager.disable(enabled 
+                ? StatusBarManager.DISABLE_NOTIFICATION_TICKER
+                : StatusBarManager.DISABLE_NONE);
+        }
+    }
+
+    private void setMode(int modeType, int modeNight) throws RemoteException {
+        final IActivityManager am = ActivityManagerNative.getDefault();
+        Configuration config = am.getConfiguration();
+
+        if (config.uiMode != (modeType | modeNight)) {
+            config.uiMode = modeType | modeNight;
+            long ident = Binder.clearCallingIdentity();
+            am.updateConfiguration(config);
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    private void setNightMode(int mode) throws RemoteException {
+        mNightMode = mode;
+        switch (mode) {
+            case MODE_NIGHT_NO:
+            case MODE_NIGHT_YES:
+                setMode(Configuration.UI_MODE_TYPE_CAR, mode << 4);
+                break;
+            case MODE_NIGHT_AUTO:
+                // FIXME: not yet supported, this functionality will be
+                // added in a separate change.
+                break;
+            default:
+                setMode(Configuration.UI_MODE_TYPE_CAR, MODE_NIGHT_NO << 4);
+                break;
+        }
+    }
+
+    /**
+     * Wrapper class implementing the IUiModeManager interface.
+     */
+    private final IUiModeManager.Stub mBinder = new IUiModeManager.Stub() {
+
+        public void disableCarMode() throws RemoteException {
+            if (mCarModeEnabled) {
+                setCarMode(false);
+                update();
+            }
+        }
+
+        public void enableCarMode() throws RemoteException {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.ENABLE_CAR_MODE,
+                    "Need ENABLE_CAR_MODE permission");
+            if (!mCarModeEnabled) {
+                setCarMode(true);
+                update();
+            }
+        }
+
+        public void setNightMode(int mode) throws RemoteException {
+            if (mCarModeEnabled) {
+                DockObserver.this.setNightMode(mode);
+            }
+        }
+
+        public int getNightMode() throws RemoteException {
+            return mNightMode;
+        }
+    };
 }
diff --git a/services/java/com/android/server/FallbackCheckinService.java b/services/java/com/android/server/FallbackCheckinService.java
deleted file mode 100644
index fc0ab69..0000000
--- a/services/java/com/android/server/FallbackCheckinService.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-package com.android.server;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Binder;
-import android.os.ICheckinService;
-import android.os.IParentalControlCallback;
-import android.os.RecoverySystem;
-import android.util.Log;
-
-import java.io.IOException;
-
-import com.google.android.net.ParentalControlState;
-
-/**
- * @hide
- */
-public final class FallbackCheckinService extends ICheckinService.Stub {
-    static final String TAG = "FallbackCheckinService";
-    final Context mContext;
-
-    public FallbackCheckinService(Context context) {
-        mContext = context;
-    }
-
-    public void masterClear() {
-        if (mContext.checkCallingOrSelfPermission("android.permission.MASTER_CLEAR") !=
-                PackageManager.PERMISSION_GRANTED) {
-            Log.e(TAG, "Permission Denial: can't invoke masterClear from "
-                    + "pid=" + Binder.getCallingPid() + ", "
-                    + "uid=" + Binder.getCallingUid());
-            return;
-        }
-
-        // Save the android ID so the new system can get it erased.
-        try {
-            RecoverySystem.rebootWipeUserData(mContext);
-        } catch (IOException e) {
-            Log.e(TAG, "Reboot for masterClear() failed", e);
-        }
-    }
-
-    public void masterClearAndToggleEFS(boolean efsEnabled) {
-        if (mContext.checkCallingOrSelfPermission("android.permission.MASTER_CLEAR") !=
-			PackageManager.PERMISSION_GRANTED) {
-            Log.e(TAG, "Permission Denial: can't invoke masterClearAndToggleEFS from "
-				  + "pid=" + Binder.getCallingPid() + ", "
-				  + "uid=" + Binder.getCallingUid());
-            return;
-        }
-
-        // Save the android ID so the new system can get it erased.
-        try {
-            RecoverySystem.rebootToggleEFS(mContext, efsEnabled);
-        } catch (IOException e) {
-            Log.e(TAG, "Reboot for toggle EFS failed", e);
-        }
-    }
-
-    public void getParentalControlState(IParentalControlCallback p, String requestingApp)
-            throws android.os.RemoteException {
-        ParentalControlState state = new ParentalControlState();
-        state.isEnabled = false;
-        p.onResult(state);
-    }
-}
diff --git a/services/java/com/android/server/HeadsetObserver.java b/services/java/com/android/server/HeadsetObserver.java
index c94450b..9d69564 100644
--- a/services/java/com/android/server/HeadsetObserver.java
+++ b/services/java/com/android/server/HeadsetObserver.java
@@ -53,19 +53,6 @@
     private final Context mContext;
     private final WakeLock mWakeLock;  // held while there is a pending route change
 
-    private boolean mHandleTTY;
-    private int mTTYState;
-    private AudioManager mAudioManager = null;
-
-    // special use of bits in headset state received from kernel made by some
-    // platforms to indicate changes in TTY mode.
-    private static final int BIT_TTY_OFF = 0;
-    private static final int BIT_TTY_FULL = (1 << 2);
-    private static final int BIT_TTY_VCO = (1 << 5);
-    private static final int BIT_TTY_HCO = (1 << 6);
-    private static final int TTY_BITS_MASK = (BIT_TTY_FULL | BIT_TTY_VCO | BIT_TTY_HCO);
-
-
     public HeadsetObserver(Context context) {
         mContext = context;
         PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
@@ -74,11 +61,6 @@
 
         startObserving(HEADSET_UEVENT_MATCH);
 
-        // read settings for TTY mode indication method
-        mHandleTTY = context.getResources().getBoolean(
-                com.android.internal.R.bool.tty_mode_uses_headset_events);
-        mTTYState = BIT_TTY_OFF;
-
         init();  // set initial status
     }
 
@@ -118,39 +100,6 @@
     }
 
     private synchronized final void update(String newName, int newState) {
-        // handle TTY state change first
-        if (mHandleTTY) {
-            int ttyState = newState  & TTY_BITS_MASK;
-            if (ttyState != mTTYState) {
-                String ttyMode;
-
-                switch (ttyState) {
-                case BIT_TTY_FULL:
-                    ttyMode = "tty_full";
-                    break;
-                case BIT_TTY_VCO:
-                    ttyMode = "tty_vco";
-                    break;
-                case BIT_TTY_HCO:
-                    ttyMode = "tty_hco";
-                    break;
-                case BIT_TTY_OFF:
-                    ttyMode = "tty_off";
-                    break;
-                default:
-                    ttyMode = "tty_invalid";
-                    break;
-
-                }
-                if (ttyMode != "tty_invalid") {
-                    mTTYState = ttyState;
-                    if (mAudioManager == null) {
-                        mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
-                    }
-                    mAudioManager.setParameters("tty_mode="+ttyMode);
-                }
-            }
-        }
         // Retain only relevant bits
         int headsetState = newState & SUPPORTED_HEADSETS;
         int newOrOld = headsetState | mHeadsetState;
diff --git a/services/java/com/android/server/InputDevice.java b/services/java/com/android/server/InputDevice.java
index 6f207e0..d3bb6dc 100644
--- a/services/java/com/android/server/InputDevice.java
+++ b/services/java/com/android/server/InputDevice.java
@@ -570,14 +570,14 @@
                         mDownTime = curTime;
                     } else {
                         action = MotionEvent.ACTION_POINTER_DOWN
-                                | (upOrDownPointer << MotionEvent.ACTION_POINTER_ID_SHIFT);
+                                | (upOrDownPointer << MotionEvent.ACTION_POINTER_INDEX_SHIFT);
                     }
                 } else {
                     if (numPointers == 1) {
                         action = MotionEvent.ACTION_UP;
                     } else {
                         action = MotionEvent.ACTION_POINTER_UP
-                                | (upOrDownPointer << MotionEvent.ACTION_POINTER_ID_SHIFT);
+                                | (upOrDownPointer << MotionEvent.ACTION_POINTER_INDEX_SHIFT);
                     }
                 }
                 currentMove = null;
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index fff6c54..e12f2e1 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -45,11 +45,11 @@
 import android.location.IGpsStatusProvider;
 import android.location.ILocationListener;
 import android.location.ILocationManager;
-import android.location.ILocationProvider;
 import android.location.INetInitiatedListener;
 import android.location.Location;
 import android.location.LocationManager;
 import android.location.LocationProvider;
+import android.location.LocationProviderInterface;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.net.Uri;
@@ -114,8 +114,8 @@
     private LocationWorkerHandler mLocationHandler;
 
     // Cache the real providers for use in addTestProvider() and removeTestProvider()
-     LocationProviderProxy mNetworkLocationProvider;
-     LocationProviderProxy mGpsLocationProvider;
+     LocationProviderInterface mNetworkLocationProvider;
+     LocationProviderInterface mGpsLocationProvider;
 
     // Handler messages
     private static final int MESSAGE_LOCATION_CHANGED = 1;
@@ -134,10 +134,10 @@
     /**
      * List of location providers.
      */
-    private final ArrayList<LocationProviderProxy> mProviders =
-        new ArrayList<LocationProviderProxy>();
-    private final HashMap<String, LocationProviderProxy> mProvidersByName
-        = new HashMap<String, LocationProviderProxy>();
+    private final ArrayList<LocationProviderInterface> mProviders =
+        new ArrayList<LocationProviderInterface>();
+    private final HashMap<String, LocationProviderInterface> mProvidersByName
+        = new HashMap<String, LocationProviderInterface>();
 
     /**
      * Object used internally for synchronization
@@ -411,12 +411,12 @@
         }
     }
 
-    private void addProvider(LocationProviderProxy provider) {
+    private void addProvider(LocationProviderInterface provider) {
         mProviders.add(provider);
         mProvidersByName.put(provider.getName(), provider);
     }
 
-    private void removeProvider(LocationProviderProxy provider) {
+    private void removeProvider(LocationProviderInterface provider) {
         mProviders.remove(provider);
         mProvidersByName.remove(provider.getName());
     }
@@ -445,13 +445,11 @@
         // Attempt to load "real" providers first
         if (GpsLocationProvider.isSupported()) {
             // Create a gps location provider
-            GpsLocationProvider provider = new GpsLocationProvider(mContext, this);
-            mGpsStatusProvider = provider.getGpsStatusProvider();
-            mNetInitiatedListener = provider.getNetInitiatedListener();
-            LocationProviderProxy proxy =
-                    new LocationProviderProxy(mContext, LocationManager.GPS_PROVIDER, provider);
-            addProvider(proxy);
-            mGpsLocationProvider = proxy;
+            GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this);
+            mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
+            mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
+            addProvider(gpsProvider);
+            mGpsLocationProvider = gpsProvider;
         }
 
         // initialize external network location and geocoder services
@@ -591,7 +589,7 @@
         }
         ArrayList<String> out = new ArrayList<String>(mProviders.size());
         for (int i = mProviders.size() - 1; i >= 0; i--) {
-            LocationProviderProxy p = mProviders.get(i);
+            LocationProviderInterface p = mProviders.get(i);
             out.add(p.getName());
         }
         return out;
@@ -616,7 +614,7 @@
         }
         ArrayList<String> out = new ArrayList<String>(mProviders.size());
         for (int i = mProviders.size() - 1; i >= 0; i--) {
-            LocationProviderProxy p = mProviders.get(i);
+            LocationProviderInterface p = mProviders.get(i);
             String name = p.getName();
             if (isAllowedProviderSafe(name)) {
                 if (enabledOnly && !isAllowedBySettingsLocked(name)) {
@@ -630,7 +628,7 @@
 
     private void updateProvidersLocked() {
         for (int i = mProviders.size() - 1; i >= 0; i--) {
-            LocationProviderProxy p = mProviders.get(i);
+            LocationProviderInterface p = mProviders.get(i);
             boolean isEnabled = p.isEnabled();
             String name = p.getName();
             boolean shouldBeEnabled = isAllowedBySettingsLocked(name);
@@ -647,7 +645,7 @@
     private void updateProviderListenersLocked(String provider, boolean enabled) {
         int listeners = 0;
 
-        LocationProviderProxy p = mProvidersByName.get(provider);
+        LocationProviderInterface p = mProvidersByName.get(provider);
         if (p == null) {
             return;
         }
@@ -837,8 +835,8 @@
             Log.v(TAG, "_requestLocationUpdates: listener = " + receiver);
         }
 
-        LocationProviderProxy proxy = mProvidersByName.get(provider);
-        if (proxy == null) {
+        LocationProviderInterface p = mProvidersByName.get(provider);
+        if (p == null) {
             throw new IllegalArgumentException("provider=" + provider);
         }
 
@@ -856,14 +854,14 @@
             }
 
             if (newUid) {
-                proxy.addListener(callingUid);
+                p.addListener(callingUid);
             }
 
             boolean isProviderEnabled = isAllowedBySettingsLocked(provider);
             if (isProviderEnabled) {
                 long minTimeForProvider = getMinTimeLocked(provider);
-                proxy.setMinTime(minTimeForProvider);
-                proxy.enableLocationTracking(true);
+                p.setMinTime(minTimeForProvider);
+                p.enableLocationTracking(true);
             } else {
                 // Notify the listener that updates are currently disabled
                 receiver.callProviderEnabledLocked(provider, false);
@@ -923,9 +921,9 @@
                 // Call dispose() on the obsolete update records.
                 for (UpdateRecord record : oldRecords.values()) {
                     if (!providerHasListener(record.mProvider, callingUid, receiver)) {
-                        LocationProviderProxy proxy = mProvidersByName.get(record.mProvider);
-                        if (proxy != null) {
-                            proxy.removeListener(callingUid);
+                        LocationProviderInterface p = mProvidersByName.get(record.mProvider);
+                        if (p != null) {
+                            p.removeListener(callingUid);
                         }
                     }
                     record.disposeLocked();
@@ -949,7 +947,7 @@
                     hasOtherListener = true;
                 }
 
-                LocationProviderProxy p = mProvidersByName.get(provider);
+                LocationProviderInterface p = mProvidersByName.get(provider);
                 if (p != null) {
                     if (hasOtherListener) {
                         p.setMinTime(getMinTimeLocked(provider));
@@ -1006,12 +1004,12 @@
         }
 
         synchronized (mLock) {
-            LocationProviderProxy proxy = mProvidersByName.get(provider);
-            if (proxy == null) {
+            LocationProviderInterface p = mProvidersByName.get(provider);
+            if (p == null) {
                 return false;
             }
     
-            return proxy.sendExtraCommand(command, extras);
+            return p.sendExtraCommand(command, extras);
         }
     }
 
@@ -1261,7 +1259,7 @@
             mProximityReceiver = new Receiver(mProximityListener);
 
             for (int i = mProviders.size() - 1; i >= 0; i--) {
-                LocationProviderProxy provider = mProviders.get(i);
+                LocationProviderInterface provider = mProviders.get(i);
                 requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityReceiver);
             }
         }
@@ -1311,7 +1309,7 @@
     }
 
     private Bundle _getProviderInfoLocked(String provider) {
-        LocationProviderProxy p = mProvidersByName.get(provider);
+        LocationProviderInterface p = mProvidersByName.get(provider);
         if (p == null || !p.isEnabled()) {
             return null;
         }
@@ -1359,7 +1357,7 @@
     private boolean _isProviderEnabledLocked(String provider) {
         checkPermissionsSafe(provider);
 
-        LocationProviderProxy p = mProvidersByName.get(provider);
+        LocationProviderInterface p = mProvidersByName.get(provider);
         if (p == null) {
             throw new IllegalArgumentException("provider=" + provider);
         }
@@ -1382,7 +1380,7 @@
     private Location _getLastKnownLocationLocked(String provider) {
         checkPermissionsSafe(provider);
 
-        LocationProviderProxy p = mProvidersByName.get(provider);
+        LocationProviderInterface p = mProvidersByName.get(provider);
         if (p == null) {
             throw new IllegalArgumentException("provider=" + provider);
         }
@@ -1424,7 +1422,7 @@
             return;
         }
 
-        LocationProviderProxy p = mProvidersByName.get(provider);
+        LocationProviderInterface p = mProvidersByName.get(provider);
         if (p == null) {
             return;
         }
@@ -1507,9 +1505,9 @@
 
                         // notify other providers of the new location
                         for (int i = mProviders.size() - 1; i >= 0; i--) {
-                            LocationProviderProxy proxy = mProviders.get(i);
-                            if (!provider.equals(proxy.getName())) {
-                                proxy.updateLocation(location);
+                            LocationProviderInterface p = mProviders.get(i);
+                            if (!provider.equals(p.getName())) {
+                                p.updateLocation(location);
                             }
                         }
 
@@ -1597,7 +1595,7 @@
                 // Notify location providers of current network state
                 synchronized (mLock) {
                     for (int i = mProviders.size() - 1; i >= 0; i--) {
-                        LocationProviderProxy provider = mProviders.get(i);
+                        LocationProviderInterface provider = mProviders.get(i);
                         if (provider.isEnabled() && provider.requiresNetwork()) {
                             provider.updateNetworkState(mNetworkState, info);
                         }
@@ -1698,16 +1696,16 @@
             // remove the real provider if we are replacing GPS or network provider
             if (LocationManager.GPS_PROVIDER.equals(name)
                     || LocationManager.NETWORK_PROVIDER.equals(name)) {
-                LocationProviderProxy proxy = mProvidersByName.get(name);
-                if (proxy != null) {
-                    proxy.enableLocationTracking(false);
-                    removeProvider(proxy);
+                LocationProviderInterface p = mProvidersByName.get(name);
+                if (p != null) {
+                    p.enableLocationTracking(false);
+                    removeProvider(p);
                 }
             }
             if (mProvidersByName.get(name) != null) {
                 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
             }
-            addProvider(new LocationProviderProxy(mContext, name, provider));
+            addProvider(provider);
             mMockProviders.put(name, provider);
             mLastKnownLocation.put(name, null);
             updateProvidersLocked();
diff --git a/services/java/com/android/server/MasterClearReceiver.java b/services/java/com/android/server/MasterClearReceiver.java
index 3c366da..ab0eb81 100644
--- a/services/java/com/android/server/MasterClearReceiver.java
+++ b/services/java/com/android/server/MasterClearReceiver.java
@@ -16,16 +16,15 @@
 
 package com.android.server;
 
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.BroadcastReceiver;
-import android.os.RemoteException;
-import android.os.ICheckinService;
-import android.os.ServiceManager;
+import android.os.RecoverySystem;
 import android.util.Log;
 
-public class MasterClearReceiver extends BroadcastReceiver {
+import java.io.IOException;
 
+public class MasterClearReceiver extends BroadcastReceiver {
     private static final String TAG = "MasterClear";
 
     @Override
@@ -36,18 +35,17 @@
                 return;
             }
         }
-        Log.w(TAG, "!!! FACTORY RESETTING DEVICE !!!");
-        ICheckinService service =
-            ICheckinService.Stub.asInterface(
-                ServiceManager.getService("checkin"));
-        if (service != null) {
-            try {
-                // This RPC should never return.
-                service.masterClear();
-            } catch (RemoteException e) {
-                Log.w("MasterClear",
-                      "Unable to invoke ICheckinService.masterClear()");
+
+        try {
+            Log.w(TAG, "!!! FACTORY RESET !!!");
+            if (intent.hasExtra("enableEFS")) {
+                RecoverySystem.rebootToggleEFS(context, intent.getBooleanExtra("enableEFS", false));
+            } else {
+                RecoverySystem.rebootWipeUserData(context);
             }
+            Log.wtf(TAG, "Still running after master clear?!");
+        } catch (IOException e) {
+            Log.e(TAG, "Can't perform master clear/factory reset", e);
         }
     }
 }
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 8d45033..e764bbb 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -37,6 +37,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 import java.util.ArrayList;
+import java.util.HashSet;
 
 import java.io.File;
 import java.io.FileReader;
@@ -116,6 +117,11 @@
     private boolean                               mBooted;
     private boolean                               mReady;
 
+    /**
+     * Private hash of currently mounted secure containers.
+     */
+    private HashSet<String> mAsecMountSet = new HashSet<String>();
+
     private void waitForReady() {
         while (mReady == false) {
             for (int retries = 5; retries > 0; retries--) {
@@ -537,7 +543,7 @@
             // call back will handle the status changes any way.
             int code = e.getCode();
             if (code == VoldResponseCode.OpFailedVolNotMounted) {
-                return StorageResultCode.OperationFailedVolumeNotMounted;
+                return StorageResultCode.OperationFailedStorageNotMounted;
             } else {
                 return StorageResultCode.OperationFailedInternalError;
             }
@@ -820,6 +826,12 @@
         } catch (NativeDaemonConnectorException e) {
             rc = StorageResultCode.OperationFailedInternalError;
         }
+
+        if (rc == StorageResultCode.OperationSucceeded) {
+            synchronized (mAsecMountSet) {
+                mAsecMountSet.add(id);
+            }
+        }
         return rc;
     }
 
@@ -830,6 +842,10 @@
         int rc = StorageResultCode.OperationSucceeded;
         try {
             mConnector.doCommand(String.format("asec finalize %s", id));
+            /*
+             * Finalization does a remount, so no need
+             * to update mAsecMountSet
+             */
         } catch (NativeDaemonConnectorException e) {
             rc = StorageResultCode.OperationFailedInternalError;
         }
@@ -847,6 +863,15 @@
         } catch (NativeDaemonConnectorException e) {
             rc = StorageResultCode.OperationFailedInternalError;
         }
+
+        if (rc == StorageResultCode.OperationSucceeded) {
+            synchronized (mAsecMountSet) {
+                if (mAsecMountSet.contains(id)) {
+                    mAsecMountSet.remove(id);
+                }
+            }
+        }
+
         return rc;
     }
    
@@ -855,6 +880,12 @@
         waitForReady();
         warnOnNotMounted();
 
+        synchronized (mAsecMountSet) {
+            if (mAsecMountSet.contains(id)) {
+                return StorageResultCode.OperationFailedStorageMounted;
+            }
+        }
+
         int rc = StorageResultCode.OperationSucceeded;
         String cmd = String.format("asec mount %s %s %d", id, key, ownerUid);
         try {
@@ -862,6 +893,12 @@
         } catch (NativeDaemonConnectorException e) {
             rc = StorageResultCode.OperationFailedInternalError;
         }
+
+        if (rc == StorageResultCode.OperationSucceeded) {
+            synchronized (mAsecMountSet) {
+                mAsecMountSet.add(id);
+            }
+        }
         return rc;
     }
 
@@ -870,6 +907,12 @@
         waitForReady();
         warnOnNotMounted();
 
+        synchronized (mAsecMountSet) {
+            if (!mAsecMountSet.contains(id)) {
+                return StorageResultCode.OperationFailedStorageNotMounted;
+            }
+         }
+
         int rc = StorageResultCode.OperationSucceeded;
         String cmd = String.format("asec unmount %s", id);
         try {
@@ -877,14 +920,36 @@
         } catch (NativeDaemonConnectorException e) {
             rc = StorageResultCode.OperationFailedInternalError;
         }
+
+        if (rc == StorageResultCode.OperationSucceeded) {
+            synchronized (mAsecMountSet) {
+                mAsecMountSet.remove(id);
+            }
+        }
         return rc;
     }
 
+    public boolean isSecureContainerMounted(String id) {
+        validatePermission(android.Manifest.permission.ASEC_ACCESS);
+        waitForReady();
+        warnOnNotMounted();
+
+        synchronized (mAsecMountSet) {
+            return mAsecMountSet.contains(id);
+        }
+    }
+
     public int renameSecureContainer(String oldId, String newId) {
         validatePermission(android.Manifest.permission.ASEC_RENAME);
         waitForReady();
         warnOnNotMounted();
 
+        synchronized (mAsecMountSet) {
+            if (mAsecMountSet.contains(oldId)) {
+                return StorageResultCode.OperationFailedStorageMounted;
+            }
+        }
+
         int rc = StorageResultCode.OperationSucceeded;
         String cmd = String.format("asec rename %s %s", oldId, newId);
         try {
@@ -892,6 +957,7 @@
         } catch (NativeDaemonConnectorException e) {
             rc = StorageResultCode.OperationFailedInternalError;
         }
+
         return rc;
     }
 
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index ad8ab84..3657133 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -50,7 +50,6 @@
 import android.os.Power;
 import android.os.Process;
 import android.os.RemoteException;
-import android.os.storage.StorageManager;
 import android.os.SystemProperties;
 import android.os.Vibrator;
 import android.provider.Settings;
@@ -408,9 +407,6 @@
         mToastQueue = new ArrayList<ToastRecord>();
         mHandler = new WorkerHandler();
 
-        StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
-        sm.registerListener(new com.android.internal.app.StorageNotification(context));
-
         mStatusBarService = statusBar;
         statusBar.setNotificationCallbacks(mNotificationCallbacks);
 
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index b1e5d32..812ff64 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -20,6 +20,8 @@
 import com.android.internal.app.ResolverActivity;
 import com.android.common.FastXmlSerializer;
 import com.android.common.XmlUtils;
+import com.android.internal.content.PackageHelper;
+import com.android.server.JournaledFile;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -303,6 +305,7 @@
     static final int INIT_COPY = 5;
     static final int MCS_UNBIND = 6;
     static final int START_CLEANING_PACKAGE = 7;
+    static final int FIND_INSTALL_LOC = 8;
     // Delay time in millisecs
     static final int BROADCAST_DELAY = 10 * 1000;
     private ServiceConnection mDefContainerConn = new ServiceConnection() {
@@ -318,8 +321,8 @@
     };
 
     class PackageHandler extends Handler {
-        final ArrayList<InstallArgs> mPendingInstalls =
-            new ArrayList<InstallArgs>();
+        final ArrayList<InstallParams> mPendingInstalls =
+            new ArrayList<InstallParams>();
         // Service Connection to remote media container service to copy
         // package uri's from external media onto secure containers
         // or internal storage.
@@ -331,21 +334,20 @@
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case INIT_COPY: {
-                    InstallArgs args = (InstallArgs) msg.obj;
-                    args.createCopyFile();
+                    InstallParams params = (InstallParams) msg.obj;
                     Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
                     if (mContainerService != null) {
                         // No need to add to pending list. Use remote stub directly
-                        handleStartCopy(args);
+                        handleStartCopy(params);
                     } else {
                         if (mContext.bindService(service, mDefContainerConn,
                                 Context.BIND_AUTO_CREATE)) {
-                            mPendingInstalls.add(args);
+                            mPendingInstalls.add(params);
                         } else {
                             Log.e(TAG, "Failed to bind to media container service");
                             // Indicate install failure TODO add new error code
-                            processPendingInstall(args,
-                                    PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE);
+                            processPendingInstall(createInstallArgs(params),
+                                    PackageManager.INSTALL_FAILED_INTERNAL_ERROR);
                         }
                     }
                     break;
@@ -356,9 +358,9 @@
                         mContainerService = (IMediaContainerService) msg.obj;
                     }
                     if (mPendingInstalls.size() > 0) {
-                        InstallArgs args = mPendingInstalls.remove(0);
-                        if (args != null) {
-                            handleStartCopy(args);
+                        InstallParams params = mPendingInstalls.remove(0);
+                        if (params != null) {
+                            handleStartCopy(params);
                         }
                     }
                     break;
@@ -422,22 +424,56 @@
 
         // Utility method to initiate copying apk via media
         // container service.
-        private void handleStartCopy(InstallArgs args) {
-            int ret = PackageManager.INSTALL_SUCCEEDED;
-            if (mContainerService == null) {
-                // Install error
-                ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
-            } else {
-                ret = args.copyApk(mContainerService);
+        private void handleStartCopy(InstallParams params) {
+            int ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+            if (mContainerService != null) {
+                // Remote call to find out default install location
+                int loc = params.getInstallLocation(mContainerService);
+                // Use install location to create InstallArgs and temporary
+                // install location
+                if (loc == PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE){
+                    ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+                } else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
+                    ret = PackageManager.INSTALL_FAILED_INVALID_APK;
+                } else {
+                    if ((params.flags & PackageManager.INSTALL_EXTERNAL) == 0){
+                        if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
+                            // Set the flag to install on external media.
+                            params.flags |= PackageManager.INSTALL_EXTERNAL;
+                        } else {
+                            // Make sure the flag for installing on external
+                            // media is unset
+                            params.flags &= ~PackageManager.INSTALL_EXTERNAL;
+                        }
+                    }
+                    // Disable forward locked apps on sdcard.
+                    if ((params.flags & PackageManager.INSTALL_FORWARD_LOCK) != 0 &&
+                            (params.flags & PackageManager.INSTALL_EXTERNAL) != 0) {
+                        // Make sure forward locked apps can only be installed
+                        // on internal storage
+                        Log.w(TAG, "Cannot install protected apps on sdcard");
+                        ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
+                    } else {
+                        ret = PackageManager.INSTALL_SUCCEEDED;
+                    }
+                }
             }
             mHandler.sendEmptyMessage(MCS_UNBIND);
+            // Create the file args now.
+            InstallArgs args = createInstallArgs(params);
+            if (ret == PackageManager.INSTALL_SUCCEEDED) {
+                // Create copy only if we are not in an erroneous state.
+                args.createCopyFile();
+                // Remote call to initiate copy
+                ret = args.copyApk(mContainerService);
+            }
             processPendingInstall(args, ret);
         }
     }
 
     static boolean installOnSd(int flags) {
         if (((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) ||
-                ((flags & PackageManager.INSTALL_ON_SDCARD) == 0)) {
+                ((flags & PackageManager.INSTALL_EXTERNAL) == 0)) {
             return false;
         }
         return true;
@@ -703,7 +739,8 @@
             while (psit.hasNext()) {
                 PackageSetting ps = psit.next();
                 if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
-                        && !mPackages.containsKey(ps.name)) {
+                        && !mPackages.containsKey(ps.name)
+                        && !mSettings.mDisabledSysPackages.containsKey(ps.name)) {
                     psit.remove();
                     String msg = "System package " + ps.name
                             + " no longer exists; wiping its data";
@@ -1074,6 +1111,28 @@
         return null;
     }
 
+    public String[] currentToCanonicalPackageNames(String[] names) {
+        String[] out = new String[names.length];
+        synchronized (mPackages) {
+            for (int i=names.length-1; i>=0; i--) {
+                PackageSetting ps = mSettings.mPackages.get(names[i]);
+                out[i] = ps != null && ps.realName != null ? ps.realName : names[i];
+            }
+        }
+        return out;
+    }
+    
+    public String[] canonicalToCurrentPackageNames(String[] names) {
+        String[] out = new String[names.length];
+        synchronized (mPackages) {
+            for (int i=names.length-1; i>=0; i--) {
+                String cur = mSettings.mRenamedPackages.get(names[i]);
+                out[i] = cur != null ? cur : names[i];
+            }
+        }
+        return out;
+    }
+    
     public int getPackageUid(String packageName) {
         synchronized (mPackages) {
             PackageParser.Package p = mPackages.get(packageName);
@@ -2177,47 +2236,56 @@
      *  Returns null in case of errors and the error code is stored in mLastScanError
      */
     private PackageParser.Package scanPackageLI(File scanFile,
-            int parseFlags,
-            int scanMode) {
+            int parseFlags, int scanMode) {
         mLastScanError = PackageManager.INSTALL_SUCCEEDED;
         String scanPath = scanFile.getPath();
         parseFlags |= mDefParseFlags;
         PackageParser pp = new PackageParser(scanPath);
         pp.setSeparateProcesses(mSeparateProcesses);
         final PackageParser.Package pkg = pp.parsePackage(scanFile,
-                scanPath,
-                mMetrics, parseFlags);
+                scanPath, mMetrics, parseFlags);
         if (pkg == null) {
             mLastScanError = pp.getParseError();
             return null;
         }
-        PackageSetting ps;
+        PackageSetting ps = null;
         PackageSetting updatedPkg;
         synchronized (mPackages) {
-            ps = mSettings.peekPackageLP(pkg.packageName);
-            updatedPkg = mSettings.mDisabledSysPackages.get(pkg.packageName);
+            // Look to see if we already know about this package.
+            String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
+            if (oldName != null && oldName.equals(pkg.mOriginalPackage)) {
+                // This package has been renamed to its original name.  Let's
+                // use that.
+                ps = mSettings.peekPackageLP(pkg.mOriginalPackage);
+            }
+            // If there was no original package, see one for the real package name.
+            if (ps == null) {
+                ps = mSettings.peekPackageLP(pkg.packageName);
+            }
+            // Check to see if this package could be hiding/updating a system
+            // package.  Must look for it either under the original or real
+            // package name depending on our state.
+            updatedPkg = mSettings.mDisabledSysPackages.get(
+                    ps != null ? ps.name : pkg.packageName);
         }
-        // Verify certificates first
-        if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
-            Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
-            return null;
-        }
-        if (updatedPkg != null) {
-            // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
-            parseFlags |= PackageParser.PARSE_IS_SYSTEM;
-        }
-        if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
-            // Check for updated system applications here
-            if ((ps != null) && (!ps.codePath.equals(scanFile))) {
+        // First check if this is a system package that may involve an update
+        if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
+            if (!ps.codePath.equals(scanFile)) {
+                // The path has changed from what was last scanned...  check the
+                // version of the new path against what we have stored to determine
+                // what to do.
                 if (pkg.mVersionCode < ps.versionCode) {
                     // The system package has been updated and the code path does not match
-                    // Ignore entry. Just return
-                    Log.w(TAG, "Package:" + pkg.packageName +
-                            " has been updated. Ignoring the one from path:"+scanFile);
+                    // Ignore entry. Skip it.
+                    Log.i(TAG, "Package " + ps.name + " at " + scanFile
+                            + "ignored: updated version " + ps.versionCode
+                            + " better than this " + pkg.mVersionCode);
                     mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
                     return null;
                 } else {
-                    // Delete the older apk pointed to by ps
+                    // The current app on the system partion is better than
+                    // what we have updated to on the data partition; switch
+                    // back to the system partition version.
                     // At this point, its safely assumed that package installation for
                     // apps in system partition will go through. If not there won't be a working
                     // version of the app
@@ -2225,12 +2293,25 @@
                         // Just remove the loaded entries from package lists.
                         mPackages.remove(ps.name);
                     }
+                    Log.w(TAG, "Package " + ps.name + " at " + scanFile
+                            + "reverting from " + ps.codePathString
+                            + ": new version " + pkg.mVersionCode
+                            + " better than installed " + ps.versionCode);
                     InstallArgs args = new FileInstallArgs(ps.codePathString, ps.resourcePathString);
                     args.cleanUpResourcesLI();
                     mSettings.enableSystemPackageLP(ps.name);
                 }
             }
         }
+        if (updatedPkg != null) {
+            // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
+            parseFlags |= PackageParser.PARSE_IS_SYSTEM;
+        }
+        // Verify certificates against what was last scanned
+        if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
+            Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
+            return null;
+        }
         // The apk is forward locked (not public) if its code and resources
         // are kept in different files.
         // TODO grab this value from PackageSettings
@@ -2368,8 +2449,8 @@
         return true;
     }
     
-    private PackageParser.Package scanPackageLI(
-        PackageParser.Package pkg, int parseFlags, int scanMode) {
+    private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
+            int parseFlags, int scanMode) {
         File scanFile = new File(pkg.mScanPath);
         if (scanFile == null || pkg.applicationInfo.sourceDir == null ||
                 pkg.applicationInfo.publicSourceDir == null) {
@@ -2384,12 +2465,11 @@
             return null;
         }
 
-        final String pkgName = pkg.applicationInfo.packageName;
         if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
         }
 
-        if (pkgName.equals("android")) {
+        if (pkg.packageName.equals("android")) {
             synchronized (mPackages) {
                 if (mAndroidApplication != null) {
                     Log.w(TAG, "*************************************************");
@@ -2424,10 +2504,11 @@
         }
 
         if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
-                TAG, "Scanning package " + pkgName);
-        if (mPackages.containsKey(pkgName) || mSharedLibraries.containsKey(pkgName)) {
+                TAG, "Scanning package " + pkg.packageName);
+        if (mPackages.containsKey(pkg.packageName)
+                || mSharedLibraries.containsKey(pkg.packageName)) {
             Log.w(TAG, "*************************************************");
-            Log.w(TAG, "Application package " + pkgName
+            Log.w(TAG, "Application package " + pkg.packageName
                     + " already installed.  Skipping duplicate.");
             Log.w(TAG, "*************************************************");
             mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
@@ -2443,6 +2524,13 @@
 
         boolean removeExisting = false;
 
+        if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
+            // Only system apps can use these features.
+            pkg.mOriginalPackage = null;
+            pkg.mRealPackage = null;
+            pkg.mAdoptPermissions = null;
+        }
+        
         synchronized (mPackages) {
             // Check all shared libraries and map to their actual file path.
             if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
@@ -2508,7 +2596,7 @@
                 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
                         pkg.applicationInfo.flags, true);
                 if (suid == null) {
-                    Log.w(TAG, "Creating application package " + pkgName
+                    Log.w(TAG, "Creating application package " + pkg.packageName
                             + " for shared user failed");
                     mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                     return null;
@@ -2519,16 +2607,44 @@
                 }
             }
 
+            if (false) {
+                if (pkg.mOriginalPackage != null) {
+                    Log.w(TAG, "WAITING FOR DEBUGGER");
+                    Debug.waitForDebugger();
+                    Log.i(TAG, "Package " + pkg.packageName + " from original package"
+                            + pkg.mOriginalPackage);
+                }
+            }
+            
             // Check if we are renaming from an original package name.
             PackageSetting origPackage = null;
+            String realName = null;
             if (pkg.mOriginalPackage != null) {
-                // We will only retrieve the setting for it if it already
-                // exists; otherwise we need to make a new one later.
-                origPackage = mSettings.peekPackageLP(pkg.mOriginalPackage);
-                if (origPackage != null) {
+                // This package may need to be renamed to a previously
+                // installed name.  Let's check on that...
+                String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage);
+                if (pkg.mOriginalPackage.equals(renamed)) {
+                    // This package had originally been installed as the
+                    // original name, and we have already taken care of
+                    // transitioning to the new one.  Just update the new
+                    // one to continue using the old name.
+                    realName = pkg.mRealPackage;
+                    if (!pkg.packageName.equals(renamed)) {
+                        // Callers into this function may have already taken
+                        // care of renaming the package; only do it here if
+                        // it is not already done.
+                        pkg.setPackageName(renamed);
+                    }
+                    
+                } else if ((origPackage
+                        = mSettings.peekPackageLP(pkg.mOriginalPackage)) != null) {
+                    // We do have the package already installed under its
+                    // original name...  should we use it?
                     if (!verifyPackageUpdate(origPackage, pkg)) {
+                        // New package is not compatible with original.
                         origPackage = null;
                     } else if (origPackage.sharedUser != null) {
+                        // Make sure uid is compatible between packages.
                         if (!origPackage.sharedUser.name.equals(pkg.mSharedUserId)) {
                             Log.w(TAG, "Unable to migrate data from " + origPackage.name
                                     + " to " + pkg.packageName + ": old uid "
@@ -2537,8 +2653,8 @@
                             origPackage = null;
                         }
                     } else {
-                        if (DEBUG_UPGRADE) Log.v(TAG, "Migrating data from "
-                                + origPackage.name + " to " + pkg.packageName);
+                        if (DEBUG_UPGRADE) Log.v(TAG, "Renaming new package "
+                                + pkg.packageName + " to old name " + origPackage.name);
                     }
                 }
             }
@@ -2550,13 +2666,38 @@
             
             // Just create the setting, don't add it yet. For already existing packages
             // the PkgSetting exists already and doesn't have to be created.
-            pkgSetting = mSettings.getPackageLP(pkg, origPackage, suid, destCodeFile,
+            pkgSetting = mSettings.getPackageLP(pkg, origPackage, realName, suid, destCodeFile,
                             destResourceFile, pkg.applicationInfo.flags, true, false);
             if (pkgSetting == null) {
-                Log.w(TAG, "Creating application package " + pkgName + " failed");
+                Log.w(TAG, "Creating application package " + pkg.packageName + " failed");
                 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                 return null;
             }
+            
+            if (pkgSetting.origPackage != null) {
+                // If we are first transitioning from an original package,
+                // fix up the new package's name now.  We need to do this after
+                // looking up the package under its new name, so getPackageLP
+                // can take care of fiddling things correctly.
+                pkg.setPackageName(origPackage.name);
+                
+                // File a report about this.
+                String msg = "New package " + pkgSetting.realName
+                        + " renamed to replace old package " + pkgSetting.name;
+                reportSettingsProblem(Log.WARN, msg);
+                
+                // Make a note of it.
+                mTransferedPackages.add(origPackage.name);
+                
+                // No longer need to retain this.
+                pkgSetting.origPackage = null;
+            }
+            
+            if (realName != null) {
+                // Make a note of it.
+                mTransferedPackages.add(pkg.packageName);
+            }
+            
             if (mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
                 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
             }
@@ -2564,22 +2705,6 @@
             pkg.applicationInfo.uid = pkgSetting.userId;
             pkg.mExtras = pkgSetting;
 
-            if (pkg.mAdoptPermissions != null) {
-                // This package wants to adopt ownership of permissions from
-                // another package.
-                for (int i=pkg.mAdoptPermissions.size()-1; i>=0; i--) {
-                    String origName = pkg.mAdoptPermissions.get(i);
-                    PackageSetting orig = mSettings.peekPackageLP(origName);
-                    if (orig != null) {
-                        if (verifyPackageUpdate(orig, pkg)) {
-                            if (DEBUG_UPGRADE) Log.v(TAG, "Adopting permissions from "
-                                    + origName + " to " + pkg.packageName);
-                            mSettings.transferPermissions(origName, pkg.packageName);
-                        }
-                    }
-                }
-            }
-            
             if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
                     (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
                 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
@@ -2620,8 +2745,8 @@
                             Log.w(TAG, "Can't install because provider name " + names[j] +
                                     " (in package " + pkg.applicationInfo.packageName +
                                     ") is already used by "
-                                    + ((other != null && other.component != null)
-                                            ? other.component.getPackageName() : "?"));
+                                    + ((other != null && other.getComponentName() != null)
+                                            ? other.getComponentName().getPackageName() : "?"));
                             mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
                             return null;
                         }
@@ -2630,6 +2755,8 @@
             }
         }
 
+        final String pkgName = pkg.packageName;
+        
         if (removeExisting) {
             boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
             if (mInstaller != null) {
@@ -2647,6 +2774,22 @@
             mLastScanError = PackageManager.INSTALL_SUCCEEDED;
         }
 
+        if (pkg.mAdoptPermissions != null) {
+            // This package wants to adopt ownership of permissions from
+            // another package.
+            for (int i=pkg.mAdoptPermissions.size()-1; i>=0; i--) {
+                String origName = pkg.mAdoptPermissions.get(i);
+                PackageSetting orig = mSettings.peekPackageLP(origName);
+                if (orig != null) {
+                    if (verifyPackageUpdate(orig, pkg)) {
+                        Log.i(TAG, "Adopting permissions from "
+                                + origName + " to " + pkg.packageName);
+                        mSettings.transferPermissions(origName, pkg.packageName);
+                    }
+                }
+            }
+        }
+        
         long scanFileTime = scanFile.lastModified();
         final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
         final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
@@ -2732,29 +2875,6 @@
             } else {
                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
                     Log.v(TAG, "Want this data dir: " + dataPath);
-                if (pkgSetting.origPackage != null) {
-                    synchronized (mPackages) {
-                        // This package is being update from another; rename the
-                        // old one's data dir.
-                        String msg = "Transfering data from old package "
-                                + pkgSetting.origPackage.name + " to new package "
-                                + pkgSetting.name;
-                        reportSettingsProblem(Log.WARN, msg);
-                        if (mInstaller != null) {
-                            int ret = mInstaller.rename(pkgSetting.origPackage.name,
-                                    pkgName, useEncryptedFSDir);
-                            if(ret < 0) {
-                                msg = "Error transfering data from old package "
-                                    + pkgSetting.origPackage.name + " to new package "
-                                    + pkgSetting.name;
-                                reportSettingsProblem(Log.WARN, msg);
-                            }
-                        }
-                        // And now uninstall the old package.
-                        mInstaller.remove(pkgSetting.origPackage.name, useEncryptedFSDir);
-                        mSettings.removePackageLP(pkgSetting.origPackage.name);
-                    }
-                }
                 //invoke installer to do the actual installation
                 if (mInstaller != null) {
                     int ret = mInstaller.install(pkgName, useEncryptedFSDir, pkg.applicationInfo.uid,
@@ -2784,12 +2904,6 @@
             pkgSetting.uidError = uidError;
         }
 
-        // No longer need to retain this.
-        if (pkgSetting.origPackage != null) {
-            mTransferedPackages.add(pkgSetting.origPackage.name);
-            pkgSetting.origPackage = null;
-        }
-        
         // Perform shared library installation and dex validation and
         // optimization, if this is not a system app.
         if (mInstaller != null) {
@@ -2825,7 +2939,7 @@
         // Request the ActivityManager to kill the process(only for existing packages)
         // so that we do not end up in a confused state while the user is still using the older
         // version of the application while the new one gets installed.
-        if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING ) != 0) {
+        if ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
             killApplication(pkg.applicationInfo.packageName,
                         pkg.applicationInfo.uid);
         }
@@ -2878,8 +2992,8 @@
                         Log.w(TAG, "Skipping provider name " + names[j] +
                               " (in package " + pkg.applicationInfo.packageName +
                               "): name already used by "
-                              + ((other != null && other.component != null)
-                                      ? other.component.getPackageName() : "?"));
+                              + ((other != null && other.getComponentName() != null)
+                                      ? other.getComponentName().getPackageName() : "?"));
                     }
                 }
                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
@@ -3058,7 +3172,7 @@
                 a.info.sourceDir = pkg.applicationInfo.sourceDir;
                 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
                 a.info.dataDir = pkg.applicationInfo.dataDir;
-                mInstrumentation.put(a.component, a);
+                mInstrumentation.put(a.getComponentName(), a);
                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
                     if (r == null) {
                         r = new StringBuilder(256);
@@ -3492,7 +3606,7 @@
             r = null;
             for (i=0; i<N; i++) {
                 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
-                mInstrumentation.remove(a.component);
+                mInstrumentation.remove(a.getComponentName());
                 if (chatty) {
                     if (r == null) {
                         r = new StringBuilder(256);
@@ -3721,7 +3835,7 @@
         }
 
         public final void addActivity(PackageParser.Activity a, String type) {
-            mActivities.put(a.component, a);
+            mActivities.put(a.getComponentName(), a);
             if (SHOW_INFO || Config.LOGV) Log.v(
                 TAG, "  " + type + " " +
                 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
@@ -3741,7 +3855,7 @@
         }
 
         public final void removeActivity(PackageParser.Activity a, String type) {
-            mActivities.remove(a.component);
+            mActivities.remove(a.getComponentName());
             if (SHOW_INFO || Config.LOGV) Log.v(
                 TAG, "  " + type + " " +
                 (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
@@ -3811,7 +3925,7 @@
             out.print(prefix); out.print(
                     Integer.toHexString(System.identityHashCode(filter.activity)));
                     out.print(' ');
-                    out.println(filter.activity.componentShortName);
+                    out.println(filter.activity.getComponentShortName());
         }
 
 //        List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
@@ -3867,7 +3981,7 @@
         }
 
         public final void addService(PackageParser.Service s) {
-            mServices.put(s.component, s);
+            mServices.put(s.getComponentName(), s);
             if (SHOW_INFO || Config.LOGV) Log.v(
                 TAG, "  " + (s.info.nonLocalizedLabel != null
                         ? s.info.nonLocalizedLabel : s.info.name) + ":");
@@ -3889,7 +4003,7 @@
         }
 
         public final void removeService(PackageParser.Service s) {
-            mServices.remove(s.component);
+            mServices.remove(s.getComponentName());
             if (SHOW_INFO || Config.LOGV) Log.v(
                 TAG, "  " + (s.info.nonLocalizedLabel != null
                         ? s.info.nonLocalizedLabel : s.info.name) + ":");
@@ -3962,7 +4076,7 @@
             out.print(prefix); out.print(
                     Integer.toHexString(System.identityHashCode(filter.service)));
                     out.print(' ');
-                    out.println(filter.service.componentShortName);
+                    out.println(filter.service.getComponentShortName());
         }
 
 //        List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
@@ -4170,29 +4284,11 @@
                 android.Manifest.permission.INSTALL_PACKAGES, null);
 
         Message msg = mHandler.obtainMessage(INIT_COPY);
-        msg.obj = createInstallArgs(packageURI, observer, flags, installerPackageName);
+        msg.obj = new InstallParams(packageURI, observer, flags,
+                installerPackageName);
         mHandler.sendMessage(msg);
     }
 
-    private InstallArgs createInstallArgs(Uri packageURI, IPackageInstallObserver observer,
-            int flags, String installerPackageName) {
-        if (installOnSd(flags)) {
-            return new SdInstallArgs(packageURI, observer, flags,
-                    installerPackageName);
-        } else {
-            return new FileInstallArgs(packageURI, observer, flags,
-                    installerPackageName);
-        }
-    }
-
-    private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath) {
-        if (installOnSd(flags)) {
-            return new SdInstallArgs(fullCodePath, fullResourcePath);
-        } else {
-            return new FileInstallArgs(fullCodePath, fullResourcePath);
-        }
-    }
-
     private void processPendingInstall(final InstallArgs args, final int currentStatus) {
         // Queue up an async operation since the package installation may take a little while.
         mHandler.post(new Runnable() {
@@ -4248,6 +4344,45 @@
         });
     }
 
+    static final class InstallParams {
+        final IPackageInstallObserver observer;
+        int flags;
+        final Uri packageURI;
+        final String installerPackageName;
+        InstallParams(Uri packageURI,
+                IPackageInstallObserver observer, int flags,
+                String installerPackageName) {
+            this.packageURI = packageURI;
+            this.flags = flags;
+            this.observer = observer;
+            this.installerPackageName = installerPackageName;
+        }
+
+        public int getInstallLocation(IMediaContainerService imcs) {
+            try {
+                return imcs.getRecommendedInstallLocation(packageURI);
+            } catch (RemoteException e) {
+            }
+            return  -1;
+        }
+    };
+
+    private InstallArgs createInstallArgs(InstallParams params) {
+        if (installOnSd(params.flags)) {
+            return new SdInstallArgs(params);
+        } else {
+            return new FileInstallArgs(params);
+        }
+    }
+
+    private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath) {
+        if (installOnSd(flags)) {
+            return new SdInstallArgs(fullCodePath, fullResourcePath);
+        } else {
+            return new FileInstallArgs(fullCodePath, fullResourcePath);
+        }
+    }
+
     static abstract class InstallArgs {
         final IPackageInstallObserver observer;
         final int flags;
@@ -4280,10 +4415,9 @@
         String codeFileName;
         String resourceFileName;
 
-        FileInstallArgs(Uri packageURI,
-                IPackageInstallObserver observer, int flags,
-                String installerPackageName) {
-            super(packageURI, observer, flags, installerPackageName);
+        FileInstallArgs(InstallParams params) {
+            super(params.packageURI, params.observer,
+                    params.flags, params.installerPackageName);
         }
 
         FileInstallArgs(String fullCodePath, String fullResourcePath) {
@@ -4294,6 +4428,10 @@
             resourceFileName = fullResourcePath;
         }
 
+        String getCodePath() {
+            return codeFileName;
+        }
+
         void createCopyFile() {
             boolean fwdLocked = isFwdLocked(flags);
             installDir = fwdLocked ? mDrmAppPrivateInstallDir : mAppInstallDir;
@@ -4301,10 +4439,6 @@
             resourceFileName = getResourcePathFromCodePath();
         }
 
-        String getCodePath() {
-            return codeFileName;
-        }
-
         int copyApk(IMediaContainerService imcs) {
             // Get a ParcelFileDescriptor to write to the output file
             File codeFile = new File(codeFileName);
@@ -4449,10 +4583,9 @@
         String cachePath;
         static final String RES_FILE_NAME = "pkg.apk";
 
-        SdInstallArgs(Uri packageURI,
-                IPackageInstallObserver observer, int flags,
-                String installerPackageName) {
-           super(packageURI, observer, flags, installerPackageName);
+        SdInstallArgs(InstallParams params) {
+            super(params.packageURI, params.observer,
+                    params.flags, params.installerPackageName);
         }
 
         SdInstallArgs(String fullCodePath, String fullResourcePath) {
@@ -4798,14 +4931,14 @@
         // First find the old package info and check signatures
         synchronized(mPackages) {
             oldPackage = mPackages.get(pkgName);
-            if(checkSignaturesLP(pkg.mSignatures, oldPackage.mSignatures)
+            if (checkSignaturesLP(pkg.mSignatures, oldPackage.mSignatures)
                     != PackageManager.SIGNATURE_MATCH) {
                 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
                 return;
             }
         }
         boolean sysPkg = ((oldPackage.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
-        if(sysPkg) {
+        if (sysPkg) {
             replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
         } else {
             replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode, installerPackageName, res);
@@ -4919,7 +5052,7 @@
             oldPkgSetting = mSettings.mPackages.get(packageName);
             if((oldPkg == null) || (oldPkg.applicationInfo == null) ||
                     (oldPkgSetting == null)) {
-                Log.w(TAG, "Could'nt find package:"+packageName+" information");
+                Log.w(TAG, "Couldn't find package:"+packageName+" information");
                 return;
             }
         }
@@ -5026,7 +5159,7 @@
         String installerPackageName = args.installerPackageName;
         File tmpPackageFile = new File(args.getCodePath());
         boolean forwardLocked = ((pFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0);
-        boolean onSd = ((pFlags & PackageManager.INSTALL_ON_SDCARD) != 0);
+        boolean onSd = ((pFlags & PackageManager.INSTALL_EXTERNAL) != 0);
         boolean replace = false;
         int scanMode = SCAN_MONITOR | SCAN_FORCE_DEX | SCAN_UPDATE_SIGNATURE
                 | (newInstall ? SCAN_NEW_INSTALL : 0);
@@ -5057,23 +5190,28 @@
             res.returnCode = pp.getParseError();
             return;
         }
-        // Some preinstall checks
-        if (forwardLocked && onSd) {
-            // Make sure forward locked apps can only be installed
-            // on internal storage
-            Log.w(TAG, "Cannot install protected apps on sdcard");
-            res.returnCode = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
-            return;
-        }
         // Get rid of all references to package scan path via parser.
         pp = null;
         String oldCodePath = null;
         boolean systemApp = false;
         synchronized (mPackages) {
             // Check if installing already existing package
-            if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0
-                    && mPackages.containsKey(pkgName)) {
-                replace = true;
+            if ((pFlags&PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
+                String oldName = mSettings.mRenamedPackages.get(pkgName);
+                if (oldName != null && oldName.equals(pkg.mOriginalPackage)
+                        && mPackages.containsKey(oldName)) {
+                    // This package is derived from an original package,
+                    // and this device has been updating from that original
+                    // name.  We must continue using the original name, so
+                    // rename the new package here.
+                    pkg.setPackageName(pkg.mOriginalPackage);
+                    pkgName = pkg.packageName;
+                    replace = true;
+                } else if (mPackages.containsKey(pkgName)) {
+                    // This package, under its official name, already exists
+                    // on the device; we should replace it.
+                    replace = true;
+                }
             }
             PackageSetting ps = mSettings.mPackages.get(pkgName);
             if (ps != null) {
@@ -5097,7 +5235,7 @@
         }
         // Set application objects path explicitly after the rename
         setApplicationInfoPaths(pkg, args.getCodePath(), args.getResourcePath());
-        if(replace) {
+        if (replace) {
             replacePackageLI(pkg, parseFlags, scanMode,
                     installerPackageName, res);
         } else {
@@ -5468,7 +5606,7 @@
         if (deleteCodeAndResources) {
             // TODO can pick up from PackageSettings as well
             int installFlags = ((p.applicationInfo.flags & ApplicationInfo.FLAG_ON_SDCARD)!=0) ?
-                    PackageManager.INSTALL_ON_SDCARD : 0;
+                    PackageManager.INSTALL_EXTERNAL : 0;
             installFlags |= ((p.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK)!=0) ?
                     PackageManager.INSTALL_FORWARD_LOCK : 0;
             outInfo.args = createInstallArgs(installFlags,
@@ -6069,9 +6207,14 @@
             pw.println("Packages:");
             {
                 for (PackageSetting ps : mSettings.mPackages.values()) {
-                    pw.print("  Package ["); pw.print(ps.name); pw.print("] (");
+                    pw.print("  Package [");
+                            pw.print(ps.realName != null ? ps.realName : ps.name);
+                            pw.print("] (");
                             pw.print(Integer.toHexString(System.identityHashCode(ps)));
                             pw.println("):");
+                    if (ps.realName != null) {
+                        pw.print("    compat name="); pw.println(ps.name);
+                    }
                     pw.print("    userId="); pw.print(ps.userId);
                             pw.print(" gids="); pw.println(arrayToString(ps.gids));
                     pw.print("    sharedUser="); pw.println(ps.sharedUser);
@@ -6147,6 +6290,33 @@
                     }
                 }
             }
+            if (mSettings.mRenamedPackages.size() > 0) {
+                pw.println(" ");
+                pw.println("Renamed packages:");
+                for (HashMap.Entry<String, String> e
+                        : mSettings.mRenamedPackages.entrySet()) {
+                    pw.print("  "); pw.print(e.getKey()); pw.print(" -> ");
+                            pw.println(e.getValue());
+                }
+            }
+            if (mSettings.mDisabledSysPackages.size() > 0) {
+                pw.println(" ");
+                pw.println("Hidden system packages:");
+                for (PackageSetting ps : mSettings.mDisabledSysPackages.values()) {
+                    pw.print("  Package [");
+                            pw.print(ps.realName != null ? ps.realName : ps.name);
+                            pw.print("] (");
+                            pw.print(Integer.toHexString(System.identityHashCode(ps)));
+                            pw.println("):");
+                    if (ps.realName != null) {
+                        pw.print("    compat name="); pw.println(ps.name);
+                    }
+                    pw.print("    userId="); pw.println(ps.userId);
+                    pw.print("    sharedUser="); pw.println(ps.sharedUser);
+                    pw.print("    codePath="); pw.println(ps.codePathString);
+                    pw.print("    resourcePath="); pw.println(ps.resourcePathString);
+                }
+            }
             pw.println(" ");
             pw.println("Shared Users:");
             {
@@ -6659,6 +6829,7 @@
      */
     static class PackageSettingBase extends GrantedPermissions {
         final String name;
+        final String realName;
         File codePath;
         String codePathString;
         File resourcePath;
@@ -6685,10 +6856,11 @@
         /* package name of the app that installed this package */
         String installerPackageName;
 
-        PackageSettingBase(String name, File codePath, File resourcePath,
+        PackageSettingBase(String name, String realName, File codePath, File resourcePath,
                 int pVersionCode, int pkgFlags) {
             super(pkgFlags);
             this.name = name;
+            this.realName = realName;
             init(codePath, resourcePath, pVersionCode);
         }
 
@@ -6785,9 +6957,9 @@
         PackageParser.Package pkg;
         SharedUserSetting sharedUser;
 
-        PackageSetting(String name, File codePath, File resourcePath,
+        PackageSetting(String name, String realName, File codePath, File resourcePath,
                 int pVersionCode, int pkgFlags) {
-            super(name, codePath, resourcePath, pVersionCode, pkgFlags);
+            super(name, realName, codePath, resourcePath, pVersionCode, pkgFlags);
         }
 
         @Override
@@ -6826,6 +6998,7 @@
     private static final class Settings {
         private final File mSettingsFilename;
         private final File mBackupSettingsFilename;
+        private final File mPackageListFilename;
         private final HashMap<String, PackageSetting> mPackages =
                 new HashMap<String, PackageSetting>();
         // List of replaced system applications
@@ -6876,14 +7049,20 @@
         // storage data deleted.
         final ArrayList<String> mPackagesToBeCleaned = new ArrayList<String>();
         
+        // Packages that have been renamed since they were first installed.
+        // Keys are the new names of the packages, values are the original
+        // names.  The packages appear everwhere else under their original
+        // names.
+        final HashMap<String, String> mRenamedPackages = new HashMap<String, String>();
+        
         private final StringBuilder mReadMessages = new StringBuilder();
 
         private static final class PendingPackage extends PackageSettingBase {
             final int sharedId;
 
-            PendingPackage(String name, File codePath, File resourcePath,
+            PendingPackage(String name, String realName, File codePath, File resourcePath,
                     int sharedId, int pVersionCode, int pkgFlags) {
-                super(name, codePath, resourcePath, pVersionCode, pkgFlags);
+                super(name, realName, codePath, resourcePath, pVersionCode, pkgFlags);
                 this.sharedId = sharedId;
             }
         }
@@ -6907,13 +7086,14 @@
                     -1, -1);
             mSettingsFilename = new File(systemDir, "packages.xml");
             mBackupSettingsFilename = new File(systemDir, "packages-backup.xml");
+            mPackageListFilename = new File(systemDir, "packages.list");
         }
 
         PackageSetting getPackageLP(PackageParser.Package pkg, PackageSetting origPackage,
-                SharedUserSetting sharedUser, File codePath, File resourcePath,
+                String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
                 int pkgFlags, boolean create, boolean add) {
             final String name = pkg.packageName;
-            PackageSetting p = getPackageLP(name, origPackage, sharedUser, codePath,
+            PackageSetting p = getPackageLP(name, origPackage, realName, sharedUser, codePath,
                     resourcePath, pkg.mVersionCode, pkgFlags, create, add);
             return p;
         }
@@ -7010,13 +7190,13 @@
             if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
                 p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
             }
-            PackageSetting ret = addPackageLP(name, p.codePath,
+            PackageSetting ret = addPackageLP(name, p.realName, p.codePath,
                     p.resourcePath, p.userId, p.versionCode, p.pkgFlags);
             mDisabledSysPackages.remove(name);
             return ret;
         }
 
-        PackageSetting addPackageLP(String name, File codePath,
+        PackageSetting addPackageLP(String name, String realName, File codePath,
                 File resourcePath, int uid, int vc, int pkgFlags) {
             PackageSetting p = mPackages.get(name);
             if (p != null) {
@@ -7027,7 +7207,7 @@
                         "Adding duplicate package, keeping first: " + name);
                 return null;
             }
-            p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
+            p = new PackageSetting(name, realName, codePath, resourcePath, vc, pkgFlags);
             p.userId = uid;
             if (addUserIdLP(uid, p, name)) {
                 mPackages.put(name, p);
@@ -7080,7 +7260,7 @@
         }
         
         private PackageSetting getPackageLP(String name, PackageSetting origPackage,
-                SharedUserSetting sharedUser, File codePath, File resourcePath,
+                String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
                 int vc, int pkgFlags, boolean create, boolean add) {
             PackageSetting p = mPackages.get(name);
             if (p != null) {
@@ -7122,19 +7302,22 @@
                 if (!create) {
                     return null;
                 }
-                p = new PackageSetting(name, codePath, resourcePath, vc, pkgFlags);
                 if (origPackage != null) {
                     // We are consuming the data from an existing package.
+                    p = new PackageSetting(origPackage.name, name, codePath,
+                            resourcePath, vc, pkgFlags);
                     if (DEBUG_UPGRADE) Log.v(TAG, "Package " + name
                             + " is adopting original package " + origPackage.name);
                     p.copyFrom(origPackage);
                     p.sharedUser = origPackage.sharedUser;
                     p.userId = origPackage.userId;
                     p.origPackage = origPackage;
-                    transferPermissions(origPackage.name, name);
+                    mRenamedPackages.put(name, origPackage.name);
+                    name = origPackage.name;
                     // Update new package state.
                     p.setTimeStamp(codePath.lastModified());
                 } else {
+                    p = new PackageSetting(name, realName, codePath, resourcePath, vc, pkgFlags);
                     p.setTimeStamp(codePath.lastModified());
                     p.sharedUser = sharedUser;
                     if (sharedUser != null) {
@@ -7447,6 +7630,15 @@
                     }
                 }
                 
+                if (mRenamedPackages.size() > 0) {
+                    for (HashMap.Entry<String, String> e : mRenamedPackages.entrySet()) {
+                        serializer.startTag(null, "renamed-package");
+                        serializer.attribute(null, "new", e.getKey());
+                        serializer.attribute(null, "old", e.getValue());
+                        serializer.endTag(null, "renamed-package");
+                    }
+                }
+                
                 serializer.endTag(null, "packages");
 
                 serializer.endDocument();
@@ -7462,6 +7654,61 @@
                         |FileUtils.S_IRGRP|FileUtils.S_IWGRP
                         |FileUtils.S_IROTH,
                         -1, -1);
+
+                // Write package list file now, use a JournaledFile.
+                //
+                File tempFile = new File(mPackageListFilename.toString() + ".tmp");
+                JournaledFile journal = new JournaledFile(mPackageListFilename, tempFile);
+
+                str = new FileOutputStream(journal.chooseForWrite());
+                try {
+                    StringBuilder sb = new StringBuilder();
+                    for (PackageSetting pkg : mPackages.values()) {
+                        ApplicationInfo ai = pkg.pkg.applicationInfo;
+                        String  dataPath = ai.dataDir;
+                        boolean isDebug  = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
+
+                        // Avoid any application that has a space in its path
+                        // or that is handled by the system.
+                        if (dataPath.indexOf(" ") >= 0 || ai.uid <= Process.FIRST_APPLICATION_UID)
+                            continue;
+
+                        // we store on each line the following information for now:
+                        //
+                        // pkgName    - package name
+                        // userId     - application-specific user id
+                        // debugFlag  - 0 or 1 if the package is debuggable.
+                        // dataPath   - path to package's data path
+                        //
+                        // NOTE: We prefer not to expose all ApplicationInfo flags for now.
+                        //
+                        // DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS
+                        // FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
+                        //   system/core/run-as/run-as.c
+                        //
+                        sb.setLength(0);
+                        sb.append(ai.packageName);
+                        sb.append(" ");
+                        sb.append((int)ai.uid);
+                        sb.append(isDebug ? " 1 " : " 0 ");
+                        sb.append(dataPath);
+                        sb.append("\n");
+                        str.write(sb.toString().getBytes());
+                    }
+                    str.flush();
+                    str.close();
+                    journal.commit();
+                }
+                catch (Exception  e) {
+                    journal.rollback();
+                }
+
+                FileUtils.setPermissions(mPackageListFilename.toString(),
+                        FileUtils.S_IRUSR|FileUtils.S_IWUSR
+                        |FileUtils.S_IRGRP|FileUtils.S_IWGRP
+                        |FileUtils.S_IROTH,
+                        -1, -1);
+
                 return;
 
             } catch(XmlPullParserException e) {
@@ -7469,7 +7716,7 @@
             } catch(java.io.IOException e) {
                 Log.w(TAG, "Unable to write package manager settings, current changes will be lost at reboot", e);
             }
-            // Clean up partially written file
+            // Clean up partially written files
             if (mSettingsFilename.exists()) {
                 if (!mSettingsFilename.delete()) {
                     Log.i(TAG, "Failed to clean up mangled file: " + mSettingsFilename);
@@ -7482,6 +7729,9 @@
                 throws java.io.IOException {
             serializer.startTag(null, "updated-package");
             serializer.attribute(null, "name", pkg.name);
+            if (pkg.realName != null) {
+                serializer.attribute(null, "realName", pkg.realName);
+            }
             serializer.attribute(null, "codePath", pkg.codePathString);
             serializer.attribute(null, "ts", pkg.getTimeStampStr());
             serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
@@ -7520,6 +7770,9 @@
                 throws java.io.IOException {
             serializer.startTag(null, "package");
             serializer.attribute(null, "name", pkg.name);
+            if (pkg.realName != null) {
+                serializer.attribute(null, "realName", pkg.realName);
+            }
             serializer.attribute(null, "codePath", pkg.codePathString);
             if (!pkg.resourcePathString.equals(pkg.codePathString)) {
                 serializer.attribute(null, "resourcePath", pkg.resourcePathString);
@@ -7712,6 +7965,12 @@
                         if (name != null) {
                             mPackagesToBeCleaned.add(name);
                         }
+                    } else if (tagName.equals("renamed-package")) {
+                        String nname = parser.getAttributeValue(null, "new");
+                        String oname = parser.getAttributeValue(null, "old");
+                        if (nname != null && oname != null) {
+                            mRenamedPackages.put(nname, oname);
+                        }
                     } else {
                         Log.w(TAG, "Unknown element under <packages>: "
                               + parser.getName());
@@ -7736,7 +7995,7 @@
                 final PendingPackage pp = mPendingPackages.get(i);
                 Object idObj = getUserIdLP(pp.sharedId);
                 if (idObj != null && idObj instanceof SharedUserSetting) {
-                    PackageSetting p = getPackageLP(pp.name, null,
+                    PackageSetting p = getPackageLP(pp.name, null, pp.realName,
                             (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
                             pp.versionCode, pp.pkgFlags, true, true);
                     if (p == null) {
@@ -7839,9 +8098,10 @@
         private void readDisabledSysPackageLP(XmlPullParser parser)
                 throws XmlPullParserException, IOException {
             String name = parser.getAttributeValue(null, "name");
+            String realName = parser.getAttributeValue(null, "realName");
             String codePathStr = parser.getAttributeValue(null, "codePath");
             String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
-            if(resourcePathStr == null) {
+            if (resourcePathStr == null) {
                 resourcePathStr = codePathStr;
             }
             String version = parser.getAttributeValue(null, "version");
@@ -7855,7 +8115,7 @@
 
             int pkgFlags = 0;
             pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
-            PackageSetting ps = new PackageSetting(name,
+            PackageSetting ps = new PackageSetting(name, realName,
                     new File(codePathStr),
                     new File(resourcePathStr), versionCode, pkgFlags);
             String timeStampStr = parser.getAttributeValue(null, "ts");
@@ -7899,6 +8159,7 @@
         private void readPackageLP(XmlPullParser parser)
                 throws XmlPullParserException, IOException {
             String name = null;
+            String realName = null;
             String idStr = null;
             String sharedIdStr = null;
             String codePathStr = null;
@@ -7914,6 +8175,7 @@
             int versionCode = 0;
             try {
                 name = parser.getAttributeValue(null, "name");
+                realName = parser.getAttributeValue(null, "realName");
                 idStr = parser.getAttributeValue(null, "userId");
                 uidError = parser.getAttributeValue(null, "uidError");
                 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
@@ -7958,6 +8220,9 @@
                 if (resourcePathStr == null) {
                     resourcePathStr = codePathStr;
                 }
+                if (realName != null) {
+                    realName = realName.intern();
+                }
                 if (name == null) {
                     reportSettingsProblem(Log.WARN,
                             "Error in package manager settings: <package> has no name at "
@@ -7967,8 +8232,9 @@
                             "Error in package manager settings: <package> has no codePath at "
                             + parser.getPositionDescription());
                 } else if (userId > 0) {
-                    packageSetting = addPackageLP(name.intern(), new File(codePathStr),
-                            new File(resourcePathStr), userId, versionCode, pkgFlags);
+                    packageSetting = addPackageLP(name.intern(), realName,
+                            new File(codePathStr), new File(resourcePathStr),
+                            userId, versionCode, pkgFlags);
                     if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
                             + ": userId=" + userId + " pkg=" + packageSetting);
                     if (packageSetting == null) {
@@ -7983,8 +8249,9 @@
                     userId = sharedIdStr != null
                             ? Integer.parseInt(sharedIdStr) : 0;
                     if (userId > 0) {
-                        packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
-                                new File(resourcePathStr), userId, versionCode, pkgFlags);
+                        packageSetting = new PendingPackage(name.intern(), realName,
+                                new File(codePathStr), new File(resourcePathStr),
+                                userId, versionCode, pkgFlags);
                         packageSetting.setTimeStamp(timeStamp, timeStampStr);
                         mPendingPackages.add((PendingPackage) packageSetting);
                         if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
@@ -8299,6 +8566,13 @@
                 Log.v(TAG, "disabledComponents: "
                            + Arrays.toString(packageSettings.disabledComponents.toArray()));
             }
+            if (packageSettings == null) {
+                if (false) {
+                    Log.w(TAG, "WAITING FOR DEBUGGER");
+                    Debug.waitForDebugger();
+                    Log.i(TAG, "We will crash!");
+                }
+            }
             return ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0)
                    || ((componentInfo.enabled
                         && ((packageSettings.enabled == COMPONENT_ENABLED_STATE_ENABLED)
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 6e9c21b..28b4b28 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -329,19 +329,6 @@
             }
 
             try {
-                Log.i(TAG, "Checkin Service");
-                Intent intent = new Intent().setComponent(new ComponentName(
-                        "com.google.android.server.checkin",
-                        "com.google.android.server.checkin.CheckinService"));
-                if (context.startService(intent) == null) {
-                    Log.w(TAG, "Using fallback Checkin Service.");
-                    ServiceManager.addService("checkin", new FallbackCheckinService(context));
-                }
-            } catch (Throwable e) {
-                Log.e(TAG, "Failure starting Checkin Service", e);
-            }
-
-            try {
                 Log.i(TAG, "Wallpaper Service");
                 wallpaper = new WallpaperManagerService(context);
                 ServiceManager.addService(Context.WALLPAPER_SERVICE, wallpaper);
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 7951fb7..60cf5a2 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -373,8 +373,11 @@
                     failedToStopSupplicantOrUnloadDriver = true;
                 }
 
-                // We must reset the interface before we unload the driver
-                mWifiStateTracker.resetInterface(false);
+                /**
+                 * Reset connections and disable interface
+                 * before we unload the driver
+                 */
+                mWifiStateTracker.resetConnections(true);
 
                 if (!WifiNative.unloadDriver()) {
                     Log.e(TAG, "Failed to unload Wi-Fi driver.");
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 263e6db..7fcf900 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -1773,6 +1773,32 @@
         }
     }
 
+    void dispatchPointerElsewhereLocked(WindowState srcWin, WindowState relWin,
+            MotionEvent pointer, long eventTime, boolean skipped) {
+        if (relWin != null) {
+            mPolicy.dispatchedPointerEventLw(pointer, relWin.mFrame.left, relWin.mFrame.top);
+        } else {
+            mPolicy.dispatchedPointerEventLw(pointer, 0, 0);
+        }
+        
+        // If we sent an initial down to the wallpaper, then continue
+        // sending events until the final up.
+        if (mSendingPointersToWallpaper) {
+            if (skipped) {
+                Log.i(TAG, "Sending skipped pointer to wallpaper!");
+            }
+            sendPointerToWallpaperLocked(relWin, pointer, eventTime);
+            
+        // If we are on top of the wallpaper, then the wallpaper also
+        // gets to see this movement.
+        } else if (srcWin != null
+                && pointer.getAction() == MotionEvent.ACTION_DOWN
+                && mWallpaperTarget == srcWin
+                && srcWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) {
+            sendPointerToWallpaperLocked(relWin, pointer, eventTime);
+        }
+    }
+    
     public int addWindow(Session session, IWindow client,
             WindowManager.LayoutParams attrs, int viewVisibility,
             Rect outContentInsets) {
@@ -4918,10 +4944,7 @@
                 Log.w(TAG, "No window to dispatch pointer action " + ev.getAction());
             }
             synchronized (mWindowMap) {
-                if (mSendingPointersToWallpaper) {
-                    Log.i(TAG, "Sending skipped pointer to wallpaper!");
-                    sendPointerToWallpaperLocked(null, ev, ev.getEventTime());
-                }
+                dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), true);
             }
             if (qev != null) {
                 mQueue.recycleEvent(qev);
@@ -4931,10 +4954,7 @@
         }
         if (targetObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
             synchronized (mWindowMap) {
-                if (mSendingPointersToWallpaper) {
-                    Log.i(TAG, "Sending skipped pointer to wallpaper!");
-                    sendPointerToWallpaperLocked(null, ev, ev.getEventTime());
-                }
+                dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), true);
             }
             if (qev != null) {
                 mQueue.recycleEvent(qev);
@@ -5059,9 +5079,7 @@
             if (!target.isVisibleLw()) {
                 // During this motion dispatch, the target window has become
                 // invisible.
-                if (mSendingPointersToWallpaper) {
-                    sendPointerToWallpaperLocked(null, ev, eventTime);
-                }
+                dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), false);
                 if (qev != null) {
                     mQueue.recycleEvent(qev);
                 }
@@ -5094,13 +5112,7 @@
                     }
                 }
 
-                // If we are on top of the wallpaper, then the wallpaper also
-                // gets to see this movement.
-                if ((mWallpaperTarget == target &&
-                        target.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD)
-                        || mSendingPointersToWallpaper) {
-                    sendPointerToWallpaperLocked(null, ev, eventTime);
-                }
+                dispatchPointerElsewhereLocked(target, null, ev, ev.getEventTime(), false);
 
                 final Rect frame = target.mFrame;
                 ev.offsetLocation(-(float)frame.left, -(float)frame.top);
@@ -5355,7 +5367,7 @@
         switch (result) {
             case INJECT_NO_PERMISSION:
                 throw new SecurityException(
-                        "Injecting to another application requires INJECT_EVENT permission");
+                        "Injecting to another application requires INJECT_EVENTS permission");
             case INJECT_SUCCEEDED:
                 return true;
         }
@@ -5383,7 +5395,7 @@
         switch (result) {
             case INJECT_NO_PERMISSION:
                 throw new SecurityException(
-                        "Injecting to another application requires INJECT_EVENT permission");
+                        "Injecting to another application requires INJECT_EVENTS permission");
             case INJECT_SUCCEEDED:
                 return true;
         }
@@ -5411,7 +5423,7 @@
         switch (result) {
             case INJECT_NO_PERMISSION:
                 throw new SecurityException(
-                        "Injecting to another application requires INJECT_EVENT permission");
+                        "Injecting to another application requires INJECT_EVENTS permission");
             case INJECT_SUCCEEDED:
                 return true;
         }
@@ -5477,7 +5489,7 @@
                         + " fin=" + finished + " gfw=" + gotFirstWindow
                         + " ed=" + eventDispatching + " tts=" + timeToSwitch
                         + " wf=" + wasFrozen + " fp=" + focusPaused
-                        + " mcf=" + mCurrentFocus + "}}";
+                        + " mcf=" + curFocus + "}}";
             }
         };
         private DispatchState mDispatchState = null;
@@ -5610,7 +5622,7 @@
                             // If an app switch key has been pressed, and we have
                             // waited too long for the current app to finish
                             // processing keys, then wait no more!
-                            doFinishedKeyLocked(true);
+                            doFinishedKeyLocked(false);
                             continue;
                         }
                         long switchTimeout = mTimeToSwitch - now;
@@ -6008,7 +6020,7 @@
                         + ((mLastWin != null) ? mLastWin.mToken.paused : "null"));
                     if (mLastWin != null && (!mLastWin.mToken.paused || force
                             || !mEventDispatching)) {
-                        doFinishedKeyLocked(false);
+                        doFinishedKeyLocked(true);
                     } else {
                         // Make sure to wake up anyone currently waiting to
                         // dispatch a key, so they can re-evaluate their
@@ -6031,11 +6043,7 @@
 
             if (res != null && returnWhat == RETURN_PENDING_POINTER) {
                 synchronized (mWindowMap) {
-                    if ((mWallpaperTarget == win &&
-                            win.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD)
-                            || mSendingPointersToWallpaper) {
-                        sendPointerToWallpaperLocked(win, res, res.getEventTime());
-                    }
+                    dispatchPointerElsewhereLocked(win, win, res, res.getEventTime(), false);
                 }
             }
 
@@ -6086,13 +6094,9 @@
                         // The new window is above the old; finish pending input to the last
                         // window and start directing it to the new one.
                         mLastWin.mToken.paused = false;
-                        doFinishedKeyLocked(true);  // does a notifyAll()
+                        doFinishedKeyLocked(false);  // does a notifyAll()
+                        return;
                     }
-                    // Either the new window is lower, so there is no need to wake key waiters,
-                    // or we just finished key input to the previous window, which implicitly
-                    // notified the key waiters.  In both cases, we don't need to issue the
-                    // notification here.
-                    return;
                 }
 
                 // Now that we've put a new window state in place, make the event waiter
@@ -6134,7 +6138,7 @@
                         + token.paused);
                     token.paused = false;
                     if (mLastWin != null && mLastWin.mToken == token && mFinished) {
-                        doFinishedKeyLocked(true);
+                        doFinishedKeyLocked(false);
                     } else {
                         notifyAll();
                     }
@@ -6162,14 +6166,14 @@
             }
         }
 
-        private final void doFinishedKeyLocked(boolean doRecycle) {
+        private final void doFinishedKeyLocked(boolean force) {
             if (mLastWin != null) {
                 releasePendingPointerLocked(mLastWin.mSession);
                 releasePendingTrackballLocked(mLastWin.mSession);
             }
 
-            if (mLastWin == null || !mLastWin.mToken.paused
-                || !mLastWin.isVisibleLw()) {
+            if (force || mLastWin == null || !mLastWin.mToken.paused
+                    || !mLastWin.isVisibleLw()) {
                 // If the current window has been paused, we aren't -really-
                 // finished...  so let the waiters still wait.
                 mLastWin = null;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 98ded37..d0f6a7c 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -92,7 +92,6 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.provider.Checkin;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Config;
@@ -966,7 +965,6 @@
     static final int IM_FEELING_LUCKY_MSG = 15;
     static final int LAUNCH_TIMEOUT_MSG = 16;
     static final int DESTROY_TIMEOUT_MSG = 17;
-    static final int SERVICE_ERROR_MSG = 18;
     static final int RESUME_TOP_ACTIVITY_MSG = 19;
     static final int PROC_START_TIMEOUT_MSG = 20;
     static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
@@ -1161,13 +1159,6 @@
                     }
                 }
             } break;
-            case SERVICE_ERROR_MSG: {
-                ServiceRecord srv = (ServiceRecord)msg.obj;
-                // This needs to be *un*synchronized to avoid deadlock.
-                Checkin.logEvent(mContext.getContentResolver(),
-                        Checkin.Events.Tag.SYSTEM_SERVICE_LOOPING,
-                        srv.name.toShortString());
-            } break;
             case RESUME_TOP_ACTIVITY_MSG: {
                 synchronized (ActivityManagerService.this) {
                     resumeTopActivityLocked(null);
@@ -1949,6 +1940,9 @@
             if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
                 debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
             }
+            if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0) {
+                debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
+            }
             if ("1".equals(SystemProperties.get("debug.checkjni"))) {
                 debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
             }
@@ -10764,11 +10758,6 @@
         EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
                 r.shortName, r.restartDelay);
 
-        Message msg = Message.obtain();
-        msg.what = SERVICE_ERROR_MSG;
-        msg.obj = r;
-        mHandler.sendMessage(msg);
-        
         return canceled;
     }
 
diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java
index f5aeaf0..d13f9d3 100644
--- a/services/java/com/android/server/status/StatusBarPolicy.java
+++ b/services/java/com/android/server/status/StatusBarPolicy.java
@@ -22,6 +22,7 @@
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothPbap;
 import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
@@ -30,13 +31,17 @@
 import android.graphics.PixelFormat;
 import android.graphics.drawable.Drawable;
 import android.media.AudioManager;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
 import android.net.NetworkInfo;
+import android.net.Uri;
 import android.net.wifi.WifiManager;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.RemoteException;
+import android.os.storage.StorageManager;
 import android.provider.Settings;
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
@@ -93,6 +98,9 @@
     private IBinder mClockIcon;
     private IconData mClockData;
 
+    // storage
+    private StorageManager mStorageManager;
+
     // battery
     private IBinder mBatteryIcon;
     private IconData mBatteryData;
@@ -105,6 +113,7 @@
     private int mBatteryViewSequence;
     private boolean mBatteryShowLowOnEndCall = false;
     private static final boolean SHOW_LOW_BATTERY_WARNING = true;
+    private static final boolean SHOW_BATTERY_WARNINGS_IN_CALL = true;
 
     // phone
     private TelephonyManager mPhone;
@@ -407,6 +416,11 @@
         mClockIcon = service.addIcon(mClockData, null);
         updateClock();
 
+        // storage
+        mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
+        mStorageManager.registerListener(
+                new com.android.server.status.StorageNotification(context));
+
         // battery
         mBatteryData = IconData.makeIcon("battery",
                 null, com.android.internal.R.drawable.stat_sys_battery_unknown, 0, 0);
@@ -677,7 +691,7 @@
                       + " mBatteryShowLowOnEndCall=" + mBatteryShowLowOnEndCall);
             }
 
-            if (mPhoneState == TelephonyManager.CALL_STATE_IDLE) {
+            if (SHOW_BATTERY_WARNINGS_IN_CALL || mPhoneState == TelephonyManager.CALL_STATE_IDLE) {
                 showLowBatteryWarning();
             } else {
                 mBatteryShowLowOnEndCall = true;
@@ -801,6 +815,21 @@
             d.show();
             mLowBatteryDialog = d;
         }
+
+        final ContentResolver cr = mContext.getContentResolver();
+        if (Settings.System.getInt(cr,
+                Settings.System.POWER_SOUNDS_ENABLED, 1) == 1) 
+        {
+            final String soundPath = Settings.System.getString(cr,
+                Settings.System.LOW_BATTERY_SOUND);
+            if (soundPath != null) {
+                final Uri soundUri = Uri.parse("file://" + soundPath);
+                if (soundUri != null) {
+                    final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
+                    if (sfx != null) sfx.play();
+                }
+            }
+        }
     }
 
     private final void updateCallState(int state) {
diff --git a/core/java/com/android/internal/app/StorageNotification.java b/services/java/com/android/server/status/StorageNotification.java
similarity index 97%
rename from core/java/com/android/internal/app/StorageNotification.java
rename to services/java/com/android/server/status/StorageNotification.java
index 8876612..3b79049 100644
--- a/core/java/com/android/internal/app/StorageNotification.java
+++ b/services/java/com/android/server/status/StorageNotification.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.app;
+package com.android.server.status;
 
 import android.app.Activity;
 import android.app.Notification;
@@ -119,7 +119,7 @@
              * for stopping UMS.
              */
             Intent intent = new Intent();
-            intent.setClass(mContext, com.android.internal.app.UsbStorageActivity.class);
+            intent.setClass(mContext, com.android.server.status.UsbStorageActivity.class);
             PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
             setUsbStorageNotification(
                     com.android.internal.R.string.usb_storage_stop_notification_title,
@@ -237,7 +237,7 @@
 
         if (available) {
             Intent intent = new Intent();
-            intent.setClass(mContext, com.android.internal.app.UsbStorageActivity.class);
+            intent.setClass(mContext, com.android.server.status.UsbStorageActivity.class);
             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
             PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
             setUsbStorageNotification(
@@ -253,8 +253,8 @@
     /**
      * Sets the USB storage notification.
      */
-    private synchronized void setUsbStorageNotification(int titleId, int messageId, int icon, boolean sound, boolean visible,
-                                                        PendingIntent pi) {
+    private synchronized void setUsbStorageNotification(int titleId, int messageId, int icon,
+            boolean sound, boolean visible, PendingIntent pi) {
 
         if (!visible && mUsbStorageNotification == null) {
             return;
diff --git a/core/java/com/android/internal/app/UsbStorageActivity.java b/services/java/com/android/server/status/UsbStorageActivity.java
similarity index 98%
rename from core/java/com/android/internal/app/UsbStorageActivity.java
rename to services/java/com/android/server/status/UsbStorageActivity.java
index 991f04b..7a2a2d6 100644
--- a/core/java/com/android/internal/app/UsbStorageActivity.java
+++ b/services/java/com/android/server/status/UsbStorageActivity.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.app;
+package com.android.server.status;
 
 import android.app.Activity;
 import android.content.BroadcastReceiver;
diff --git a/telephony/java/android/telephony/cdma/CdmaCellLocation.java b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
index 7ef7747..2a0f8cd 100644
--- a/telephony/java/android/telephony/cdma/CdmaCellLocation.java
+++ b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
@@ -26,12 +26,17 @@
     private int mBaseStationId = -1;
 
     /**
+     * @hide
+     */
+    public final static int INVALID_LAT_LONG = Integer.MAX_VALUE;
+
+    /**
      * Latitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0.
      * It is represented in units of 0.25 seconds and ranges from -1296000
      * to 1296000, both values inclusive (corresponding to a range of -90
      * to +90 degrees). Integer.MAX_VALUE is considered invalid value.
      */
-    private int mBaseStationLatitude = Integer.MAX_VALUE;
+    private int mBaseStationLatitude = INVALID_LAT_LONG;
 
     /**
      * Longitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0.
@@ -39,7 +44,7 @@
      * to 2592000, both values inclusive (corresponding to a range of -180
      * to +180 degrees). Integer.MAX_VALUE is considered invalid value.
      */
-    private int mBaseStationLongitude = Integer.MAX_VALUE;
+    private int mBaseStationLongitude = INVALID_LAT_LONG;
 
     private int mSystemId = -1;
     private int mNetworkId = -1;
@@ -51,8 +56,8 @@
      */
     public CdmaCellLocation() {
         this.mBaseStationId = -1;
-        this.mBaseStationLatitude = Integer.MAX_VALUE;
-        this.mBaseStationLongitude = Integer.MAX_VALUE;
+        this.mBaseStationLatitude = INVALID_LAT_LONG;
+        this.mBaseStationLongitude = INVALID_LAT_LONG;
         this.mSystemId = -1;
         this.mNetworkId = -1;
     }
@@ -60,12 +65,12 @@
     /**
      * Initialize the object from a bundle.
      */
-    public CdmaCellLocation(Bundle bundleWithValues) {
-        this.mBaseStationId = bundleWithValues.getInt("baseStationId");
-        this.mBaseStationLatitude = bundleWithValues.getInt("baseStationLatitude");
-        this.mBaseStationLongitude = bundleWithValues.getInt("baseStationLongitude");
-        this.mSystemId = bundleWithValues.getInt("systemId");
-        this.mNetworkId = bundleWithValues.getInt("networkId");
+    public CdmaCellLocation(Bundle bundle) {
+        this.mBaseStationId = bundle.getInt("baseStationId", mBaseStationId);
+        this.mBaseStationLatitude = bundle.getInt("baseStationLatitude", mBaseStationLatitude);
+        this.mBaseStationLongitude = bundle.getInt("baseStationLongitude", mBaseStationLongitude);
+        this.mSystemId = bundle.getInt("systemId", mSystemId);
+        this.mNetworkId = bundle.getInt("networkId", mNetworkId);
     }
 
     /**
@@ -108,8 +113,8 @@
      */
     public void setStateInvalid() {
         this.mBaseStationId = -1;
-        this.mBaseStationLatitude = Integer.MAX_VALUE;
-        this.mBaseStationLongitude = Integer.MAX_VALUE;
+        this.mBaseStationLatitude = INVALID_LAT_LONG;
+        this.mBaseStationLongitude = INVALID_LAT_LONG;
         this.mSystemId = -1;
         this.mNetworkId = -1;
     }
diff --git a/telephony/java/android/telephony/gsm/GsmCellLocation.java b/telephony/java/android/telephony/gsm/GsmCellLocation.java
index 637a11c..0d4e0be 100644
--- a/telephony/java/android/telephony/gsm/GsmCellLocation.java
+++ b/telephony/java/android/telephony/gsm/GsmCellLocation.java
@@ -38,8 +38,8 @@
      * Initialize the object from a bundle.
      */
     public GsmCellLocation(Bundle bundle) {
-        mLac = bundle.getInt("lac");
-        mCid = bundle.getInt("cid");
+        mLac = bundle.getInt("lac", mLac);
+        mCid = bundle.getInt("cid", mCid);
     }
 
     /**
@@ -120,5 +120,3 @@
         m.putInt("cid", mCid);
     }
 }
-
-
diff --git a/telephony/java/com/android/internal/telephony/BaseCommands.java b/telephony/java/com/android/internal/telephony/BaseCommands.java
index 7421854..b962375 100644
--- a/telephony/java/com/android/internal/telephony/BaseCommands.java
+++ b/telephony/java/com/android/internal/telephony/BaseCommands.java
@@ -22,7 +22,6 @@
 import android.os.Registrant;
 import android.os.Handler;
 import android.os.AsyncResult;
-import android.provider.Checkin;
 import android.util.Config;
 import android.util.Log;
 
@@ -618,13 +617,6 @@
                 return;
             }
 
-            if (mContext != null &&
-                    newState == RadioState.RADIO_UNAVAILABLE &&
-                    oldState != RadioState.RADIO_OFF) {
-                Checkin.updateStats(mContext.getContentResolver(),
-                        Checkin.Stats.Tag.PHONE_RADIO_RESETS, 1, 0.0);
-            }
-
             mRadioStateChangedRegistrants.notifyRegistrants();
 
             if (mState.isAvailable() && !oldState.isAvailable()) {
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
index a01bc09..562a9f8 100644
--- a/telephony/java/com/android/internal/telephony/DataConnection.java
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -536,8 +536,7 @@
                             break;
                         case ERR_BadDns:
                             // Connection succeeded but DNS info is bad so disconnect
-                            EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_BAD_DNS_ADDRESS,
-                                    dnsServers[0]);
+                            EventLog.writeEvent(EventLogTags.PDP_BAD_DNS_ADDRESS, dnsServers[0]);
                             tearDownData(cp);
                             transitionTo(mDisconnectingBadDnsState);
                             break;
diff --git a/telephony/java/com/android/internal/telephony/EventLogTags.logtags b/telephony/java/com/android/internal/telephony/EventLogTags.logtags
new file mode 100644
index 0000000..b06c27d
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/EventLogTags.logtags
@@ -0,0 +1,55 @@
+# See system/core/logcat/event.logtags for a description of the format of this file.
+
+option java_package com.android.internal.telephony;
+
+# PDP Context has a bad DNS address
+50100 pdp_bad_dns_address (dns_address|3)
+
+# For data connection on PDP context, reached the data-out-without-data-in
+# packet count that triggers a countdown to radio restart
+50101 pdp_radio_reset_countdown_triggered (out_packet_count|1|1)
+
+# Radio restart - timed out with no incoming packets.
+50102 pdp_radio_reset (out_packet_count|1|1)
+
+# PDP context reset - timed out with no incoming packets.
+50103 pdp_context_reset (out_packet_count|1|1)
+
+# Reregister to data network - timed out with no incoming packets.
+50104 pdp_reregister_network (out_packet_count|1|1)
+
+# PDP Setup failures
+50105 pdp_setup_fail (cause|1|5), (cid|1|5), (network_type|1|5)
+
+# Call drops
+50106 call_drop (cause|1|5), (cid|1|5), (network_type|1|5)
+
+# Data network registration failed after successful voice registration
+50107 data_network_registration_fail (op_numeric|1|5), (cid|1|5)
+
+# Suspicious status of data connection while radio poweroff
+50108 data_network_status_on_radio_off (dc_state|3), (enable|1|5)
+
+# PDP drop caused by network
+50109 pdp_network_drop (cid|1|5), (network_type|1|5)
+
+# CDMA data network setup failure
+50110 cdma_data_setup_failed (cause|1|5), (cid|1|5), (network_type|1|5)
+
+# CDMA data network drop
+50111 cdma_data_drop (cid|1|5), (network_type|1|5)
+
+# GSM radio access technology switched
+50112 gsm_rat_switched (cid|1|5), (network_from|1|5), (network_to|1|5)
+
+# GSM data connection state transition
+50113 gsm_data_state_change (oldState|3), (newState|3)
+
+# GSM service state transition
+50114 gsm_service_state_change (oldState|1|5), (oldGprsState|1|5), (newState|1|5), (newGprsState|1|5)
+
+# CDMA data connection state transition
+50115 cdma_data_state_change (oldState|3), (newState|3)
+
+# CDMA service state transition
+50116 cdma_service_state_change (oldState|1|5), (oldDataState|1|5), (newState|1|5), (newDataState|1|5)
diff --git a/telephony/java/com/android/internal/telephony/TelephonyEventLog.java b/telephony/java/com/android/internal/telephony/TelephonyEventLog.java
deleted file mode 100644
index 0f15cb6..0000000
--- a/telephony/java/com/android/internal/telephony/TelephonyEventLog.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-package com.android.internal.telephony;
-
-/* This class contains the details related to Telephony Event Logging */
-public final class TelephonyEventLog {
-
-    /* Event log tags */
-    public static final int EVENT_LOG_BAD_DNS_ADDRESS = 50100;
-    public static final int EVENT_LOG_RADIO_RESET_COUNTDOWN_TRIGGERED = 50101;
-    public static final int EVENT_LOG_RADIO_RESET = 50102;
-    public static final int EVENT_LOG_PDP_RESET = 50103;
-    public static final int EVENT_LOG_REREGISTER_NETWORK = 50104;
-    public static final int EVENT_LOG_RADIO_PDP_SETUP_FAIL = 50105;
-    public static final int EVENT_LOG_CALL_DROP = 50106;
-    public static final int EVENT_LOG_CGREG_FAIL = 50107;
-    public static final int EVENT_LOG_DATA_STATE_RADIO_OFF = 50108;
-    public static final int EVENT_LOG_PDP_NETWORK_DROP = 50109;
-    public static final int EVENT_LOG_CDMA_DATA_SETUP_FAILED = 50110;
-    public static final int EVENT_LOG_CDMA_DATA_DROP = 50111;
-    public static final int EVENT_LOG_GSM_RAT_SWITCHED = 50112;
-}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index 979b8ba..fbb3c4c 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -33,7 +33,6 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.preference.PreferenceManager;
-import android.provider.Checkin;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 import android.telephony.cdma.CdmaCellLocation;
@@ -43,13 +42,13 @@
 
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.DataCallState;
-import com.android.internal.telephony.DataConnection;
 import com.android.internal.telephony.DataConnection.FailCause;
+import com.android.internal.telephony.DataConnection;
 import com.android.internal.telephony.DataConnectionTracker;
-import com.android.internal.telephony.RetryManager;
+import com.android.internal.telephony.EventLogTags;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.RetryManager;
 import com.android.internal.telephony.ServiceStateTracker;
-import com.android.internal.telephony.TelephonyEventLog;
 
 import java.util.ArrayList;
 
@@ -232,18 +231,10 @@
     protected void setState(State s) {
         if (DBG) log ("setState: " + s);
         if (state != s) {
-            if (s == State.INITING) { // request Data connection context
-                Checkin.updateStats(phone.getContext().getContentResolver(),
-                        Checkin.Stats.Tag.PHONE_CDMA_DATA_ATTEMPTED, 1, 0.0);
-            }
-
-            if (s == State.CONNECTED) { // pppd is up
-                Checkin.updateStats(phone.getContext().getContentResolver(),
-                        Checkin.Stats.Tag.PHONE_CDMA_DATA_CONNECTED, 1, 0.0);
-            }
+            EventLog.writeEvent(EventLogTags.CDMA_DATA_STATE_CHANGE,
+                    state.toString(), s.toString());
+            state = s;
         }
-
-        state = s;
     }
 
     @Override
@@ -528,7 +519,7 @@
 
                     if (mNoRecvPollCount == 0) {
                         EventLog.writeEvent(
-                                TelephonyEventLog.EVENT_LOG_RADIO_RESET_COUNTDOWN_TRIGGERED,
+                                EventLogTags.PDP_RADIO_RESET_COUNTDOWN_TRIGGERED,
                                 sentSinceLastRecv);
                     }
 
@@ -543,8 +534,7 @@
                         netStatPollEnabled = false;
                         stopNetStatPoll();
                         restartRadio();
-                        EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_RADIO_RESET,
-                                NO_RECV_POLL_LIMIT);
+                        EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, NO_RECV_POLL_LIMIT);
                     }
                 } else {
                     mNoRecvPollCount = 0;
@@ -822,7 +812,7 @@
                 mRetryMgr.resetRetryCount();
 
                 CdmaCellLocation loc = (CdmaCellLocation)(phone.getCellLocation());
-                EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CDMA_DATA_SETUP_FAILED,
+                EventLog.writeEvent(EventLogTags.CDMA_DATA_SETUP_FAILED,
                         loc != null ? loc.getBaseStationId() : -1,
                         TelephonyManager.getDefault().getNetworkType());
             }
@@ -863,7 +853,7 @@
 
     private void writeEventLogCdmaDataDrop() {
         CdmaCellLocation loc = (CdmaCellLocation)(phone.getCellLocation());
-        EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CDMA_DATA_DROP,
+        EventLog.writeEvent(EventLogTags.CDMA_DATA_DROP,
                 loc != null ? loc.getBaseStationId() : -1,
                 TelephonyManager.getDefault().getNetworkType());
     }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index 7f2ba47..39fe007 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -29,7 +29,6 @@
 import android.os.RegistrantList;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.provider.Checkin;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 import android.provider.Telephony.Intents;
@@ -45,10 +44,10 @@
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.DataConnectionTracker;
+import com.android.internal.telephony.EventLogTags;
 import com.android.internal.telephony.IccCard;
 import com.android.internal.telephony.MccTable;
 import com.android.internal.telephony.ServiceStateTracker;
-import com.android.internal.telephony.TelephonyEventLog;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyProperties;
 
@@ -358,8 +357,8 @@
             if (ar.exception == null) {
                 String states[] = (String[])ar.result;
                 int baseStationId = -1;
-                int baseStationLatitude = Integer.MAX_VALUE;
-                int baseStationLongitude = Integer.MAX_VALUE;
+                int baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG;
+                int baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
                 int systemId = -1;
                 int networkId = -1;
 
@@ -374,6 +373,11 @@
                         if (states[6] != null) {
                             baseStationLongitude = Integer.parseInt(states[6]);
                         }
+                        // Some carriers only return lat-lngs of 0,0
+                        if (baseStationLatitude == 0 && baseStationLongitude == 0) {
+                            baseStationLatitude  = CdmaCellLocation.INVALID_LAT_LONG;
+                            baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
+                        }
                         if (states[8] != null) {
                             systemId = Integer.parseInt(states[8]);
                         }
@@ -537,7 +541,7 @@
         } else if (!mDesiredPowerState && cm.getRadioState().isOn()) {
             DataConnectionTracker dcTracker = phone.mDataConnection;
             if (! dcTracker.isDataConnectionAsDesired()) {
-                EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_DATA_STATE_RADIO_OFF,
+                EventLog.writeEvent(EventLogTags.DATA_NETWORK_STATUS_ON_RADIO_OFF,
                         dcTracker.getStateInString(),
                         dcTracker.getAnyDataEnabled() ? 1 : 0);
             }
@@ -663,8 +667,10 @@
                 int registrationState = 4;     //[0] registrationState
                 int radioTechnology = -1;      //[3] radioTechnology
                 int baseStationId = -1;        //[4] baseStationId
-                int baseStationLatitude = Integer.MAX_VALUE;  //[5] baseStationLatitude
-                int baseStationLongitude = Integer.MAX_VALUE; //[6] baseStationLongitude
+                //[5] baseStationLatitude
+                int baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG;
+                //[6] baseStationLongitude
+                int baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
                 int cssIndicator = 0;          //[7] init with 0, because it is treated as a boolean
                 int systemId = 0;              //[8] systemId
                 int networkId = 0;             //[9] networkId
@@ -690,6 +696,11 @@
                         if (states[6] != null) {
                             baseStationLongitude = Integer.parseInt(states[6]);
                         }
+                        // Some carriers only return lat-lngs of 0,0
+                        if (baseStationLatitude == 0 && baseStationLongitude == 0) {
+                            baseStationLatitude  = CdmaCellLocation.INVALID_LAT_LONG;
+                            baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
+                        }
                         if (states[7] != null) {
                             cssIndicator = Integer.parseInt(states[7]);
                         }
@@ -1013,6 +1024,14 @@
 
         boolean hasLocationChanged = !newCellLoc.equals(cellLoc);
 
+        // Add an event log when connection state changes
+        if (ss.getState() != newSS.getState() ||
+                cdmaDataConnectionState != newCdmaDataConnectionState) {
+            EventLog.writeEvent(EventLogTags.CDMA_SERVICE_STATE_CHANGE,
+                    ss.getState(), cdmaDataConnectionState,
+                    newSS.getState(), newCdmaDataConnectionState);
+        }
+
         ServiceState tss;
         tss = ss;
         ss = newSS;
@@ -1035,7 +1054,6 @@
         }
 
         if (hasRegistered) {
-            Checkin.updateStats(cr, Checkin.Stats.Tag.PHONE_CDMA_REGISTERED, 1, 0.0);
             networkAttachedRegistrants.notifyRegistrants();
         }
 
@@ -1185,32 +1203,23 @@
         } else {
             int[] ints = (int[])ar.result;
             int offset = 2;
-
             int cdmaDbm = (ints[offset] > 0) ? -ints[offset] : -120;
             int cdmaEcio = (ints[offset+1] > 0) ? -ints[offset+1] : -160;
+            int evdoRssi = (ints[offset+2] > 0) ? -ints[offset+2] : -120;
+            int evdoEcio = (ints[offset+3] > 0) ? -ints[offset+3] : -1;
+            int evdoSnr  = ((ints[offset+4] > 0) && (ints[offset+4] <= 8)) ? ints[offset+4] : -1;
 
-            int evdoRssi = -1;
-            int evdoEcio = -1;
-            int evdoSnr = -1;
-            if ((networkType == ServiceState.RADIO_TECHNOLOGY_EVDO_0)
-                    || (networkType == ServiceState.RADIO_TECHNOLOGY_EVDO_A)) {
-                evdoRssi = (ints[offset+2] > 0) ? -ints[offset+2] : -120;
-                evdoEcio = (ints[offset+3] > 0) ? -ints[offset+3] : -1;
-                evdoSnr  = ((ints[offset+4] > 0) && (ints[offset+4] <= 8)) ? ints[offset+4] : -1;
-            }
-
+            //log(String.format("onSignalStrengthResult cdmaDbm=%d cdmaEcio=%d evdoRssi=%d evdoEcio=%d evdoSnr=%d",
+            //        cdmaDbm, cdmaEcio, evdoRssi, evdoEcio, evdoSnr));
             mSignalStrength = new SignalStrength(99, -1, cdmaDbm, cdmaEcio,
                     evdoRssi, evdoEcio, evdoSnr, false);
         }
 
-        if (!mSignalStrength.equals(oldSignalStrength)) {
-            try { // This takes care of delayed EVENT_POLL_SIGNAL_STRENGTH (scheduled after
-                  // POLL_PERIOD_MILLIS) during Radio Technology Change)
-                phone.notifySignalStrength();
-           } catch (NullPointerException ex) {
-                log("onSignalStrengthResult() Phone already destroyed: " + ex
-                        + "SignalStrength not notified");
-           }
+        try {
+            phone.notifySignalStrength();
+        } catch (NullPointerException ex) {
+            log("onSignalStrengthResult() Phone already destroyed: " + ex
+                    + "SignalStrength not notified");
         }
     }
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/TtyIntent.java b/telephony/java/com/android/internal/telephony/cdma/TtyIntent.java
index f27f79c..3813b1d 100644
--- a/telephony/java/com/android/internal/telephony/cdma/TtyIntent.java
+++ b/telephony/java/com/android/internal/telephony/cdma/TtyIntent.java
@@ -43,4 +43,25 @@
      */
     public static final String TTY_ENABLED = "ttyEnabled";
 
+    /**
+     * Broadcast intent action indicating that the TTY preferred operating mode
+     * has changed. An intent extra provides the new mode as an int.
+     * @see #TTY_PREFFERED_MODE
+     *
+     * {@hide}
+     */
+    public static final String TTY_PREFERRED_MODE_CHANGE_ACTION =
+        "com.android.internal.telephony.cdma.intent.action.TTY_PREFERRED_MODE_CHANGE";
+
+    /**
+     * The lookup key for an int that indicates preferred TTY mode.
+     * Valid modes are:
+     * - {@link Phone.TTY_MODE_OFF}
+     * - {@link Phone.TTY_MODE_FULL}
+     * - {@link Phone.TTY_MODE_HCO}
+     * - {@link Phone.TTY_MODE_VCO}
+     *
+     * {@hide}
+     */
+    public static final String TTY_PREFFERED_MODE = "ttyPreferredMode";
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java
index f4b9931..87530e4 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmCallTracker.java
@@ -16,11 +16,16 @@
 
 package com.android.internal.telephony.gsm;
 
-import android.os.*;
-import android.telephony.gsm.GsmCellLocation;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Registrant;
+import android.os.RegistrantList;
+import android.os.SystemProperties;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
+import android.telephony.gsm.GsmCellLocation;
 import android.util.EventLog;
 import android.util.Log;
 
@@ -29,13 +34,13 @@
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.Connection;
 import com.android.internal.telephony.DriverCall;
+import com.android.internal.telephony.EventLogTags;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.TelephonyProperties;
 import com.android.internal.telephony.gsm.CallFailCause;
+import com.android.internal.telephony.gsm.GSMPhone;
 import com.android.internal.telephony.gsm.GsmCall;
 import com.android.internal.telephony.gsm.GsmConnection;
-import com.android.internal.telephony.gsm.GSMPhone;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.TelephonyEventLog;
-import com.android.internal.telephony.*;
 
 import java.util.List;
 import java.util.ArrayList;
@@ -869,7 +874,7 @@
                     causeCode == CallFailCause.BEARER_NOT_AVAIL ||
                     causeCode == CallFailCause.ERROR_UNSPECIFIED) {
                     GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
-                    EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CALL_DROP,
+                    EventLog.writeEvent(EventLogTags.CALL_DROP,
                             causeCode, loc != null ? loc.getCid() : -1,
                             TelephonyManager.getDefault().getNetworkType());
                 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 6695ccb..1fd6be8 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -38,7 +38,6 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.preference.PreferenceManager;
-import android.provider.Checkin;
 import android.provider.Settings;
 import android.provider.Telephony;
 import android.telephony.ServiceState;
@@ -53,7 +52,7 @@
 import com.android.internal.telephony.DataConnectionTracker;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.RetryManager;
-import com.android.internal.telephony.TelephonyEventLog;
+import com.android.internal.telephony.EventLogTags;
 import com.android.internal.telephony.DataConnection.FailCause;
 
 import java.io.IOException;
@@ -301,21 +300,10 @@
     protected void setState(State s) {
         if (DBG) log ("setState: " + s);
         if (state != s) {
-            if (s == State.INITING) { // request PDP context
-                Checkin.updateStats(
-                        phone.getContext().getContentResolver(),
-                        Checkin.Stats.Tag.PHONE_GPRS_ATTEMPTED, 1, 0.0);
-            }
-
-            if (s == State.CONNECTED) { // pppd is up
-                Checkin.updateStats(
-                        phone.getContext().getContentResolver(),
-                        Checkin.Stats.Tag.PHONE_GPRS_CONNECTED, 1, 0.0);
-            }
+            EventLog.writeEvent(EventLogTags.GSM_DATA_STATE_CHANGE, state.toString(), s.toString());
+            state = s;
         }
 
-        state = s;
-
         if (state == State.FAILED) {
             if (waitingApns != null)
                 waitingApns.clear(); // when teardown the connection and set to IDLE
@@ -711,7 +699,7 @@
 
                 // Add an event log when the network drops PDP
                 GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
-                EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_NETWORK_DROP,
+                EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP,
                         loc != null ? loc.getCid() : -1,
                         TelephonyManager.getDefault().getNetworkType());
 
@@ -732,7 +720,7 @@
 
                     // Log the network drop on the event log.
                     GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
-                    EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_NETWORK_DROP,
+                    EventLog.writeEvent(EventLogTags.PDP_NETWORK_DROP,
                             loc != null ? loc.getCid() : -1,
                             TelephonyManager.getDefault().getNetworkType());
 
@@ -778,11 +766,11 @@
                     DEFAULT_MAX_PDP_RESET_FAIL);
             if (mPdpResetCount < maxPdpReset) {
                 mPdpResetCount++;
-                EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_RESET, sentSinceLastRecv);
+                EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, sentSinceLastRecv);
                 cleanUpConnection(true, Phone.REASON_PDP_RESET);
             } else {
                 mPdpResetCount = 0;
-                EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_REREGISTER_NETWORK, sentSinceLastRecv);
+                EventLog.writeEvent(EventLogTags.PDP_REREGISTER_NETWORK, sentSinceLastRecv);
                 mGsmPhone.mSST.reRegisterNetwork(null);
             }
             // TODO: Add increasingly drastic recovery steps, eg,
@@ -882,7 +870,7 @@
             if (sentSinceLastRecv >= watchdogTrigger) {
                 // we already have NUMBER_SENT_PACKETS sent without ack
                 if (mNoRecvPollCount == 0) {
-                    EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_RADIO_RESET_COUNTDOWN_TRIGGERED,
+                    EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET_COUNTDOWN_TRIGGERED,
                             sentSinceLastRecv);
                 }
 
@@ -955,7 +943,7 @@
         if (status == 0) {
             // ping succeeded.  False alarm.  Reset netStatPoll.
             // ("-1" for this event indicates a false alarm)
-            EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_RESET, -1);
+            EventLog.writeEvent(EventLogTags.PDP_RADIO_RESET, -1);
             mPdpResetCount = 0;
             sendMessage(obtainMessage(EVENT_START_NETSTAT_POLL));
         } else {
@@ -1145,7 +1133,7 @@
                     // Log this failure to the Event Logs.
             if (cause.isEventLoggable()) {
                 GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
-                EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_RADIO_PDP_SETUP_FAIL,
+                EventLog.writeEvent(EventLogTags.PDP_SETUP_FAIL,
                         cause.ordinal(), loc != null ? loc.getCid() : -1,
                         TelephonyManager.getDefault().getNetworkType());
             }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index 917fbfe..6352b41 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -35,7 +35,6 @@
 import android.os.RegistrantList;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.provider.Checkin;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 import android.provider.Telephony.Intents;
@@ -52,11 +51,11 @@
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.DataConnectionTracker;
+import com.android.internal.telephony.EventLogTags;
 import com.android.internal.telephony.IccCard;
 import com.android.internal.telephony.MccTable;
 import com.android.internal.telephony.RILConstants;
 import com.android.internal.telephony.ServiceStateTracker;
-import com.android.internal.telephony.TelephonyEventLog;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyProperties;
 
@@ -508,7 +507,7 @@
                     // i.e. CREG is ok while CGREG is not
                     // possible a network or baseband side error
                     GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
-                    EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CGREG_FAIL,
+                    EventLog.writeEvent(EventLogTags.DATA_NETWORK_REGISTRATION_FAIL,
                             ss.getOperatorNumeric(), loc != null ? loc.getCid() : -1);
                     mReportedGprsNoReg = true;
                 }
@@ -540,7 +539,7 @@
         } else if (!mDesiredPowerState && cm.getRadioState().isOn()) {
             DataConnectionTracker dcTracker = phone.mDataConnection;
             if (! dcTracker.isDataConnectionAsDesired()) {
-                EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_DATA_STATE_RADIO_OFF,
+                EventLog.writeEvent(EventLogTags.DATA_NETWORK_STATUS_ON_RADIO_OFF,
                         dcTracker.getStateInString(), dcTracker.getAnyDataEnabled() ? 1 : 0);
             }
             // If it's on and available and we want it off gracefully
@@ -889,6 +888,12 @@
 
         boolean hasEmergencyOnlyChanged = mNewEmergencyOnly != mEmergencyOnly;
 
+        // Add an event log when connection state changes
+        if (ss.getState() != newSS.getState() || gprsState != newGPRSState) {
+            EventLog.writeEvent(EventLogTags.GSM_SERVICE_STATE_CHANGE,
+                ss.getState(), gprsState, newSS.getState(), newGPRSState);
+        }
+
         ServiceState tss;
         tss = ss;
         ss = newSS;
@@ -902,7 +907,6 @@
 
         mEmergencyOnly = mNewEmergencyOnly;
 
-
         // Add an event log when network type switched
         // TODO: we may add filtering to reduce the event logged,
         // i.e. check preferred network setting, only switch to 2G, etc
@@ -910,8 +914,7 @@
             int cid = -1;
             GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
             if (loc != null) cid = loc.getCid();
-            EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_GSM_RAT_SWITCHED,
-                    cid, networkType, newNetworkType);
+            EventLog.writeEvent(EventLogTags.GSM_RAT_SWITCHED, cid, networkType, newNetworkType);
             Log.d(LOG_TAG,
                     "RAT switched " + networkTypeToString(networkType) + " -> "
                     + networkTypeToString(newNetworkType) + " at cell " + cid);
@@ -928,8 +931,6 @@
         }
 
         if (hasRegistered) {
-            Checkin.updateStats(phone.getContext().getContentResolver(),
-                    Checkin.Stats.Tag.PHONE_GSM_REGISTERED, 1, 0.0);
             networkAttachedRegistrants.notifyRegistrants();
         }
 
diff --git a/test-runner/android/test/ActivityInstrumentationTestCase.java b/test-runner/android/test/ActivityInstrumentationTestCase.java
index f6b31ad..d12ff6f 100644
--- a/test-runner/android/test/ActivityInstrumentationTestCase.java
+++ b/test-runner/android/test/ActivityInstrumentationTestCase.java
@@ -40,29 +40,26 @@
     boolean mInitialTouchMode = false;
 
     /**
-     * <b>NOTE:</b> The parameter <i>pkg</i> must refer to the package identifier of the
-     * package hosting the activity to be launched, which is specified in the AndroidManifest.xml
-     * file.  This is not necessarily the same as the java package name.
+     * Creates an {@link ActivityInstrumentationTestCase} in non-touch mode.
      * 
-     * @param pkg The package hosting the activity to be launched.
-     * @param activityClass The activity to test.
+     * @param pkg ignored - no longer in use.
+     * @param activityClass The activity to test. This must be a class in the instrumentation
+     * targetPackage specified in the AndroidManifest.xml
      */
     public ActivityInstrumentationTestCase(String pkg, Class<T> activityClass) {
         this(pkg, activityClass, false);
     }
 
     /**
-     * <b>NOTE:</b> The parameter <i>pkg</i> must refer to the package identifier of the
-     * package hosting the activity to be launched, which is specified in the AndroidManifest.xml
-     * file.  This is not necessarily the same as the java package name.
-     * 
-     * @param pkg The package hosting the activity to be launched.
-     * @param activityClass The activity to test.
+     * Creates an {@link ActivityInstrumentationTestCase}.
+     *
+     * @param pkg ignored - no longer in use.
+     * @param activityClass The activity to test. This must be a class in the instrumentation
+     * targetPackage specified in the AndroidManifest.xml
      * @param initialTouchMode true = in touch mode
      */
     public ActivityInstrumentationTestCase(String pkg, Class<T> activityClass, 
             boolean initialTouchMode) {
-        mPackage = pkg;
         mActivityClass = activityClass;
         mInitialTouchMode = initialTouchMode;
     }
@@ -77,7 +74,8 @@
         super.setUp();
         // set initial touch mode
         getInstrumentation().setInTouchMode(mInitialTouchMode);
-        setActivity(launchActivity(mPackage, mActivityClass, null));
+        final String targetPackageName = getInstrumentation().getTargetContext().getPackageName();
+        setActivity(launchActivity(targetPackageName, mActivityClass, null));
     }
 
     @Override
diff --git a/test-runner/android/test/ActivityInstrumentationTestCase2.java b/test-runner/android/test/ActivityInstrumentationTestCase2.java
index 679f634..e8570bd 100644
--- a/test-runner/android/test/ActivityInstrumentationTestCase2.java
+++ b/test-runner/android/test/ActivityInstrumentationTestCase2.java
@@ -40,21 +40,31 @@
  */
 public abstract class ActivityInstrumentationTestCase2<T extends Activity> 
         extends ActivityTestCase {
-    String mPackage;
     Class<T> mActivityClass;
     boolean mInitialTouchMode = false;
     Intent mActivityIntent = null;
 
     /**
-     * <b>NOTE:</b> The parameter <i>pkg</i> must refer to the package identifier of the
-     * package hosting the activity to be launched, which is specified in the AndroidManifest.xml
-     * file.  This is not necessarily the same as the java package name.
-     * 
-     * @param pkg The package hosting the activity to be launched.
-     * @param activityClass The activity to test.
+     * Creates an {@link ActivityInstrumentationTestCase2}.
+     *
+     * @param pkg ignored - no longer in use.
+     * @param activityClass The activity to test. This must be a class in the instrumentation
+     * targetPackage specified in the AndroidManifest.xml
+     *
+     * @deprecated use {@link #ActivityInstrumentationTestCase2(Class)} instead
      */
+    @Deprecated
     public ActivityInstrumentationTestCase2(String pkg, Class<T> activityClass) {
-        mPackage = pkg;
+        this(activityClass);
+    }
+
+    /**
+     * Creates an {@link ActivityInstrumentationTestCase2}.
+     *
+     * @param activityClass The activity to test. This must be a class in the instrumentation
+     * targetPackage specified in the AndroidManifest.xml
+     */
+    public ActivityInstrumentationTestCase2(Class<T> activityClass) {
         mActivityClass = activityClass;
     }
 
@@ -82,11 +92,12 @@
         if (a == null) {
             // set initial touch mode
             getInstrumentation().setInTouchMode(mInitialTouchMode);
+            final String targetPackage = getInstrumentation().getTargetContext().getPackageName();
             // inject custom intent, if provided
             if (mActivityIntent == null) {
-                a = launchActivity(mPackage, mActivityClass, null);
+                a = launchActivity(targetPackage, mActivityClass, null);
             } else {
-                a = launchActivityWithIntent(mPackage, mActivityClass, mActivityIntent);
+                a = launchActivityWithIntent(targetPackage, mActivityClass, mActivityIntent);
             }
             setActivity(a);
         }
diff --git a/test-runner/android/test/ProviderTestCase2.java b/test-runner/android/test/ProviderTestCase2.java
index a923d2a..f3655fc 100644
--- a/test-runner/android/test/ProviderTestCase2.java
+++ b/test-runner/android/test/ProviderTestCase2.java
@@ -8,6 +8,8 @@
 import android.test.mock.MockContentResolver;
 import android.database.DatabaseUtils;
 
+import java.io.File;
+
 /**
  * This TestCase class provides a framework for isolated testing of a single
  * ContentProvider.  It uses a {@link android.test.mock.MockContentResolver} to
@@ -33,6 +35,13 @@
         public Resources getResources() {
             return getContext().getResources();
         }
+
+        @Override
+        public File getDir(String name, int mode) {
+            // name the directory so the directory will be seperated from
+            // one created through the regular Context
+            return getContext().getDir("mockcontext2_" + name, mode);
+        }
     }
 
     public ProviderTestCase2(Class<T> providerClass, String providerAuthority) {
diff --git a/test-runner/android/test/TestLocationProvider.java b/test-runner/android/test/TestLocationProvider.java
deleted file mode 100644
index dc07585..0000000
--- a/test-runner/android/test/TestLocationProvider.java
+++ /dev/null
@@ -1,196 +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.
- */
-
-package android.test;
-
-
-import android.location.Criteria;
-import android.location.ILocationManager;
-import android.location.ILocationProvider;
-import android.location.Location;
-import android.location.LocationProvider;
-import android.net.NetworkInfo;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.util.Log;
-
-/**
- * @hide - This is part of a framework that is under development and should not be used for
- * active development.
- */
-public class TestLocationProvider extends ILocationProvider.Stub {
-
-    public static final String PROVIDER_NAME = "test";
-    public static final double LAT = 0;
-    public static final double LON = 1;
-    public static final double ALTITUDE = 10000;
-    public static final float SPEED = 10;
-    public static final float BEARING = 1;
-    public static final int STATUS = LocationProvider.AVAILABLE;
-    private static final long LOCATION_INTERVAL = 1000;
-
-    private static final String TAG = "TestLocationProvider";
-
-    private final ILocationManager mLocationManager;
-    private Location mLocation;
-    private boolean mEnabled;
-    private TestLocationProviderThread mThread;
-
-    private class TestLocationProviderThread extends Thread {
-
-        private boolean mDone = false;
-
-        public TestLocationProviderThread() {
-            super("TestLocationProviderThread");
-        }
-
-        public void run() {            
-            // thread exits after disable() is called
-            synchronized (this) {
-                while (!mDone) {
-                    try {
-                        wait(LOCATION_INTERVAL);
-                    } catch (InterruptedException e) {
-                    }
-                    
-                    if (!mDone) {
-                        TestLocationProvider.this.updateLocation();
-                    }
-                }
-            }
-        }
-        
-        synchronized void setDone() {
-            mDone = true;
-            notify();
-        }
-    }
-
-    public TestLocationProvider(ILocationManager locationManager) {
-        mLocationManager = locationManager;
-        mLocation = new Location(PROVIDER_NAME);
-    }
-
-    public int getAccuracy() {
-        return Criteria.ACCURACY_COARSE;
-    }
-
-    public int getPowerRequirement() {
-        return Criteria.NO_REQUIREMENT;
-    }
-
-    public boolean hasMonetaryCost() {
-        return false;
-    }
-
-    public boolean requiresCell() {
-        return false;
-    }
-
-    public boolean requiresNetwork() {
-        return false;
-    }
-
-    public boolean requiresSatellite() {
-        return false;
-    }
-
-    public boolean supportsAltitude() {
-        return true;
-    }
-
-    public boolean supportsBearing() {
-        return true;
-    }
-
-    public boolean supportsSpeed() {
-        return true;
-    }
-
-    public synchronized void disable() {
-        mEnabled = false;
-        if (mThread != null) {
-            mThread.setDone();
-            try {
-                mThread.join();
-            } catch (InterruptedException e) {
-            }
-            mThread = null;
-        }
-    }
-
-    public synchronized void enable() {
-       mEnabled = true;
-        mThread = new TestLocationProviderThread();
-        mThread.start();
-    }
-
-    public boolean isEnabled() {
-        return mEnabled;
-    }
-
-    public int getStatus(Bundle extras) {
-        return STATUS;
-    }
-
-    public long getStatusUpdateTime() {
-        return 0;
-    }
-
-    public void enableLocationTracking(boolean enable) {
-    }
-
-    public void setMinTime(long minTime) {
-    }
-
-    public void updateNetworkState(int state, NetworkInfo info) {
-    }
-
-    public void updateLocation(Location location) {
-    }
-
-    public boolean sendExtraCommand(String command, Bundle extras) {
-        return false;
-    }
-
-    public void addListener(int uid) {
-    }
-
-    public void removeListener(int uid) {
-    }
-
-    private void updateLocation() {
-        long time = SystemClock.uptimeMillis();
-        long multiplier = (time/5000)%500000;
-        mLocation.setLatitude(LAT*multiplier);
-        mLocation.setLongitude(LON*multiplier);
-        mLocation.setAltitude(ALTITUDE);
-        mLocation.setSpeed(SPEED);
-        mLocation.setBearing(BEARING*multiplier);
-
-        Bundle extras = new Bundle();
-        extras.putInt("extraTest", 24);
-        mLocation.setExtras(extras);
-        mLocation.setTime(time);
-        try {
-            mLocationManager.reportLocation(mLocation);
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException calling updateLocation");
-        }
-    }
-
-}
diff --git a/test-runner/android/test/mock/MockPackageManager.java b/test-runner/android/test/mock/MockPackageManager.java
index cbe0253..f1ba44a 100644
--- a/test-runner/android/test/mock/MockPackageManager.java
+++ b/test-runner/android/test/mock/MockPackageManager.java
@@ -30,6 +30,7 @@
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
 import android.content.pm.ProviderInfo;
@@ -58,6 +59,16 @@
     }
 
     @Override
+    public String[] currentToCanonicalPackageNames(String[] names) {
+        throw new UnsupportedOperationException();
+    }
+    
+    @Override
+    public String[] canonicalToCurrentPackageNames(String[] names) {
+        throw new UnsupportedOperationException();
+    }
+    
+    @Override
     public Intent getLaunchIntentForPackage(String packageName) {
         throw new UnsupportedOperationException();
     }
@@ -438,12 +449,4 @@
     public boolean isSafeMode() {
         throw new UnsupportedOperationException();
     }
-
-    /**
-     * @hide
-     */
-    @Override
-    public int recommendAppInstallLocation(ApplicationInfo appInfo, Uri packageURI) {
-        throw new UnsupportedOperationException();
-    }
 }
diff --git a/tests/AndroidTests/res/raw/install_loc_auto b/tests/AndroidTests/res/raw/install_loc_auto
new file mode 100644
index 0000000..60dda18
--- /dev/null
+++ b/tests/AndroidTests/res/raw/install_loc_auto
Binary files differ
diff --git a/tests/AndroidTests/res/raw/install_loc_internal b/tests/AndroidTests/res/raw/install_loc_internal
new file mode 100644
index 0000000..1bc33ca
--- /dev/null
+++ b/tests/AndroidTests/res/raw/install_loc_internal
Binary files differ
diff --git a/tests/AndroidTests/res/raw/install_loc_sdcard b/tests/AndroidTests/res/raw/install_loc_sdcard
new file mode 100644
index 0000000..6604e35
--- /dev/null
+++ b/tests/AndroidTests/res/raw/install_loc_sdcard
Binary files differ
diff --git a/tests/AndroidTests/res/raw/install_loc_unspecified b/tests/AndroidTests/res/raw/install_loc_unspecified
new file mode 100644
index 0000000..88bbace
--- /dev/null
+++ b/tests/AndroidTests/res/raw/install_loc_unspecified
Binary files differ
diff --git a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
index 3a4d38c..8f4d0a1 100755
--- a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
@@ -37,6 +37,7 @@
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageInstallObserver;
 import android.content.pm.IPackageDeleteObserver;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
 import android.content.pm.PackageStats;
@@ -59,6 +60,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.StatFs;
+import android.provider.Settings;
 
 public class PackageManagerTests extends AndroidTestCase {
     private static final boolean localLOGV = true;
@@ -190,6 +192,27 @@
         }
     }
 
+    public boolean invokeInstallPackageFail(Uri packageURI, int flags,
+            final String pkgName, int result) throws Exception {
+        PackageInstallObserver observer = new PackageInstallObserver();
+        try {
+            // Wait on observer
+            synchronized(observer) {
+                getPm().installPackage(packageURI, observer, flags, null);
+                long waitTime = 0;
+                while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
+                    observer.wait(WAIT_TIME_INCR);
+                    waitTime += WAIT_TIME_INCR;
+                }
+                if(!observer.isDone()) {
+                    throw new Exception("Timed out waiting for packageInstalled callback");
+                }
+                return (observer.returnCode == result);
+            }
+        } finally {
+        }
+    }
+
     Uri getInstallablePackage(int fileResId, File outFile) {
         Resources res = mContext.getResources();
         InputStream is = null;
@@ -236,7 +259,7 @@
             assertEquals(publicSrcPath, appInstallPath);
         } else {
             assertFalse((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
-            if ((flags & PackageManager.INSTALL_ON_SDCARD) != 0) {
+            if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
                 assertTrue((info.flags & ApplicationInfo.FLAG_ON_SDCARD) != 0);
                 // Hardcoded for now
                 assertTrue(srcPath.startsWith("/asec"));
@@ -251,6 +274,13 @@
             failStr("failed with exception : " + e);
         }
     }
+    private void assertNotInstalled(String pkgName) {
+        try {
+            ApplicationInfo info = getPm().getApplicationInfo(pkgName, 0);
+            fail(pkgName + " shouldnt be installed");
+        } catch (NameNotFoundException e) {
+        }
+    }
 
     class InstallParams {
         String outFileName;
@@ -263,30 +293,42 @@
         }
     }
 
+    private InstallParams sampleInstallFromRawResource(int flags, boolean cleanUp) {
+        return installFromRawResource("install.apk", R.raw.install, flags, cleanUp,
+                false, -1);
+    }
     /*
      * Utility function that reads a apk bundled as a raw resource
      * copies it into own data directory and invokes
      * PackageManager api to install it.
      */
-    public InstallParams installFromRawResource(int flags, boolean cleanUp) {
-        String outFileName = "install.apk";
+    private InstallParams installFromRawResource(String outFileName,
+            int rawResId, int flags, boolean cleanUp, boolean fail, int result) {
         File filesDir = mContext.getFilesDir();
         File outFile = new File(filesDir, outFileName);
-        Uri packageURI = getInstallablePackage(R.raw.install, outFile);
+        Uri packageURI = getInstallablePackage(rawResId, outFile);
         PackageParser.Package pkg = parsePackage(packageURI);
         assertNotNull(pkg);
-        InstallReceiver receiver = new InstallReceiver(pkg.packageName);
         InstallParams ip = null;
         try {
             try {
-                assertTrue(invokeInstallPackage(packageURI, flags,
-                        pkg.packageName, receiver));
+                if (fail) {
+                    // Make sure it doesn't exist
+                    getPm().deletePackage(pkg.packageName, null, 0);
+                    assertTrue(invokeInstallPackageFail(packageURI, flags,
+                            pkg.packageName, result));
+                    assertNotInstalled(pkg.packageName);
+                } else {
+                    InstallReceiver receiver = new InstallReceiver(pkg.packageName);
+                    assertTrue(invokeInstallPackage(packageURI, flags,
+                            pkg.packageName, receiver));
+                    // Verify installed information
+                    assertInstall(pkg.packageName, flags);
+                    ip = new InstallParams(pkg, outFileName, packageURI);
+                }
             } catch (Exception e) {
                 failStr("Failed with exception : " + e);
             }
-            // Verify installed information
-            assertInstall(pkg.packageName, flags);
-            ip = new InstallParams(pkg, outFileName, packageURI);
             return ip;
         } finally {
             if (cleanUp) {
@@ -297,17 +339,17 @@
 
     @MediumTest
     public void testInstallNormalInternal() {
-        installFromRawResource(0, true);
+        sampleInstallFromRawResource(0, true);
     }
 
     @MediumTest
     public void testInstallFwdLockedInternal() {
-        installFromRawResource(PackageManager.INSTALL_FORWARD_LOCK, true);
+        sampleInstallFromRawResource(PackageManager.INSTALL_FORWARD_LOCK, true);
     }
 
     @MediumTest
     public void testInstallSdcard() {
-        installFromRawResource(PackageManager.INSTALL_ON_SDCARD, true);
+        sampleInstallFromRawResource(PackageManager.INSTALL_EXTERNAL, true);
     }
 
     /* ------------------------- Test replacing packages --------------*/
@@ -371,7 +413,7 @@
      * again.
      */
     public void replaceFromRawResource(int flags) {
-        InstallParams ip = installFromRawResource(flags, false);
+        InstallParams ip = sampleInstallFromRawResource(flags, false);
         boolean replace = ((flags & PackageManager.INSTALL_REPLACE_EXISTING) != 0);
         GenericReceiver receiver;
         if (replace) {
@@ -407,7 +449,7 @@
 
     @MediumTest
     public void testReplaceFailSdcard() {
-        replaceFromRawResource(PackageManager.INSTALL_ON_SDCARD);
+        replaceFromRawResource(PackageManager.INSTALL_EXTERNAL);
     }
 
     @MediumTest
@@ -424,7 +466,7 @@
     @MediumTest
     public void testReplaceSdcard() {
         replaceFromRawResource(PackageManager.INSTALL_REPLACE_EXISTING |
-                PackageManager.INSTALL_ON_SDCARD);
+                PackageManager.INSTALL_EXTERNAL);
     }
 
     /* -------------- Delete tests ---*/
@@ -506,7 +548,7 @@
     }
 
     public void deleteFromRawResource(int iFlags, int dFlags) {
-        InstallParams ip = installFromRawResource(iFlags, false);
+        InstallParams ip = sampleInstallFromRawResource(iFlags, false);
         boolean retainData = ((dFlags & PackageManager.DONT_DELETE_DATA) != 0);
         GenericReceiver receiver = new DeleteReceiver(ip.pkg.packageName);
         DeleteObserver observer = new DeleteObserver();
@@ -548,7 +590,7 @@
 
     @MediumTest
     public void testDeleteSdcard() {
-        deleteFromRawResource(PackageManager.INSTALL_ON_SDCARD, 0);
+        deleteFromRawResource(PackageManager.INSTALL_EXTERNAL, 0);
     }
 
     @MediumTest
@@ -563,7 +605,7 @@
 
     @MediumTest
     public void testDeleteSdcardRetainData() {
-        deleteFromRawResource(PackageManager.INSTALL_ON_SDCARD, PackageManager.DONT_DELETE_DATA);
+        deleteFromRawResource(PackageManager.INSTALL_EXTERNAL, PackageManager.DONT_DELETE_DATA);
     }
 
     /* sdcard mount/unmount tests ******/
@@ -694,7 +736,7 @@
 
     private boolean mountFromRawResource() {
         // Install pkg on sdcard
-        InstallParams ip = installFromRawResource(PackageManager.INSTALL_ON_SDCARD |
+        InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_EXTERNAL |
                 PackageManager.INSTALL_REPLACE_EXISTING, false);
         if (localLOGV) Log.i(TAG, "Installed pkg on sdcard");
         boolean origState = getMediaState();
@@ -761,6 +803,33 @@
             outFile.delete();
         }
     }
+
+    public void testManifestInstallLocationInternal() {
+        installFromRawResource("install.apk", R.raw.install_loc_internal,
+                0, true, false, -1);
+    }
+
+    public void testManifestInstallLocationSdcard() {
+        installFromRawResource("install.apk", R.raw.install_loc_sdcard,
+                PackageManager.INSTALL_EXTERNAL, true, false, -1);
+    }
+
+    public void testManifestInstallLocationAuto() {
+        installFromRawResource("install.apk", R.raw.install_loc_auto,
+                0, true, false, -1);
+    }
+
+    public void testManifestInstallLocationUnspecified() {
+        installFromRawResource("install.apk", R.raw.install_loc_unspecified,
+                0, true, false, -1);
+    }
+
+    public void testManifestInstallLocationFwdLockedSdcard() {
+        installFromRawResource("install.apk", R.raw.install_loc_sdcard,
+                PackageManager.INSTALL_FORWARD_LOCK |
+                PackageManager.INSTALL_EXTERNAL, true, true,
+                PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION);
+    }
     /*
      * TODO's
      * check version numbers for upgrades
diff --git a/tests/backup/AndroidManifest.xml b/tests/backup/AndroidManifest.xml
index d992627..3778742 100644
--- a/tests/backup/AndroidManifest.xml
+++ b/tests/backup/AndroidManifest.xml
@@ -1,6 +1,5 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.backuptest">
-    <uses-permission android:name="android.permission.BACKUP_DATA" />
     <application android:backupAgent="BackupTestAgent">
         <activity android:name="BackupTestActivity" android:label="_BackupTest">
             <intent-filter>
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index c346b90..663a33a 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -163,6 +163,20 @@
         return 0;
     }
 
+    // ui mode type
+    if (getUiModeTypeName(part.string(), &config)) {
+        *axis = AXIS_UIMODETYPE;
+        *value = (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE);
+        return 0;
+    }
+
+    // ui mode night
+    if (getUiModeNightName(part.string(), &config)) {
+        *axis = AXIS_UIMODENIGHT;
+        *value = (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT);
+        return 0;
+    }
+
     // density
     if (getDensityName(part.string(), &config)) {
         *axis = AXIS_DENSITY;
@@ -229,6 +243,7 @@
 
     String8 mcc, mnc, loc, layoutsize, layoutlong, orient, den;
     String8 touch, key, keysHidden, nav, navHidden, size, vers;
+    String8 uiModeType, uiModeNight;
 
     const char *p = dir;
     const char *q;
@@ -352,6 +367,32 @@
         //printf("not orientation: %s\n", part.string());
     }
 
+    // ui mode type
+    if (getUiModeTypeName(part.string())) {
+        uiModeType = part;
+
+        index++;
+        if (index == N) {
+            goto success;
+        }
+        part = parts[index];
+    } else {
+        //printf("not ui mode type: %s\n", part.string());
+    }
+
+    // ui mode night
+    if (getUiModeNightName(part.string())) {
+        uiModeNight = part;
+
+        index++;
+        if (index == N) {
+            goto success;
+        }
+        part = parts[index];
+    } else {
+        //printf("not ui mode night: %s\n", part.string());
+    }
+
     // density
     if (getDensityName(part.string())) {
         den = part;
@@ -463,6 +504,8 @@
     this->screenLayoutSize = layoutsize;
     this->screenLayoutLong = layoutlong;
     this->orientation = orient;
+    this->uiModeType = uiModeType;
+    this->uiModeNight = uiModeNight;
     this->density = den;
     this->touchscreen = touch;
     this->keysHidden = keysHidden;
@@ -493,6 +536,10 @@
     s += ",";
     s += this->orientation;
     s += ",";
+    s += uiModeType;
+    s += ",";
+    s += uiModeNight;
+    s += ",";
     s += density;
     s += ",";
     s += touchscreen;
@@ -539,6 +586,14 @@
         s += "-";
         s += orientation;
     }
+    if (this->uiModeType != "") {
+        s += "-";
+        s += uiModeType;
+    }
+    if (this->uiModeNight != "") {
+        s += "-";
+        s += uiModeNight;
+    }
     if (this->density != "") {
         s += "-";
         s += density;
@@ -759,6 +814,47 @@
     return false;
 }
 
+bool AaptGroupEntry::getUiModeTypeName(const char* name,
+                                       ResTable_config* out)
+{
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->uiMode =
+                (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
+                | ResTable_config::UI_MODE_TYPE_NORMAL;
+        return true;
+    } else if (strcmp(name, "car") == 0) {
+      if (out) out->uiMode =
+              (out->uiMode&~ResTable_config::MASK_UI_MODE_TYPE)
+              | ResTable_config::UI_MODE_TYPE_CAR;
+        return true;
+    }
+
+    return false;
+}
+
+bool AaptGroupEntry::getUiModeNightName(const char* name,
+                                          ResTable_config* out)
+{
+    if (strcmp(name, kWildcardName) == 0) {
+        if (out) out->uiMode =
+                (out->uiMode&~ResTable_config::MASK_UI_MODE_NIGHT)
+                | ResTable_config::UI_MODE_NIGHT_ANY;
+        return true;
+    } else if (strcmp(name, "night") == 0) {
+        if (out) out->uiMode =
+                (out->uiMode&~ResTable_config::MASK_UI_MODE_NIGHT)
+                | ResTable_config::UI_MODE_NIGHT_YES;
+        return true;
+    } else if (strcmp(name, "notnight") == 0) {
+      if (out) out->uiMode =
+              (out->uiMode&~ResTable_config::MASK_UI_MODE_NIGHT)
+              | ResTable_config::UI_MODE_NIGHT_NO;
+        return true;
+    }
+
+    return false;
+}
+
 bool AaptGroupEntry::getDensityName(const char* name,
                                     ResTable_config* out)
 {
@@ -1004,6 +1100,8 @@
     if (v == 0) v = screenLayoutSize.compare(o.screenLayoutSize);
     if (v == 0) v = screenLayoutLong.compare(o.screenLayoutLong);
     if (v == 0) v = orientation.compare(o.orientation);
+    if (v == 0) v = uiModeType.compare(o.uiModeType);
+    if (v == 0) v = uiModeNight.compare(o.uiModeNight);
     if (v == 0) v = density.compare(o.density);
     if (v == 0) v = touchscreen.compare(o.touchscreen);
     if (v == 0) v = keysHidden.compare(o.keysHidden);
@@ -1025,6 +1123,8 @@
     getScreenLayoutSizeName(screenLayoutSize.string(), &params);
     getScreenLayoutLongName(screenLayoutLong.string(), &params);
     getOrientationName(orientation.string(), &params);
+    getUiModeTypeName(uiModeType.string(), &params);
+    getUiModeNightName(uiModeNight.string(), &params);
     getDensityName(density.string(), &params);
     getTouchscreenName(touchscreen.string(), &params);
     getKeysHiddenName(keysHidden.string(), &params);
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index 26500a3..9a848e4 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -33,6 +33,8 @@
     AXIS_SCREENLAYOUTSIZE,
     AXIS_SCREENLAYOUTLONG,
     AXIS_ORIENTATION,
+    AXIS_UIMODETYPE,
+    AXIS_UIMODENIGHT,
     AXIS_DENSITY,
     AXIS_TOUCHSCREEN,
     AXIS_KEYSHIDDEN,
@@ -61,6 +63,8 @@
     String8 screenLayoutSize;
     String8 screenLayoutLong;
     String8 orientation;
+    String8 uiModeType;
+    String8 uiModeNight;
     String8 density;
     String8 touchscreen;
     String8 keysHidden;
@@ -80,6 +84,8 @@
     static bool getScreenLayoutSizeName(const char* name, ResTable_config* out = NULL);
     static bool getScreenLayoutLongName(const char* name, ResTable_config* out = NULL);
     static bool getOrientationName(const char* name, ResTable_config* out = NULL);
+    static bool getUiModeTypeName(const char* name, ResTable_config* out = NULL);
+    static bool getUiModeNightName(const char* name, ResTable_config* out = NULL);
     static bool getDensityName(const char* name, ResTable_config* out = NULL);
     static bool getTouchscreenName(const char* name, ResTable_config* out = NULL);
     static bool getKeysHiddenName(const char* name, ResTable_config* out = NULL);
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 5d345e6..ee07415 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -741,6 +741,15 @@
                                     error.string());
                             goto bail;
                         }
+                    } else if (tag == "original-package") {
+                        String8 name = getAttribute(tree, NAME_ATTR, &error);
+                        if (name != "" && error == "") {
+                            printf("original-package:'%s'\n", name.string());
+                        } else {
+                            fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n",
+                                    error.string());
+                                goto bail;
+                        }
                     }
                 } else if (depth == 3 && withinApplication) {
                     withinActivity = false;
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 0d2ea60..88c5441 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -101,13 +101,13 @@
             String8 leaf(group->getLeaf());
             mLeafName = String8(leaf);
             mParams = file->getGroupEntry().toParams();
-            NOISY(printf("Dir %s: mcc=%d mnc=%d lang=%c%c cnt=%c%c orient=%d density=%d touch=%d key=%d inp=%d nav=%d\n",
+            NOISY(printf("Dir %s: mcc=%d mnc=%d lang=%c%c cnt=%c%c orient=%d ui=%d density=%d touch=%d key=%d inp=%d nav=%d\n",
                    group->getPath().string(), mParams.mcc, mParams.mnc,
                    mParams.language[0] ? mParams.language[0] : '-',
                    mParams.language[1] ? mParams.language[1] : '-',
                    mParams.country[0] ? mParams.country[0] : '-',
                    mParams.country[1] ? mParams.country[1] : '-',
-                   mParams.orientation,
+                   mParams.orientation, mParams.uiMode,
                    mParams.density, mParams.touchscreen, mParams.keyboard,
                    mParams.inputFlags, mParams.navigation));
             mPath = "res";
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index b682702..a389bfb 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -2472,6 +2472,12 @@
     if (!match(AXIS_ORIENTATION, config.orientation)) {
         return false;
     }
+    if (!match(AXIS_UIMODETYPE, (config.uiMode&ResTable_config::MASK_UI_MODE_TYPE))) {
+        return false;
+    }
+    if (!match(AXIS_UIMODENIGHT, (config.uiMode&ResTable_config::MASK_UI_MODE_NIGHT))) {
+        return false;
+    }
     if (!match(AXIS_DENSITY, config.density)) {
         return false;
     }
@@ -2674,7 +2680,7 @@
                 ConfigDescription config = t->getUniqueConfigs().itemAt(ci);
 
                 NOISY(printf("Writing config %d config: imsi:%d/%d lang:%c%c cnt:%c%c "
-                     "orien:%d touch:%d density:%d key:%d inp:%d nav:%d w:%d h:%d\n",
+                     "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d w:%d h:%d\n",
                       ti+1,
                       config.mcc, config.mnc,
                       config.language[0] ? config.language[0] : '-',
@@ -2682,6 +2688,7 @@
                       config.country[0] ? config.country[0] : '-',
                       config.country[1] ? config.country[1] : '-',
                       config.orientation,
+                      config.uiMode,
                       config.touchscreen,
                       config.density,
                       config.keyboard,
@@ -2711,7 +2718,7 @@
                 tHeader->entriesStart = htodl(typeSize);
                 tHeader->config = config;
                 NOISY(printf("Writing type %d config: imsi:%d/%d lang:%c%c cnt:%c%c "
-                     "orien:%d touch:%d density:%d key:%d inp:%d nav:%d w:%d h:%d\n",
+                     "orien:%d ui:%d touch:%d density:%d key:%d inp:%d nav:%d w:%d h:%d\n",
                       ti+1,
                       tHeader->config.mcc, tHeader->config.mnc,
                       tHeader->config.language[0] ? tHeader->config.language[0] : '-',
@@ -2719,6 +2726,7 @@
                       tHeader->config.country[0] ? tHeader->config.country[0] : '-',
                       tHeader->config.country[1] ? tHeader->config.country[1] : '-',
                       tHeader->config.orientation,
+                      tHeader->config.uiMode,
                       tHeader->config.touchscreen,
                       tHeader->config.density,
                       tHeader->config.keyboard,
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java
index 6c1b5b3..71803fc 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java
@@ -17,12 +17,9 @@
 package com.android.layoutlib.bridge;
 
 import android.content.res.AssetManager;
-import android.content.res.Configuration;
-
-import java.util.Locale;
 
 public class BridgeAssetManager extends AssetManager {
-    
+
     /**
      * This initializes the static field {@link AssetManager#mSystem} which is used
      * by methods who get a global asset manager using {@link AssetManager#getSystem()}.
@@ -40,7 +37,7 @@
         }
         return AssetManager.sSystem;
     }
-    
+
     /**
      * Clears the static {@link AssetManager#sSystem} to make sure we don't leave objects
      * around that would prevent us from unloading the library.
@@ -48,28 +45,7 @@
     /*package*/ static void clearSystem() {
         AssetManager.sSystem = null;
     }
-    
+
     private BridgeAssetManager() {
     }
-    
-    /**
-     * Change the configuration used when retrieving resources.  Not for use by applications.
-     */
-    @Override
-    public void setConfiguration(int mcc, int mnc, String locale,
-            int orientation, int touchscreen, int density, int keyboard,
-            int keyboardHidden, int navigation, int screenWidth, int screenHeight,
-            int screenLayout, int version)  {
-        
-        Configuration c = new Configuration();
-        c.mcc = mcc;
-        c.mnc = mnc;
-        c.locale = new Locale(locale);
-        c.touchscreen = touchscreen;
-        c.keyboard = keyboard;
-        c.keyboardHidden = keyboardHidden;
-        c.navigation = navigation;
-        c.orientation = orientation;
-        c.screenLayout = screenLayout;
-    }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
index 57b5d4e..73a3986 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
@@ -66,14 +66,14 @@
  */
 public final class BridgeContext extends Context {
 
-    private Resources mResources;
-    private Theme mTheme;
-    private HashMap<View, Object> mViewKeyMap = new HashMap<View, Object>();
-    private IStyleResourceValue mThemeValues;
+    private final Resources mResources;
+    private final Theme mTheme;
+    private final HashMap<View, Object> mViewKeyMap = new HashMap<View, Object>();
+    private final IStyleResourceValue mThemeValues;
     private final Object mProjectKey;
-    private Map<String, Map<String, IResourceValue>> mProjectResources;
-    private Map<String, Map<String, IResourceValue>> mFrameworkResources;
-    private Map<IStyleResourceValue, IStyleResourceValue> mStyleInheritanceMap;
+    private final Map<String, Map<String, IResourceValue>> mProjectResources;
+    private final Map<String, Map<String, IResourceValue>> mFrameworkResources;
+    private final Map<IStyleResourceValue, IStyleResourceValue> mStyleInheritanceMap;
 
     // maps for dynamically generated id representing style objects (IStyleResourceValue)
     private Map<Integer, IStyleResourceValue> mDynamicIdToStyleMap;
@@ -927,7 +927,6 @@
         return null;
     }
 
-    @Override
     public File getExternalCacheDir() {
         // TODO Auto-generated method stub
         return null;
@@ -965,7 +964,6 @@
         return null;
     }
 
-    @Override
     public File getExternalFilesDir(String type) {
         // TODO Auto-generated method stub
         return null;
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index cb615d2..afaed24 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -835,7 +835,7 @@
                     WifiNative.closeSupplicantConnection();
                 }
                 if (died) {
-                    resetInterface(false);
+                    resetConnections(true);
                 }
                 // When supplicant dies, kill the DHCP thread
                 if (mDhcpTarget != null) {
@@ -1074,6 +1074,13 @@
                         DetailedState saveState = getNetworkInfo().getDetailedState();
                         handleDisconnectedState(DetailedState.DISCONNECTED);
                         setDetailedStateInternal(saveState);
+                    } else {
+                        /**
+                         *  stop DHCP to ensure there is a new IP address
+                         *  even if the supplicant transitions without disconnect
+                         *  COMPLETED -> ASSOCIATED -> COMPLETED
+                         */
+                        resetConnections(false);
                     }
                     configureInterface();
                     mLastBssid = result.BSSID;
@@ -1279,12 +1286,11 @@
      * {@code DISCONNECTED} or {@code FAILED}.
      */
     private void handleDisconnectedState(DetailedState newState) {
-        if (LOCAL_LOGD) Log.d(TAG, "Deconfiguring interface and stopping DHCP");
         if (mDisconnectPending) {
             cancelDisconnect();
         }
         mDisconnectExpected = false;
-        resetInterface(true);
+        resetConnections(true);
         setDetailedState(newState);
         sendNetworkStateChangeBroadcast(mLastBssid);
         mWifiInfo.setBSSID(null);
@@ -1294,10 +1300,11 @@
     }
 
     /**
-     * Resets the Wi-Fi interface by clearing any state, resetting any sockets
+     * Resets the Wi-Fi Connections by clearing any state, resetting any sockets
      * using the interface, stopping DHCP, and disabling the interface.
      */
-    public void resetInterface(boolean reenable) {
+    public void resetConnections(boolean disableInterface) {
+        if (LOCAL_LOGD) Log.d(TAG, "Reset connections and stopping DHCP");
         mHaveIpAddress = false;
         mObtainingIpAddress = false;
         mWifiInfo.setIpAddress(0);
@@ -1317,9 +1324,14 @@
             Log.e(TAG, "Could not stop DHCP");
         }
 
-        NetworkUtils.disableInterface(mInterfaceName);
-        // we no longer net to start the interface (driver does this for us)
-        // and it led to problems - removed.
+        /**
+         * Interface is re-enabled in the supplicant
+         * when moving out of ASSOCIATING state
+         */
+        if(disableInterface) {
+            if (LOCAL_LOGD) Log.d(TAG, "Disabling interface");
+            NetworkUtils.disableInterface(mInterfaceName);
+        }
     }
 
     /**
@@ -1538,7 +1550,7 @@
     public synchronized boolean restart() {
         if (mRunState == RUN_STATE_STOPPED) {
             mRunState = RUN_STATE_STARTING;
-            resetInterface(true);
+            resetConnections(true);
             return WifiNative.startDriverCommand();
         } else if (mRunState == RUN_STATE_STOPPING) {
             mRunState = RUN_STATE_STARTING;
@@ -1969,7 +1981,7 @@
                         oDns2 != mDhcpInfo.dns2));
 
             if (changed) {
-                resetInterface(true);
+                resetConnections(true);
                 configureInterface();
                 if (mUseStaticIp) {
                     mTarget.sendEmptyMessage(EVENT_CONFIGURATION_CHANGED);