Merge "Import revised translations."
diff --git a/api/current.txt b/api/current.txt
index 3a90ef7..86e8b1d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -179,9 +179,9 @@
   public static final class R.attr {
     ctor public R.attr();
     field public static final int absListViewStyle = 16842858; // 0x101006a
-    field public static final int accessibilityEventTypes = 16843643; // 0x101037b
-    field public static final int accessibilityFeedbackType = 16843645; // 0x101037d
-    field public static final int accessibilityFlags = 16843647; // 0x101037f
+    field public static final int accessibilityEventTypes = 16843645; // 0x101037d
+    field public static final int accessibilityFeedbackType = 16843647; // 0x101037f
+    field public static final int accessibilityFlags = 16843649; // 0x1010381
     field public static final int accountPreferences = 16843423; // 0x101029f
     field public static final int accountType = 16843407; // 0x101028f
     field public static final int action = 16842797; // 0x101002d
@@ -201,7 +201,7 @@
     field public static final int actionModeCopyDrawable = 16843538; // 0x1010312
     field public static final int actionModeCutDrawable = 16843537; // 0x1010311
     field public static final int actionModePasteDrawable = 16843539; // 0x1010313
-    field public static final int actionModeSelectAllDrawable = 16843641; // 0x1010379
+    field public static final int actionModeSelectAllDrawable = 16843643; // 0x101037b
     field public static final int actionOverflowButtonStyle = 16843510; // 0x10102f6
     field public static final int actionViewClass = 16843516; // 0x10102fc
     field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
@@ -273,7 +273,7 @@
     field public static final int cacheColorHint = 16843009; // 0x1010101
     field public static final int calendarViewShown = 16843596; // 0x101034c
     field public static final int calendarViewStyle = 16843613; // 0x101035d
-    field public static final int canRetrieveWindowContent = 16843648; // 0x1010380
+    field public static final int canRetrieveWindowContent = 16843650; // 0x1010382
     field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
     field public static final deprecated int capitalize = 16843113; // 0x1010169
     field public static final int centerBright = 16842956; // 0x10100cc
@@ -306,10 +306,11 @@
     field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab
     field public static final int colorForeground = 16842800; // 0x1010030
     field public static final int colorForegroundInverse = 16843270; // 0x1010206
-    field public static final int columnCount = 16843633; // 0x1010371
+    field public static final int columnCount = 16843635; // 0x1010373
     field public static final int columnDelay = 16843215; // 0x10101cf
-    field public static final int columnOrderPreserved = 16843634; // 0x1010372
+    field public static final int columnOrderPreserved = 16843636; // 0x1010374
     field public static final int columnWidth = 16843031; // 0x1010117
+    field public static final int compatibleWidthLimitDp = 16843621; // 0x1010365
     field public static final int completionHint = 16843122; // 0x1010172
     field public static final int completionHintView = 16843123; // 0x1010173
     field public static final int completionThreshold = 16843124; // 0x1010174
@@ -452,7 +453,7 @@
     field public static final int fromXScale = 16843202; // 0x10101c2
     field public static final int fromYDelta = 16843208; // 0x10101c8
     field public static final int fromYScale = 16843204; // 0x10101c4
-    field public static final int fullBackupAgent = 16843629; // 0x101036d
+    field public static final int fullBackupAgent = 16843631; // 0x101036f
     field public static final int fullBright = 16842954; // 0x10100ca
     field public static final int fullDark = 16842950; // 0x10100c6
     field public static final int functionalTest = 16842787; // 0x1010023
@@ -483,7 +484,7 @@
     field public static final int hint = 16843088; // 0x1010150
     field public static final int homeAsUpIndicator = 16843531; // 0x101030b
     field public static final int homeLayout = 16843549; // 0x101031d
-    field public static final int horizontalDirection = 16843628; // 0x101036c
+    field public static final int horizontalDirection = 16843630; // 0x101036e
     field public static final int horizontalDivider = 16843053; // 0x101012d
     field public static final int horizontalGap = 16843327; // 0x101023f
     field public static final int horizontalScrollViewStyle = 16843603; // 0x1010353
@@ -531,7 +532,7 @@
     field public static final int installLocation = 16843447; // 0x10102b7
     field public static final int interpolator = 16843073; // 0x1010141
     field public static final int isAlwaysSyncable = 16843571; // 0x1010333
-    field public static final int isAuxiliary = 16843642; // 0x101037a
+    field public static final int isAuxiliary = 16843644; // 0x101037c
     field public static final int isDefault = 16843297; // 0x1010221
     field public static final int isIndicator = 16843079; // 0x1010147
     field public static final int isModifier = 16843334; // 0x1010246
@@ -583,8 +584,8 @@
     field public static final int layout_centerInParent = 16843151; // 0x101018f
     field public static final int layout_centerVertical = 16843153; // 0x1010191
     field public static final int layout_column = 16843084; // 0x101014c
-    field public static final int layout_columnSpan = 16843639; // 0x1010377
-    field public static final int layout_columnWeight = 16843640; // 0x1010378
+    field public static final int layout_columnSpan = 16843641; // 0x1010379
+    field public static final int layout_columnWeight = 16843642; // 0x101037a
     field public static final int layout_gravity = 16842931; // 0x10100b3
     field public static final int layout_height = 16842997; // 0x10100f5
     field public static final int layout_margin = 16842998; // 0x10100f6
@@ -592,9 +593,9 @@
     field public static final int layout_marginLeft = 16842999; // 0x10100f7
     field public static final int layout_marginRight = 16843001; // 0x10100f9
     field public static final int layout_marginTop = 16843000; // 0x10100f8
-    field public static final int layout_row = 16843636; // 0x1010374
-    field public static final int layout_rowSpan = 16843637; // 0x1010375
-    field public static final int layout_rowWeight = 16843638; // 0x1010376
+    field public static final int layout_row = 16843638; // 0x1010376
+    field public static final int layout_rowSpan = 16843639; // 0x1010377
+    field public static final int layout_rowWeight = 16843640; // 0x1010378
     field public static final int layout_scale = 16843155; // 0x1010193
     field public static final int layout_span = 16843085; // 0x101014d
     field public static final int layout_toLeftOf = 16843138; // 0x1010182
@@ -660,7 +661,7 @@
     field public static final int nextFocusUp = 16842979; // 0x10100e3
     field public static final int noHistory = 16843309; // 0x101022d
     field public static final int normalScreens = 16843397; // 0x1010285
-    field public static final int notificationTimeout = 16843646; // 0x101037e
+    field public static final int notificationTimeout = 16843648; // 0x1010380
     field public static final int numColumns = 16843032; // 0x1010118
     field public static final int numStars = 16843076; // 0x1010144
     field public static final deprecated int numeric = 16843109; // 0x1010165
@@ -677,7 +678,7 @@
     field public static final int overScrollFooter = 16843459; // 0x10102c3
     field public static final int overScrollHeader = 16843458; // 0x10102c2
     field public static final int overScrollMode = 16843457; // 0x10102c1
-    field public static final int packageNames = 16843644; // 0x101037c
+    field public static final int packageNames = 16843646; // 0x101037e
     field public static final int padding = 16842965; // 0x10100d5
     field public static final int paddingBottom = 16842969; // 0x10100d9
     field public static final int paddingLeft = 16842966; // 0x10100d6
@@ -755,6 +756,7 @@
     field public static final int reqNavigation = 16843306; // 0x101022a
     field public static final int reqTouchScreen = 16843303; // 0x1010227
     field public static final int required = 16843406; // 0x101028e
+    field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
     field public static final int resizeMode = 16843619; // 0x1010363
     field public static final int resizeable = 16843405; // 0x101028d
     field public static final int resource = 16842789; // 0x1010025
@@ -766,11 +768,11 @@
     field public static final int rotation = 16843558; // 0x1010326
     field public static final int rotationX = 16843559; // 0x1010327
     field public static final int rotationY = 16843560; // 0x1010328
-    field public static final int rowCount = 16843631; // 0x101036f
+    field public static final int rowCount = 16843633; // 0x1010371
     field public static final int rowDelay = 16843216; // 0x10101d0
     field public static final int rowEdgeFlags = 16843329; // 0x1010241
     field public static final int rowHeight = 16843058; // 0x1010132
-    field public static final int rowOrderPreserved = 16843632; // 0x1010370
+    field public static final int rowOrderPreserved = 16843634; // 0x1010372
     field public static final int saveEnabled = 16842983; // 0x10100e7
     field public static final int scaleGravity = 16843262; // 0x10101fe
     field public static final int scaleHeight = 16843261; // 0x10101fd
@@ -857,14 +859,14 @@
     field public static final int state_active = 16842914; // 0x10100a2
     field public static final int state_checkable = 16842911; // 0x101009f
     field public static final int state_checked = 16842912; // 0x10100a0
-    field public static final int state_drag_can_accept = 16843621; // 0x1010365
-    field public static final int state_drag_hovered = 16843622; // 0x1010366
+    field public static final int state_drag_can_accept = 16843623; // 0x1010367
+    field public static final int state_drag_hovered = 16843624; // 0x1010368
     field public static final int state_empty = 16842921; // 0x10100a9
     field public static final int state_enabled = 16842910; // 0x101009e
     field public static final int state_expanded = 16842920; // 0x10100a8
     field public static final int state_first = 16842916; // 0x10100a4
     field public static final int state_focused = 16842908; // 0x101009c
-    field public static final int state_hovered = 16843620; // 0x1010364
+    field public static final int state_hovered = 16843622; // 0x1010366
     field public static final int state_last = 16842918; // 0x10100a6
     field public static final int state_long_pressable = 16843324; // 0x101023c
     field public static final int state_middle = 16842917; // 0x10100a5
@@ -875,7 +877,7 @@
     field public static final int state_window_focused = 16842909; // 0x101009d
     field public static final int staticWallpaperPreview = 16843569; // 0x1010331
     field public static final int stepSize = 16843078; // 0x1010146
-    field public static final int stopWithTask = 16843623; // 0x1010367
+    field public static final int stopWithTask = 16843625; // 0x1010369
     field public static final int streamType = 16843273; // 0x1010209
     field public static final int stretchColumns = 16843081; // 0x1010149
     field public static final int stretchMode = 16843030; // 0x1010116
@@ -883,7 +885,7 @@
     field public static final int subtitleTextStyle = 16843513; // 0x10102f9
     field public static final int suggestActionMsg = 16843228; // 0x10101dc
     field public static final int suggestActionMsgColumn = 16843229; // 0x10101dd
-    field public static final int suggestionsEnabled = 16843630; // 0x101036e
+    field public static final int suggestionsEnabled = 16843632; // 0x1010370
     field public static final int summary = 16843241; // 0x10101e9
     field public static final int summaryColumn = 16843426; // 0x10102a2
     field public static final int summaryOff = 16843248; // 0x10101f0
@@ -951,9 +953,9 @@
     field public static final int textEditPasteWindowLayout = 16843540; // 0x1010314
     field public static final int textEditSideNoPasteWindowLayout = 16843615; // 0x101035f
     field public static final int textEditSidePasteWindowLayout = 16843614; // 0x101035e
-    field public static final int textEditSuggestionItemLayout = 16843627; // 0x101036b
-    field public static final int textEditSuggestionsBottomWindowLayout = 16843625; // 0x1010369
-    field public static final int textEditSuggestionsTopWindowLayout = 16843626; // 0x101036a
+    field public static final int textEditSuggestionItemLayout = 16843629; // 0x101036d
+    field public static final int textEditSuggestionsBottomWindowLayout = 16843627; // 0x101036b
+    field public static final int textEditSuggestionsTopWindowLayout = 16843628; // 0x101036c
     field public static final int textFilterEnabled = 16843007; // 0x10100ff
     field public static final int textIsSelectable = 16843542; // 0x1010316
     field public static final int textOff = 16843045; // 0x1010125
@@ -965,7 +967,7 @@
     field public static final int textSelectHandleWindowStyle = 16843464; // 0x10102c8
     field public static final int textSize = 16842901; // 0x1010095
     field public static final int textStyle = 16842903; // 0x1010097
-    field public static final int textSuggestionsWindowStyle = 16843624; // 0x1010368
+    field public static final int textSuggestionsWindowStyle = 16843626; // 0x101036a
     field public static final int textViewStyle = 16842884; // 0x1010084
     field public static final int theme = 16842752; // 0x1010000
     field public static final int thickness = 16843360; // 0x1010260
@@ -1001,7 +1003,7 @@
     field public static final int unfocusedMonthDateColor = 16843588; // 0x1010344
     field public static final int unselectedAlpha = 16843278; // 0x101020e
     field public static final int updatePeriodMillis = 16843344; // 0x1010250
-    field public static final int useDefaultMargins = 16843635; // 0x1010373
+    field public static final int useDefaultMargins = 16843637; // 0x1010375
     field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
     field public static final int useLevel = 16843167; // 0x101019f
     field public static final int userVisible = 16843409; // 0x1010291
@@ -5500,6 +5502,7 @@
     field public static final int FLAG_VM_SAFE_MODE = 16384; // 0x4000
     field public java.lang.String backupAgentName;
     field public java.lang.String className;
+    field public int compatibleWidthLimitDp;
     field public java.lang.String dataDir;
     field public int descriptionRes;
     field public boolean enabled;
@@ -5509,6 +5512,7 @@
     field public java.lang.String permission;
     field public java.lang.String processName;
     field public java.lang.String publicSourceDir;
+    field public int requiresSmallestWidthDp;
     field public java.lang.String[] sharedLibraryFiles;
     field public java.lang.String sourceDir;
     field public int targetSdkVersion;
@@ -11596,12 +11600,14 @@
     method public void writeToParcel(android.os.Parcel, int);
     enum_constant public static final android.net.wifi.SupplicantState ASSOCIATED;
     enum_constant public static final android.net.wifi.SupplicantState ASSOCIATING;
+    enum_constant public static final android.net.wifi.SupplicantState AUTHENTICATING;
     enum_constant public static final android.net.wifi.SupplicantState COMPLETED;
     enum_constant public static final android.net.wifi.SupplicantState DISCONNECTED;
     enum_constant public static final android.net.wifi.SupplicantState DORMANT;
     enum_constant public static final android.net.wifi.SupplicantState FOUR_WAY_HANDSHAKE;
     enum_constant public static final android.net.wifi.SupplicantState GROUP_HANDSHAKE;
     enum_constant public static final android.net.wifi.SupplicantState INACTIVE;
+    enum_constant public static final android.net.wifi.SupplicantState INTERFACE_DISABLED;
     enum_constant public static final android.net.wifi.SupplicantState INVALID;
     enum_constant public static final android.net.wifi.SupplicantState SCANNING;
     enum_constant public static final android.net.wifi.SupplicantState UNINITIALIZED;
@@ -19892,6 +19898,7 @@
     field public static final int DENSITY_HIGH = 240; // 0xf0
     field public static final int DENSITY_LOW = 120; // 0x78
     field public static final int DENSITY_MEDIUM = 160; // 0xa0
+    field public static final int DENSITY_TV = 213; // 0xd5
     field public static final int DENSITY_XHIGH = 320; // 0x140
     field public float density;
     field public int densityDpi;
@@ -23391,6 +23398,7 @@
     method public void onReceivedTouchIconUrl(android.webkit.WebView, java.lang.String, boolean);
     method public void onRequestFocus(android.webkit.WebView);
     method public void onShowCustomView(android.view.View, android.webkit.WebChromeClient.CustomViewCallback);
+    method public void onShowCustomView(android.view.View, int, android.webkit.WebChromeClient.CustomViewCallback);
   }
 
   public static abstract interface WebChromeClient.CustomViewCallback {
diff --git a/cmds/keystore/keystore.cpp b/cmds/keystore/keystore.cpp
index 31db9fd..b48be6ef 100644
--- a/cmds/keystore/keystore.cpp
+++ b/cmds/keystore/keystore.cpp
@@ -392,9 +392,7 @@
             return false;
         }
         while ((file = readdir(dir)) != NULL) {
-            if (isKeyFile(file->d_name)) {
-                unlink(file->d_name);
-            }
+            unlink(file->d_name);
         }
         closedir(dir);
         return true;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 955cef2..7e20c75 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1534,7 +1534,7 @@
         synchronized (this) {
             ContextImpl context = getSystemContext();
             context.init(new LoadedApk(this, "android", context, info,
-                    new CompatibilityInfo(info, 0, false)), null, this);
+                    new CompatibilityInfo(info, 0, 0, false)), null, this);
         }
     }
 
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 2a0ebcf..f3b1d94 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -16,16 +16,6 @@
 
 package android.content;
 
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.Set;
-
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -36,6 +26,15 @@
 
 import com.android.internal.util.XmlUtils;
 
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Set;
+
 /**
  * Structured description of Intent values to be matched.  An IntentFilter can
  * match against actions, categories, and data (either via its type, scheme,
@@ -754,7 +753,7 @@
     }
 
     /**
-     * Add a new Intent data oath to match against.  The filter must
+     * Add a new Intent data path to match against.  The filter must
      * include one or more schemes (via {@link #addDataScheme}) <em>and</em>
      * one or more authorities (via {@link #addDataAuthority}) for the
      * path to be considered.  If any paths are
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 4b38d48..ccd3567 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -330,6 +330,22 @@
     public int flags = 0;
     
     /**
+     * The required smallest screen width the application can run on.  If 0,
+     * nothing has been specified.  Comes from
+     * {@link android.R.styleable#AndroidManifestSupportsScreens_requiresSmallestWidthDp
+     * android:requiresSmallestWidthDp} attribute of the &lt;supports-screens&gt; tag.
+     */
+    public int requiresSmallestWidthDp = 0;
+
+    /**
+     * The maximum smallest screen width the application is designed for.  If 0,
+     * nothing has been specified.  Comes from
+     * {@link android.R.styleable#AndroidManifestSupportsScreens_compatibleWidthLimitDp
+     * android:compatibleWidthLimitDp} attribute of the &lt;supports-screens&gt; tag.
+     */
+    public int compatibleWidthLimitDp = 0;
+
+    /**
      * Full path to the location of this package.
      */
     public String sourceDir;
@@ -410,6 +426,8 @@
         pw.println(prefix + "taskAffinity=" + taskAffinity);
         pw.println(prefix + "uid=" + uid + " flags=0x" + Integer.toHexString(flags)
                 + " theme=0x" + Integer.toHexString(theme));
+        pw.println(prefix + "requiresSmallestWidthDp=" + requiresSmallestWidthDp
+                + " compatibleWidthLimitDp=" + compatibleWidthLimitDp);
         pw.println(prefix + "sourceDir=" + sourceDir);
         if (sourceDir == null) {
             if (publicSourceDir != null) {
@@ -469,6 +487,8 @@
         className = orig.className;
         theme = orig.theme;
         flags = orig.flags;
+        requiresSmallestWidthDp = orig.requiresSmallestWidthDp;
+        compatibleWidthLimitDp = orig.compatibleWidthLimitDp;
         sourceDir = orig.sourceDir;
         publicSourceDir = orig.publicSourceDir;
         nativeLibraryDir = orig.nativeLibraryDir;
@@ -502,6 +522,8 @@
         dest.writeString(className);
         dest.writeInt(theme);
         dest.writeInt(flags);
+        dest.writeInt(requiresSmallestWidthDp);
+        dest.writeInt(compatibleWidthLimitDp);
         dest.writeString(sourceDir);
         dest.writeString(publicSourceDir);
         dest.writeString(nativeLibraryDir);
@@ -536,6 +558,8 @@
         className = source.readString();
         theme = source.readInt();
         flags = source.readInt();
+        requiresSmallestWidthDp = source.readInt();
+        compatibleWidthLimitDp = source.readInt();
         sourceDir = source.readString();
         publicSourceDir = source.readString();
         nativeLibraryDir = source.readString();
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 9ff324b..5f9a957 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -993,6 +993,13 @@
                 sa = res.obtainAttributes(attrs,
                         com.android.internal.R.styleable.AndroidManifestSupportsScreens);
 
+                pkg.applicationInfo.requiresSmallestWidthDp = sa.getInteger(
+                        com.android.internal.R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
+                        0);
+                pkg.applicationInfo.compatibleWidthLimitDp = sa.getInteger(
+                        com.android.internal.R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
+                        0);
+
                 // This is a trick to get a boolean and still able to detect
                 // if a value was actually set.
                 supportsSmallScreens = sa.getInteger(
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index 8d725cd..e42caca 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -63,37 +63,19 @@
     private static final int SCALING_REQUIRED = 1; 
 
     /**
-     * Has the application said that its UI is expandable?  Based on the
-     * <supports-screen> android:expandible in the manifest.
-     */
-    private static final int EXPANDABLE = 2;
-    
-    /**
-     * Has the application said that its UI supports large screens?  Based on the
-     * <supports-screen> android:largeScreens in the manifest.
-     */
-    private static final int LARGE_SCREENS = 8;
-    
-    /**
-     * Has the application said that its UI supports xlarge screens?  Based on the
-     * <supports-screen> android:xlargeScreens in the manifest.
-     */
-    private static final int XLARGE_SCREENS = 32;
-    
-    /**
      * Application must always run in compatibility mode?
      */
-    private static final int ALWAYS_COMPAT = 64;
+    private static final int ALWAYS_NEEDS_COMPAT = 2;
 
     /**
      * Application never should run in compatibility mode?
      */
-    private static final int NEVER_COMPAT = 128;
+    private static final int NEVER_NEEDS_COMPAT = 4;
 
     /**
      * Set if the application needs to run in screen size compatibility mode.
      */
-    private static final int NEEDS_SCREEN_COMPAT = 256;
+    private static final int NEEDS_SCREEN_COMPAT = 8;
 
     /**
      * The effective screen density we have selected for this application.
@@ -110,86 +92,126 @@
      */
     public final float applicationInvertedScale;
 
-    public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, boolean forceCompat) {
+    public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, int sw,
+            boolean forceCompat) {
         int compatFlags = 0;
 
-        // We can't rely on the application always setting
-        // FLAG_RESIZEABLE_FOR_SCREENS so will compute it based on various input.
-        boolean anyResizeable = false;
-
-        if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
-            compatFlags |= LARGE_SCREENS;
-            anyResizeable = true;
-            if (!forceCompat) {
-                // If we aren't forcing the app into compatibility mode, then
-                // assume if it supports large screens that we should allow it
-                // to use the full space of an xlarge screen as well.
-                compatFlags |= XLARGE_SCREENS | EXPANDABLE;
+        if (appInfo.requiresSmallestWidthDp != 0 || appInfo.compatibleWidthLimitDp != 0) {
+            // New style screen requirements spec.
+            int required = appInfo.requiresSmallestWidthDp != 0
+                    ? appInfo.requiresSmallestWidthDp
+                    : appInfo.compatibleWidthLimitDp;
+            int compat = appInfo.compatibleWidthLimitDp != 0
+                    ? appInfo.compatibleWidthLimitDp
+                    : appInfo.requiresSmallestWidthDp;
+            if (compat < required)  {
+                compat = required;
             }
-        }
-        if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) {
-            anyResizeable = true;
-            if (!forceCompat) {
-                compatFlags |= XLARGE_SCREENS | EXPANDABLE;
+
+            if (compat >= sw) {
+                compatFlags |= NEVER_NEEDS_COMPAT;
+            } else if (forceCompat) {
+                compatFlags |= NEEDS_SCREEN_COMPAT;
             }
-        }
-        if ((appInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
-            anyResizeable = true;
-            compatFlags |= EXPANDABLE;
-        }
 
-        if (forceCompat) {
-            // If we are forcing compatibility mode, then ignore an app that
-            // just says it is resizable for screens.  We'll only have it fill
-            // the screen if it explicitly says it supports the screen size we
-            // are running in.
-            compatFlags &= ~EXPANDABLE;
-        }
-
-        boolean supportsScreen = false;
-        switch (screenLayout&Configuration.SCREENLAYOUT_SIZE_MASK) {
-            case Configuration.SCREENLAYOUT_SIZE_XLARGE:
-                if ((compatFlags&XLARGE_SCREENS) != 0) {
-                    supportsScreen = true;
-                }
-                if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) {
-                    compatFlags |= NEVER_COMPAT;
-                }
-                break;
-            case Configuration.SCREENLAYOUT_SIZE_LARGE:
-                if ((compatFlags&LARGE_SCREENS) != 0) {
-                    supportsScreen = true;
-                }
-                if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
-                    compatFlags |= NEVER_COMPAT;
-                }
-                break;
-        }
-
-        if ((screenLayout&Configuration.SCREENLAYOUT_COMPAT_NEEDED) != 0) {
-            if ((compatFlags&EXPANDABLE) != 0) {
-                supportsScreen = true;
-            } else if (!anyResizeable) {
-                compatFlags |= ALWAYS_COMPAT;
-            }
-        }
-
-        if (supportsScreen) {
-            compatFlags &= ~NEEDS_SCREEN_COMPAT;
-        } else {
-            compatFlags |= NEEDS_SCREEN_COMPAT;
-        }
-        
-        if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
+            // Modern apps always support densities.
             applicationDensity = DisplayMetrics.DENSITY_DEVICE;
             applicationScale = 1.0f;
             applicationInvertedScale = 1.0f;
+
         } else {
-            applicationDensity = DisplayMetrics.DENSITY_DEFAULT;
-            applicationScale = DisplayMetrics.DENSITY_DEVICE
-                    / (float) DisplayMetrics.DENSITY_DEFAULT;
-            applicationInvertedScale = 1.0f / applicationScale;
-            compatFlags |= SCALING_REQUIRED;
+            /**
+             * Has the application said that its UI is expandable?  Based on the
+             * <supports-screen> android:expandible in the manifest.
+             */
+            final int EXPANDABLE = 2;
+
+            /**
+             * Has the application said that its UI supports large screens?  Based on the
+             * <supports-screen> android:largeScreens in the manifest.
+             */
+            final int LARGE_SCREENS = 8;
+
+            /**
+             * Has the application said that its UI supports xlarge screens?  Based on the
+             * <supports-screen> android:xlargeScreens in the manifest.
+             */
+            final int XLARGE_SCREENS = 32;
+
+            int sizeInfo = 0;
+
+            // We can't rely on the application always setting
+            // FLAG_RESIZEABLE_FOR_SCREENS so will compute it based on various input.
+            boolean anyResizeable = false;
+
+            if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
+                sizeInfo |= LARGE_SCREENS;
+                anyResizeable = true;
+                if (!forceCompat) {
+                    // If we aren't forcing the app into compatibility mode, then
+                    // assume if it supports large screens that we should allow it
+                    // to use the full space of an xlarge screen as well.
+                    sizeInfo |= XLARGE_SCREENS | EXPANDABLE;
+                }
+            }
+            if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) {
+                anyResizeable = true;
+                if (!forceCompat) {
+                    sizeInfo |= XLARGE_SCREENS | EXPANDABLE;
+                }
+            }
+            if ((appInfo.flags & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
+                anyResizeable = true;
+                sizeInfo |= EXPANDABLE;
+            }
+
+            if (forceCompat) {
+                // If we are forcing compatibility mode, then ignore an app that
+                // just says it is resizable for screens.  We'll only have it fill
+                // the screen if it explicitly says it supports the screen size we
+                // are running in.
+                sizeInfo &= ~EXPANDABLE;
+            }
+
+            compatFlags |= NEEDS_SCREEN_COMPAT;
+            switch (screenLayout&Configuration.SCREENLAYOUT_SIZE_MASK) {
+                case Configuration.SCREENLAYOUT_SIZE_XLARGE:
+                    if ((sizeInfo&XLARGE_SCREENS) != 0) {
+                        compatFlags &= ~NEEDS_SCREEN_COMPAT;
+                    }
+                    if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) {
+                        compatFlags |= NEVER_NEEDS_COMPAT;
+                    }
+                    break;
+                case Configuration.SCREENLAYOUT_SIZE_LARGE:
+                    if ((sizeInfo&LARGE_SCREENS) != 0) {
+                        compatFlags &= ~NEEDS_SCREEN_COMPAT;
+                    }
+                    if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
+                        compatFlags |= NEVER_NEEDS_COMPAT;
+                    }
+                    break;
+            }
+
+            if ((screenLayout&Configuration.SCREENLAYOUT_COMPAT_NEEDED) != 0) {
+                if ((sizeInfo&EXPANDABLE) != 0) {
+                    compatFlags &= ~NEEDS_SCREEN_COMPAT;
+                } else if (!anyResizeable) {
+                    compatFlags |= ALWAYS_NEEDS_COMPAT;
+                }
+            }
+
+            if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
+                applicationDensity = DisplayMetrics.DENSITY_DEVICE;
+                applicationScale = 1.0f;
+                applicationInvertedScale = 1.0f;
+            } else {
+                applicationDensity = DisplayMetrics.DENSITY_DEFAULT;
+                applicationScale = DisplayMetrics.DENSITY_DEVICE
+                        / (float) DisplayMetrics.DENSITY_DEFAULT;
+                applicationInvertedScale = 1.0f / applicationScale;
+                compatFlags |= SCALING_REQUIRED;
+            }
         }
 
         mCompatibilityFlags = compatFlags;
@@ -204,8 +226,7 @@
     }
 
     private CompatibilityInfo() {
-        this(XLARGE_SCREENS | LARGE_SCREENS | EXPANDABLE,
-                DisplayMetrics.DENSITY_DEVICE,
+        this(NEVER_NEEDS_COMPAT, DisplayMetrics.DENSITY_DEVICE,
                 1.0f,
                 1.0f);
     }
@@ -214,7 +235,7 @@
      * @return true if the scaling is required
      */
     public boolean isScalingRequired() {
-        return (mCompatibilityFlags & SCALING_REQUIRED) != 0;
+        return (mCompatibilityFlags&SCALING_REQUIRED) != 0;
     }
     
     public boolean supportsScreen() {
@@ -222,16 +243,11 @@
     }
     
     public boolean neverSupportsScreen() {
-        return (mCompatibilityFlags&NEVER_COMPAT) != 0;
+        return (mCompatibilityFlags&NEVER_NEEDS_COMPAT) != 0;
     }
 
     public boolean alwaysSupportsScreen() {
-        return (mCompatibilityFlags&ALWAYS_COMPAT) != 0;
-    }
-
-    @Override
-    public String toString() {
-        return "CompatibilityInfo{scale=" + applicationScale + "}";
+        return (mCompatibilityFlags&ALWAYS_NEEDS_COMPAT) != 0;
     }
 
     /**
@@ -490,6 +506,28 @@
     }
 
     @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("{");
+        sb.append(applicationDensity);
+        sb.append("dpi");
+        if (isScalingRequired()) {
+            sb.append(" scaling");
+        }
+        if (!supportsScreen()) {
+            sb.append(" resizing");
+        }
+        if (neverSupportsScreen()) {
+            sb.append(" never-compat");
+        }
+        if (alwaysSupportsScreen()) {
+            sb.append(" always-compat");
+        }
+        sb.append("}");
+        return sb.toString();
+    }
+
+    @Override
     public int hashCode() {
         int result = 17;
         result = 31 * result + mCompatibilityFlags;
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index e63e7eb..81dc46a 100755
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -193,11 +193,7 @@
             Configuration config, CompatibilityInfo compInfo) {
         mAssets = assets;
         mMetrics.setToDefaults();
-        if (compInfo == null) {
-            mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
-        } else {
-            mCompatibilityInfo = compInfo;
-        }
+        mCompatibilityInfo = compInfo;
         updateConfiguration(config, metrics);
         assets.ensureStringBlocks();
     }
@@ -1416,7 +1412,9 @@
             int configChanges = 0xfffffff;
             if (config != null) {
                 mTmpConfig.setTo(config);
-                mCompatibilityInfo.applyToConfiguration(mTmpConfig);
+                if (mCompatibilityInfo != null) {
+                    mCompatibilityInfo.applyToConfiguration(mTmpConfig);
+                }
                 configChanges = mConfiguration.updateFrom(mTmpConfig);
                 configChanges = ActivityInfo.activityInfoConfigToNative(configChanges);
             }
@@ -1434,7 +1432,9 @@
                 // it would be cleaner and more maintainble to just be
                 // consistently dealing with a compatible display everywhere in
                 // the framework.
-                mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
+                if (mCompatibilityInfo != null) {
+                    mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
+                }
             }
             mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
 
@@ -1565,11 +1565,12 @@
      * Return the compatibility mode information for the application.
      * The returned object should be treated as read-only.
      * 
-     * @return compatibility info. null if the app does not require compatibility mode.
+     * @return compatibility info.
      * @hide
      */
     public CompatibilityInfo getCompatibilityInfo() {
-        return mCompatibilityInfo;
+        return mCompatibilityInfo != null ? mCompatibilityInfo
+                : CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
     }
 
     /**
diff --git a/core/java/android/database/sqlite/SQLiteQueryBuilder.java b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
index 9c09e81..8f8eb6e 100644
--- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java
+++ b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
@@ -145,15 +145,6 @@
     }
 
     /**
-     * Need to keep this to not break the build until ContactsProvider2 has been changed to
-     * use the new API
-     * TODO: Remove this
-     * @hide
-     */
-    public void setStrictProjectionMap(boolean flag) {
-    }
-
-    /**
      * When set, the selection is verified against malicious arguments.
      * When using this class to create a statement using
      * {@link #buildQueryString(boolean, String, String[], String, String, String, String, String)},
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 6fd1d00..cdb622c 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -23,7 +23,6 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.util.Log;
-import android.util.Slog;
 import android.util.SparseArray;
 
 import java.lang.ref.WeakReference;
@@ -100,10 +99,11 @@
     private final ObbActionListener mObbActionListener = new ObbActionListener();
 
     private class ObbActionListener extends IObbActionListener.Stub {
+        @SuppressWarnings("hiding")
         private SparseArray<ObbListenerDelegate> mListeners = new SparseArray<ObbListenerDelegate>();
 
         @Override
-        public void onObbResult(String filename, int nonce, int status) throws RemoteException {
+        public void onObbResult(String filename, int nonce, int status) {
             final ObbListenerDelegate delegate;
             synchronized (mListeners) {
                 delegate = mListeners.get(nonce);
@@ -147,8 +147,8 @@
             mHandler = new Handler(mTgtLooper) {
                 @Override
                 public void handleMessage(Message msg) {
-                    final OnObbStateChangeListener listener = getListener();
-                    if (listener == null) {
+                    final OnObbStateChangeListener changeListener = getListener();
+                    if (changeListener == null) {
                         return;
                     }
 
@@ -156,7 +156,7 @@
 
                     if (msg.what == StorageEvent.EVENT_OBB_STATE_CHANGED) {
                         ObbStateChangedStorageEvent ev = (ObbStateChangedStorageEvent) e;
-                        listener.onObbStateChange(ev.path, ev.state);
+                        changeListener.onObbStateChange(ev.path, ev.state);
                     } else {
                         Log.e(TAG, "Unsupported event " + msg.what);
                     }
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index bc6e993..bc4208a 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -16,10 +16,8 @@
 
 package android.os.storage;
 
-import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.util.Log;
 
 /**
  * A class representing a storage volume
@@ -27,7 +25,7 @@
  */
 public class StorageVolume implements Parcelable {
 
-    private static final String TAG = "StorageVolume";
+    //private static final String TAG = "StorageVolume";
 
     private final String mPath;
     private final String mDescription;
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 717dde8..ddd3252 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -55,6 +55,8 @@
 
     private CallbackMap mCallbacks;
 
+    private int mDefaultAvailability = TextToSpeech.LANG_NOT_SUPPORTED;
+
     @Override
     public void onCreate() {
         if (DBG) Log.d(TAG, "onCreate()");
@@ -71,7 +73,8 @@
         mCallbacks = new CallbackMap();
 
         // Load default language
-        onLoadLanguage(getDefaultLanguage(), getDefaultCountry(), getDefaultVariant());
+        mDefaultAvailability = onLoadLanguage(getDefaultLanguage(),
+                getDefaultCountry(), getDefaultVariant());
     }
 
     @Override
@@ -651,17 +654,43 @@
             return onGetLanguage();
         }
 
+        /*
+         * If defaults are enforced, then no language is "available" except
+         * perhaps the default language selected by the user.
+         */
         public int isLanguageAvailable(String lang, String country, String variant) {
+            if (areDefaultsEnforced()) {
+                if (isDefault(lang, country, variant)) {
+                    return mDefaultAvailability;
+                } else {
+                    return TextToSpeech.LANG_NOT_SUPPORTED;
+                }
+            }
             return onIsLanguageAvailable(lang, country, variant);
         }
 
+        /*
+         * There is no point loading a non default language if defaults
+         * are enforced.
+         */
         public int loadLanguage(String lang, String country, String variant) {
+            if (areDefaultsEnforced()) {
+                if (isDefault(lang, country, variant)) {
+                    return mDefaultAvailability;
+                } else {
+                    return TextToSpeech.LANG_NOT_SUPPORTED;
+                }
+            }
             return onLoadLanguage(lang, country, variant);
         }
 
         public void setCallback(String packageName, ITextToSpeechCallback cb) {
             mCallbacks.setCallback(packageName, cb);
         }
+
+        private boolean isDefault(String lang, String country, String variant) {
+            return Locale.getDefault().equals(new Locale(lang, country, variant));
+        }
     };
 
     private class CallbackMap extends RemoteCallbackList<ITextToSpeechCallback> {
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index 60a4ef2..d594567 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -38,6 +38,15 @@
     public static final int DENSITY_MEDIUM = 160;
 
     /**
+     * Standard quantized DPI for 720p TV screens.  Applications should
+     * generally not worry about this density, instead targeting
+     * {@link #DENSITY_XHIGH} for 1080p TV screens.  For situations where
+     * output is needed for a 720p screen, the UI elements can be scaled
+     * automatically by the platform.
+     */
+    public static final int DENSITY_TV = 213;
+
+    /**
      * Standard quantized DPI for high-density screens.
      */
     public static final int DENSITY_HIGH = 240;
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 2b79a76..d5cad96 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -201,6 +201,14 @@
     private static native void nSetViewport(int renderer, int width, int height);
 
     /**
+     * Preserves the back buffer of the current surface after a buffer swap.
+     * Calling this method sets the EGL_SWAP_BEHAVIOR attribute of the current
+     * surface to EGL_BUFFER_PRESERVED. Calling this method requires an EGL
+     * config that supports EGL_SWAP_BEHAVIOR_PRESERVED_BIT.
+     * 
+     * @return True if the swap behavior was successfully changed,
+     *         false otherwise.
+     * 
      * @hide
      */
     public static boolean preserveBackBuffer() {
@@ -208,6 +216,21 @@
     }
 
     private static native boolean nPreserveBackBuffer();    
+
+    /**
+     * Indicates whether the current surface preserves its back buffer
+     * after a buffer swap.
+     * 
+     * @return True, if the surface's EGL_SWAP_BEHAVIOR is EGL_BUFFER_PRESERVED,
+     *         false otherwise
+     *         
+     * @hide
+     */
+    public static boolean isBackBufferPreserved() {
+        return nIsBackBufferPreserved();
+    }
+
+    private static native boolean nIsBackBufferPreserved();    
     
     @Override
     void onPreDraw(Rect dirty) {
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 61a24a0..2611ec0 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -311,6 +311,7 @@
         Paint mDebugPaint;
 
         boolean mDirtyRegions;
+        final boolean mDirtyRegionsRequested;
 
         final int mGlVersion;
         final boolean mTranslucent;
@@ -325,6 +326,7 @@
             final String dirtyProperty = SystemProperties.get(RENDER_DIRTY_REGIONS_PROPERTY, "true");
             //noinspection PointlessBooleanExpression,ConstantConditions
             mDirtyRegions = RENDER_DIRTY_REGIONS && "true".equalsIgnoreCase(dirtyProperty);
+            mDirtyRegionsRequested = mDirtyRegions;
         }
 
         /**
@@ -545,11 +547,21 @@
                 throw new Surface.OutOfResourcesException("eglMakeCurrent failed "
                         + getEGLErrorString(sEgl.eglGetError()));
             }
-            
+
+            // If mDirtyRegions is set, this means we have an EGL configuration
+            // with EGL_SWAP_BEHAVIOR_PRESERVED_BIT set
             if (mDirtyRegions) {
                 if (!GLES20Canvas.preserveBackBuffer()) {
                     Log.w(LOG_TAG, "Backbuffer cannot be preserved");
                 }
+            } else if (mDirtyRegionsRequested) {
+                // If mDirtyRegions is not set, our EGL configuration does not
+                // have EGL_SWAP_BEHAVIOR_PRESERVED_BIT; however, the default
+                // swap behavior might be EGL_BUFFER_PRESERVED, which means we
+                // want to set mDirtyRegions. We try to do this only if dirty
+                // regions were initially requested as part of the device
+                // configuration (see RENDER_DIRTY_REGIONS)
+                mDirtyRegions = GLES20Canvas.isBackBufferPreserved();
             }
 
             return sEglContext.getGL();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c9db697..014f19f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4147,7 +4147,7 @@
      * @attr ref android.R.styleable#View_horizontalDirection
      * @hide
      */
-    @ViewDebug.ExportedProperty(mapping = {
+    @ViewDebug.ExportedProperty(category = "layout", mapping = {
         @ViewDebug.IntToString(from = HORIZONTAL_DIRECTION_LTR,     to = "LTR"),
         @ViewDebug.IntToString(from = HORIZONTAL_DIRECTION_RTL,     to = "RTL"),
         @ViewDebug.IntToString(from = HORIZONTAL_DIRECTION_INHERIT, to = "INHERIT"),
@@ -10043,6 +10043,7 @@
      *
      * @return true if the layout is right-to-left.
      */
+    @ViewDebug.ExportedProperty(category = "layout")
     public boolean isLayoutRtl() {
         return (mPrivateFlags2 & RESOLVED_LAYOUT_RTL) == RESOLVED_LAYOUT_RTL;
     }
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index ea66d67..4df237b 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1024,13 +1024,13 @@
                 if (DEBUG) Log.v(TAG, "START INPUT: " + view + " ic="
                         + ic + " tba=" + tba + " initial=" + initial);
                 InputBindResult res = mService.startInput(mClient,
-                        servedContext, tba, initial, mCurMethod == null);
+                        servedContext, tba, initial, true);
                 if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res);
                 if (res != null) {
                     if (res.id != null) {
                         mBindSequence = res.sequence;
                         mCurMethod = res.method;
-                    } else {
+                    } else if (mCurMethod == null) {
                         // This means there is no input method available.
                         if (DEBUG) Log.v(TAG, "ABORT input: no input method!");
                         return;
diff --git a/core/java/android/webkit/PluginFullScreenHolder.java b/core/java/android/webkit/PluginFullScreenHolder.java
index ae326d5..42ba7c9 100644
--- a/core/java/android/webkit/PluginFullScreenHolder.java
+++ b/core/java/android/webkit/PluginFullScreenHolder.java
@@ -24,34 +24,44 @@
  */
 package android.webkit;
 
-import android.app.Dialog;
+import android.content.Context;
+import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.SurfaceView;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.FrameLayout;
 
-class PluginFullScreenHolder extends Dialog {
+class PluginFullScreenHolder {
 
     private final WebView mWebView;
     private final int mNpp;
+    private final int mOrientation;
+
+    // The container for the plugin view
+    private static CustomFrameLayout mLayout;
+
     private View mContentView;
 
-    PluginFullScreenHolder(WebView webView, int npp) {
-        super(webView.getContext(), android.R.style.Theme_NoTitleBar_Fullscreen);
+    PluginFullScreenHolder(WebView webView, int orientation, int npp) {
         mWebView = webView;
         mNpp = npp;
+        mOrientation = orientation;
     }
 
-    @Override
     public void setContentView(View contentView) {
-        // as we are sharing the View between full screen and
-        // embedded mode, we have to remove the
-        // AbsoluteLayout.LayoutParams set by embedded mode to
-        // ViewGroup.LayoutParams before adding it to the dialog
-        contentView.setLayoutParams(new ViewGroup.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT,
-                ViewGroup.LayoutParams.MATCH_PARENT));
+
+        // Create a FrameLayout that will contain the plugin's view
+        mLayout = new CustomFrameLayout(mWebView.getContext());
+        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
+                            ViewGroup.LayoutParams.MATCH_PARENT,
+                            ViewGroup.LayoutParams.MATCH_PARENT,
+                            Gravity.CENTER);
+
+        mLayout.addView(contentView, layoutParams);
+        mLayout.setVisibility(View.VISIBLE);
+
         // fixed size is only used either during pinch zoom or surface is too
         // big. Make sure it is not fixed size before setting it to the full
         // screen content view. The SurfaceView will be set to the correct mode
@@ -62,59 +72,79 @@
                 sView.getHolder().setSizeFromLayout();
             }
         }
-        super.setContentView(contentView);
+
         mContentView = contentView;
     }
 
-    @Override
-    public void onBackPressed() {
-        mWebView.mPrivateHandler.obtainMessage(WebView.HIDE_FULLSCREEN)
-                .sendToTarget();
+    public void show() {
+        // Other plugins may attempt to draw so hide them while we're active.
+        if (mWebView.getViewManager() != null)
+            mWebView.getViewManager().hideAll();
+
+        WebChromeClient client = mWebView.getWebChromeClient();
+        client.onShowCustomView(mLayout, mOrientation, mCallback);
     }
 
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        if (event.isSystem()) {
-            return super.onKeyDown(keyCode, event);
+    public void hide() {
+        WebChromeClient client = mWebView.getWebChromeClient();
+        client.onHideCustomView();
+    }
+
+    private class CustomFrameLayout extends FrameLayout {
+
+        CustomFrameLayout(Context context) {
+            super(context);
         }
-        mWebView.onKeyDown(keyCode, event);
-        // always return true as we are the handler
-        return true;
-    }
 
-    @Override
-    public boolean onKeyUp(int keyCode, KeyEvent event) {
-        if (event.isSystem()) {
-            return super.onKeyUp(keyCode, event);
+        @Override
+        public boolean onKeyDown(int keyCode, KeyEvent event) {
+            if (event.isSystem()) {
+                return super.onKeyDown(keyCode, event);
+            }
+            mWebView.onKeyDown(keyCode, event);
+            // always return true as we are the handler
+            return true;
         }
-        mWebView.onKeyUp(keyCode, event);
-        // always return true as we are the handler
-        return true;
-    }
 
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        // always return true as we don't want the event to propagate any further
-        return true;
-    }
-
-    @Override
-    public boolean onTrackballEvent(MotionEvent event) {
-        mWebView.onTrackballEvent(event);
-        // always return true as we are the handler
-        return true;
-    }
-
-    @Override
-    protected void onStop() {
-        super.onStop();
-        // manually remove the contentView's parent since the dialog does not
-        if (mContentView != null && mContentView.getParent() != null) {
-            ViewGroup vg = (ViewGroup) mContentView.getParent();
-            vg.removeView(mContentView);
+        @Override
+        public boolean onKeyUp(int keyCode, KeyEvent event) {
+            if (event.isSystem()) {
+                return super.onKeyUp(keyCode, event);
+            }
+            mWebView.onKeyUp(keyCode, event);
+            // always return true as we are the handler
+            return true;
         }
-        mWebView.getWebViewCore().sendMessage(
-                WebViewCore.EventHub.HIDE_FULLSCREEN, mNpp, 0);
-    }
 
+        @Override
+        public boolean onTouchEvent(MotionEvent event) {
+            // always return true as we don't want the event to propagate any further
+            return true;
+        }
+
+        @Override
+        public boolean onTrackballEvent(MotionEvent event) {
+            mWebView.onTrackballEvent(event);
+            // always return true as we are the handler
+            return true;
+        }
+    }
+    
+    private final WebChromeClient.CustomViewCallback mCallback =
+        new WebChromeClient.CustomViewCallback() {
+            public void onCustomViewHidden() {
+
+                mWebView.mPrivateHandler.obtainMessage(WebView.HIDE_FULLSCREEN)
+                    .sendToTarget();
+
+                mWebView.getWebViewCore().sendMessage(
+                        WebViewCore.EventHub.HIDE_FULLSCREEN, mNpp, 0);
+
+                mLayout.removeView(mContentView);
+                mLayout = null;
+
+                // Re enable plugin views.
+                mWebView.getViewManager().showAll();
+            }
+        };
 }
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 755366c..ae40ded 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -16,6 +16,7 @@
 
 package android.webkit;
 
+import android.content.pm.ActivityInfo;
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Message;
@@ -77,6 +78,18 @@
 
     /**
      * Notify the host application that the current page would
+     * like to show a custom View in a particular orientation.
+     * @param view is the View object to be shown.
+     * @param requestedOrientation An orientation constant as used in
+     * {@link ActivityInfo#screenOrientation ActivityInfo.screenOrientation}.
+     * @param callback is the callback to be invoked if and when the view
+     * is dismissed.
+     */
+    public void onShowCustomView(View view, int requestedOrientation,
+            CustomViewCallback callback) {};
+    
+    /**
+     * Notify the host application that the current page would
      * like to hide its custom view.
      */
     public void onHideCustomView() {}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 3c2c8f6..739d77e 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -5543,7 +5543,7 @@
 
     private void dismissFullScreenMode() {
         if (inFullScreenMode()) {
-            mFullScreenHolder.dismiss();
+            mFullScreenHolder.hide();
             mFullScreenHolder = null;
         }
     }
@@ -8198,16 +8198,15 @@
 
                 case SHOW_FULLSCREEN: {
                     View view = (View) msg.obj;
-                    int npp = msg.arg1;
+                    int orientation = msg.arg1;
+                    int npp = msg.arg2;
 
                     if (inFullScreenMode()) {
                         Log.w(LOGTAG, "Should not have another full screen.");
                         dismissFullScreenMode();
                     }
-                    mFullScreenHolder = new PluginFullScreenHolder(WebView.this, npp);
+                    mFullScreenHolder = new PluginFullScreenHolder(WebView.this, orientation, npp);
                     mFullScreenHolder.setContentView(view);
-                    mFullScreenHolder.setCancelable(false);
-                    mFullScreenHolder.setCanceledOnTouchOutside(false);
                     mFullScreenHolder.show();
 
                     break;
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 13a9793..16e4571 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -2623,14 +2623,15 @@
 
     // called by JNI. PluginWidget function to launch a full-screen view using a
     // View object provided by the plugin class.
-    private void showFullScreenPlugin(ViewManager.ChildView childView, int npp) {
+    private void showFullScreenPlugin(ViewManager.ChildView childView, int orientation, int npp) {
         if (mWebView == null) {
             return;
         }
 
         Message message = mWebView.mPrivateHandler.obtainMessage(WebView.SHOW_FULLSCREEN);
         message.obj = childView.mView;
-        message.arg1 = npp;
+        message.arg1 = orientation;
+        message.arg2 = npp;
         message.sendToTarget();
     }
 
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 0573d88..7803391 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -1006,8 +1006,9 @@
         boolean mobileSiteInOverview = mInZoomOverview &&
                 !exceedsMinScaleIncrement(newZoomOverviewScale, 1.0f);
         if (!mWebView.drawHistory() &&
-                (mInitialZoomOverview || scaleLessThanOverview || mobileSiteInOverview) &&
-                scaleHasDiff && zoomOverviewWidthChanged) {
+            (scaleLessThanOverview ||
+                ((mInitialZoomOverview || mobileSiteInOverview) &&
+                    scaleHasDiff && zoomOverviewWidthChanged))) {
             mInitialZoomOverview = false;
             setZoomScale(newZoomOverviewScale, !willScaleTriggerZoom(mTextWrapScale) &&
                 !mWebView.getSettings().getUseFixedViewport());
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 298fe00..f843574 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -103,21 +103,37 @@
     @ViewDebug.ExportedProperty(category = "measurement")
     private int mOrientation;
 
-    @ViewDebug.ExportedProperty(category = "measurement", mapping = {
-            @ViewDebug.IntToString(from =  -1,                       to = "NONE"),
-            @ViewDebug.IntToString(from = Gravity.NO_GRAVITY,        to = "NONE"),
-            @ViewDebug.IntToString(from = Gravity.TOP,               to = "TOP"),
-            @ViewDebug.IntToString(from = Gravity.BOTTOM,            to = "BOTTOM"),
-            @ViewDebug.IntToString(from = Gravity.LEFT,              to = "LEFT"),
-            @ViewDebug.IntToString(from = Gravity.RIGHT,             to = "RIGHT"),
-            @ViewDebug.IntToString(from = Gravity.BEFORE,            to = "BEFORE"),
-            @ViewDebug.IntToString(from = Gravity.AFTER,             to = "AFTER"),
-            @ViewDebug.IntToString(from = Gravity.CENTER_VERTICAL,   to = "CENTER_VERTICAL"),
-            @ViewDebug.IntToString(from = Gravity.FILL_VERTICAL,     to = "FILL_VERTICAL"),
-            @ViewDebug.IntToString(from = Gravity.CENTER_HORIZONTAL, to = "CENTER_HORIZONTAL"),
-            @ViewDebug.IntToString(from = Gravity.FILL_HORIZONTAL,   to = "FILL_HORIZONTAL"),
-            @ViewDebug.IntToString(from = Gravity.CENTER,            to = "CENTER"),
-            @ViewDebug.IntToString(from = Gravity.FILL,              to = "FILL")
+    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
+            @ViewDebug.FlagToString(mask = -1,
+                equals = -1, name = "NONE"),
+            @ViewDebug.FlagToString(mask = Gravity.NO_GRAVITY,
+                equals = Gravity.NO_GRAVITY,name = "NONE"),
+            @ViewDebug.FlagToString(mask = Gravity.TOP,
+                equals = Gravity.TOP, name = "TOP"),
+            @ViewDebug.FlagToString(mask = Gravity.BOTTOM,
+                equals = Gravity.BOTTOM, name = "BOTTOM"),
+            @ViewDebug.FlagToString(mask = Gravity.LEFT,
+                equals = Gravity.LEFT, name = "LEFT"),
+            @ViewDebug.FlagToString(mask = Gravity.RIGHT,
+                equals = Gravity.RIGHT, name = "RIGHT"),
+            @ViewDebug.FlagToString(mask = Gravity.BEFORE,
+                equals = Gravity.BEFORE, name = "BEFORE"),
+            @ViewDebug.FlagToString(mask = Gravity.AFTER,
+                equals = Gravity.AFTER, name = "AFTER"),
+            @ViewDebug.FlagToString(mask = Gravity.CENTER_VERTICAL,
+                equals = Gravity.CENTER_VERTICAL, name = "CENTER_VERTICAL"),
+            @ViewDebug.FlagToString(mask = Gravity.FILL_VERTICAL,
+                equals = Gravity.FILL_VERTICAL, name = "FILL_VERTICAL"),
+            @ViewDebug.FlagToString(mask = Gravity.CENTER_HORIZONTAL,
+                equals = Gravity.CENTER_HORIZONTAL, name = "CENTER_HORIZONTAL"),
+            @ViewDebug.FlagToString(mask = Gravity.FILL_HORIZONTAL,
+                equals = Gravity.FILL_HORIZONTAL, name = "FILL_HORIZONTAL"),
+            @ViewDebug.FlagToString(mask = Gravity.CENTER,
+                equals = Gravity.CENTER, name = "CENTER"),
+            @ViewDebug.FlagToString(mask = Gravity.FILL,
+                equals = Gravity.FILL, name = "FILL"),
+            @ViewDebug.FlagToString(mask = Gravity.RELATIVE_HORIZONTAL_DIRECTION,
+                equals = Gravity.RELATIVE_HORIZONTAL_DIRECTION, name = "RELATIVE")
         })
     private int mGravity = Gravity.BEFORE | Gravity.TOP;
 
diff --git a/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java b/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java
index 965022e..4773ce4 100644
--- a/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java
+++ b/core/java/com/android/internal/os/storage/ExternalStorageFormatter.java
@@ -14,6 +14,7 @@
 import android.os.storage.IMountService;
 import android.os.storage.StorageEventListener;
 import android.os.storage.StorageManager;
+import android.os.storage.StorageVolume;
 import android.util.Log;
 import android.view.WindowManager;
 import android.widget.Toast;
@@ -32,6 +33,9 @@
 
     public static final String EXTRA_ALWAYS_RESET = "always_reset";
 
+    // If non-null, the volume to format. Otherwise, will use the default external storage directory
+    private StorageVolume mStorageVolume;
+
     public static final ComponentName COMPONENT_NAME
             = new ComponentName("android", ExternalStorageFormatter.class.getName());
 
@@ -80,6 +84,8 @@
             mAlwaysReset = true;
         }
 
+        mStorageVolume = intent.getParcelableExtra(StorageVolume.EXTRA_STORAGE_VOLUME);
+
         if (mProgressDialog == null) {
             mProgressDialog = new ProgressDialog(this);
             mProgressDialog.setIndeterminate(true);
@@ -115,7 +121,9 @@
     @Override
     public void onCancel(DialogInterface dialog) {
         IMountService mountService = getMountService();
-        String extStoragePath = Environment.getExternalStorageDirectory().toString();
+        String extStoragePath = mStorageVolume == null ?
+                Environment.getExternalStorageDirectory().toString() :
+                mStorageVolume.getPath();
         try {
             mountService.mountVolume(extStoragePath);
         } catch (RemoteException e) {
@@ -133,12 +141,16 @@
     }
 
     void updateProgressState() {
-        String status = Environment.getExternalStorageState();
+        String status = mStorageVolume == null ?
+                Environment.getExternalStorageState() :
+                mStorageManager.getVolumeState(mStorageVolume.getPath());
         if (Environment.MEDIA_MOUNTED.equals(status)
                 || Environment.MEDIA_MOUNTED_READ_ONLY.equals(status)) {
             updateProgressDialog(R.string.progress_unmounting);
             IMountService mountService = getMountService();
-            String extStoragePath = Environment.getExternalStorageDirectory().toString();
+            final String extStoragePath = mStorageVolume == null ?
+                    Environment.getExternalStorageDirectory().toString() :
+                    mStorageVolume.getPath();
             try {
                 mountService.unmountVolume(extStoragePath, true);
             } catch (RemoteException e) {
@@ -149,9 +161,12 @@
                 || Environment.MEDIA_UNMOUNTABLE.equals(status)) {
             updateProgressDialog(R.string.progress_erasing);
             final IMountService mountService = getMountService();
-            final String extStoragePath = Environment.getExternalStorageDirectory().toString();
+            final String extStoragePath = mStorageVolume == null ?
+                    Environment.getExternalStorageDirectory().toString() :
+                    mStorageVolume.getPath();
             if (mountService != null) {
                 new Thread() {
+                    @Override
                     public void run() {
                         boolean success = false;
                         try {
@@ -185,7 +200,7 @@
                     }
                 }.start();
             } else {
-                Log.w("MediaFormat", "Unable to locate IMountService");
+                Log.w(TAG, "Unable to locate IMountService");
             }
         } else if (Environment.MEDIA_BAD_REMOVAL.equals(status)) {
             fail(R.string.media_bad_removal);
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index b3666cb..dfba486 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -397,13 +397,17 @@
             }
             raf.close();
             DevicePolicyManager dpm = getDevicePolicyManager();
+            KeyStore keyStore = KeyStore.getInstance();
             if (pattern != null) {
-                KeyStore.getInstance().password(patternToString(pattern));
+                keyStore.password(patternToString(pattern));
                 setBoolean(PATTERN_EVER_CHOSEN_KEY, true);
                 setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
                 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, pattern
                         .size(), 0, 0, 0, 0, 0, 0);
             } else {
+                if (keyStore.isEmpty()) {
+                    keyStore.reset();
+                }
                 dpm.setActivePasswordState(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0,
                         0, 0, 0, 0, 0);
             }
@@ -486,12 +490,13 @@
             }
             raf.close();
             DevicePolicyManager dpm = getDevicePolicyManager();
+            KeyStore keyStore = KeyStore.getInstance();
             if (password != null) {
                 // Update the encryption password.
                 updateEncryptionPassword(password);
 
                 // Update the keystore password
-                KeyStore.getInstance().password(password);
+                keyStore.password(password);
 
                 int computedQuality = computePasswordQuality(password);
                 setLong(PASSWORD_TYPE_KEY, Math.max(quality, computedQuality));
@@ -545,6 +550,11 @@
                 }
                 setString(PASSWORD_HISTORY_KEY, passwordHistory);
             } else {
+                // Conditionally reset the keystore if empty. If
+                // non-empty, we are just switching key guard type
+                if (keyStore.isEmpty()) {
+                    keyStore.reset();
+                }
                 dpm.setActivePasswordState(
                         DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED, 0, 0, 0, 0, 0, 0, 0);
             }
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index e2832ed..31988f7 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -91,11 +91,29 @@
     eglSurfaceAttrib(display, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
 
     EGLint error = eglGetError();
-    RENDERER_LOGD("Could not enable buffer preserved swap behavior (%x)", error);
+    if (error != EGL_SUCCESS) {
+        RENDERER_LOGD("Could not enable buffer preserved swap behavior (%x)", error);
+    }
 
     return error == EGL_SUCCESS;
 }
 
+static jboolean android_view_GLES20Canvas_isBackBufferPreserved(JNIEnv* env, jobject clazz) {
+    EGLDisplay display = eglGetCurrentDisplay();
+    EGLSurface surface = eglGetCurrentSurface(EGL_DRAW);
+    EGLint value;
+
+    eglGetError();
+    eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &value);
+
+    EGLint error = eglGetError();
+    if (error != EGL_SUCCESS) {
+        RENDERER_LOGD("Could not query buffer preserved swap behavior (%x)", error);
+    }
+
+    return error == EGL_SUCCESS && value == EGL_BUFFER_PRESERVED;
+}
+
 // ----------------------------------------------------------------------------
 // Constructors
 // ----------------------------------------------------------------------------
@@ -676,7 +694,8 @@
     { "nIsAvailable",       "()Z",             (void*) android_view_GLES20Canvas_isAvailable },
 
 #ifdef USE_OPENGL_RENDERER
-    { "nPreserveBackBuffer", "()Z",            (void*) android_view_GLES20Canvas_preserveBackBuffer },
+    { "nIsBackBufferPreserved", "()Z",         (void*) android_view_GLES20Canvas_isBackBufferPreserved },
+    { "nPreserveBackBuffer",    "()Z",         (void*) android_view_GLES20Canvas_preserveBackBuffer },
 
     { "nCreateRenderer",    "()I",             (void*) android_view_GLES20Canvas_createRenderer },
     { "nDestroyRenderer",   "(I)V",            (void*) android_view_GLES20Canvas_destroyRenderer },
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 6b7c2a6..dba03e9 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1019,6 +1019,30 @@
          <p>This appears as a child tag of the
          {@link #AndroidManifest manifest} tag. -->
     <declare-styleable name="AndroidManifestSupportsScreens" parent="AndroidManifest">
+        <!-- Starting with {@link android.os.Build.VERSION_CODES#HONEYCOMB_MR2},
+             this is the new way to specify the screens an application is
+             compatible with.  This attribute provides the required minimum
+             "smallest screen width" (as per the -swNNNdp resource configuration)
+             that the application can run on.  For example, a typical phone
+             screen is 320, a 7" tablet 600, and a 10" tablet 720.  If the
+             smallest screen width of the device is below the value supplied here,
+             then the application is considered incompatible with that device.
+             If not supplied, then any old smallScreens, normalScreens, largeScreens,
+             or xlargeScreens attributes will be used instead. -->
+        <attr name="requiresSmallestWidthDp" format="integer" />
+        <!-- Starting with {@link android.os.Build.VERSION_CODES#HONEYCOMB_MR2},
+             this is the new way to specify the screens an application is
+             compatible with.  This attribute provides the maximum
+             "smallest screen width" (as per the -swNNNdp resource configuration)
+             that the application is designed for.  If this value is smaller than
+             the "smallest screen width" of the device it is running on, the user
+             will of offered to run it in a compatibility mode that emulates a
+             smaller screen.  Currently the compatibility mode only emulates
+             phone screens, so it will not be used it the application provides
+             a requiresSmallestWidthDp that is larger than 320.  Typical values
+             used with this attribute are 320 for a phone screen, 600 for a
+             7" tablet, and 720 for a 10" tablet. -->
+        <attr name="compatibleWidthLimitDp" format="integer" />
         <!-- Indicates whether the application supports smaller screen form-factors.
              A small screen is defined as one with a smaller aspect ratio than
              the traditional HVGA screen; that is, for a portrait screen, less
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 4c3cfc1..6cdb957 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1643,11 +1643,18 @@
   <public type="mipmap" name="sym_def_app_icon" id="0x010d0000" />
 
 <!-- ===============================================================
-     Resources added in version 12 of the platform (Honeycomb / 3.1)
+     Resources added in version 12 of the platform (Honeycomb MR 1 / 3.1)
      =============================================================== -->
   <eat-comment />
   <public type="attr" name="textCursorDrawable" id="0x01010362" />
-  <public type="attr" name="resizeMode" />
+  <public type="attr" name="resizeMode" id="0x01010363" />
+
+<!-- ===============================================================
+     Resources added in version 13 of the platform (Honeycomb MR 2)
+     =============================================================== -->
+  <eat-comment />
+  <public type="attr" name="requiresSmallestWidthDp" id="0x01010364" />
+  <public type="attr" name="compatibleWidthLimitDp" />
 
 <!-- ===============================================================
      Resources added in version 13 of the platform (Ice Cream Sandwich)
@@ -1694,5 +1701,4 @@
   <public type="attr" name="notificationTimeout" />
   <public type="attr" name="accessibilityFlags" />
   <public type="attr" name="canRetrieveWindowContent" />
-
 </resources>
diff --git a/docs/html/guide/developing/tools/adb.jd b/docs/html/guide/developing/tools/adb.jd
index e891ccd..a109dc8 100644
--- a/docs/html/guide/developing/tools/adb.jd
+++ b/docs/html/guide/developing/tools/adb.jd
@@ -35,45 +35,9 @@
 </div>
 </div>
 
-<!-- 
-<p>Android Debug Bridge (adb) is a versatile tool that </a>. </p>
-
-<p>Some of ways you can use adb include:</p>
-
-<ul>
-
-</ul>
-<p>The sections below introduce adb and describe many of its common uses. </p>
-
-<h2>Contents</h2>
-<dl>
-<dt><a href="#overview">Overview</a></dt>
-<dt><a href="#issuingcommands">Issuing adb Commands</a></dt>
-<dt><a href="#devicestatus">Querying for Emulator/Device Instances</a></dt>
-<dt><a href="#directingcommands">Directing Commands to a Specific Emulator/Device Instance</a></dt>
-<dt><a href="#move">Installing an Application</a></dt>
-<dt><a href="#forwardports">Forwarding Ports</a></dt>
-<dt><a href="#copyfiles">Copying Files to or from an Emulator/Device Instance</a></dt>
-<dt><a href="#commandsummary">Listing of adb Commands </a></dt>
-<dt><a href="#shellcommands">Issuing Shell Commands</a></dt>
-    <dd><a href="#sqlite">Examining sqlite3 Databases from a Remote Shell</a></dd>
-    <dd><a href="#monkey">UI/Application Exerciser Monkey</a></dd>
-	<dd><a href="#othershellcommands">Other Shell Commands</a></dd>
-<dt><a href="#logcat">Enabling logcat Logging</a> </dt>
-	<dd><a href="#usinglogcat">Using logcat Commands</a></dd>
-	<dd><a href="#filteringoutput">Filtering Log Output</a></dd>
-	<dd><a href="#outputformat">Controlling Log Output Format</a></dd>
-	<dd><a href="#alternativebuffers">Viewing Alternative Log Buffers</a></dd>
-	<dd><a href="#stdout">Viewing stdout and stderr</a></dd>
-	<dd><a href="#logcatoptions">Listing of logcat Command Options</a></dd>
-<dt><a href="#stopping">Stopping the adb Server</a> </dt>
-</dl>
-
-<a name="overview"></a>
-
-<h2>Overview</h2>
--->
-<p>Android Debug Bridge (adb) is a versatile tool lets you manage the state of an emulator instance or Android-powered device. It is a client-server program that includes three components: </p>
+<p>Android Debug Bridge (adb) is a versatile command line tool that lets you communicate with an
+emulator instance or connected Android-powered device. It is a client-server program that includes
+three components: </p>
 
 <ul>
   <li>A client, which runs on your development machine. You can invoke a client from a shell by issuing an adb command. Other Android tools such as the ADT plugin and DDMS also create adb clients. </li>
diff --git a/docs/html/guide/practices/optimizing-for-3.0.jd b/docs/html/guide/practices/optimizing-for-3.0.jd
index 5cd519b..e968372 100644
--- a/docs/html/guide/practices/optimizing-for-3.0.jd
+++ b/docs/html/guide/practices/optimizing-for-3.0.jd
@@ -22,6 +22,14 @@
 </li>
 </ol>
 
+<h2>See also</h2>
+
+<ol>
+  <li><a
+href="{@docRoot}sdk/compatibility-library.html">Compatibility Library</a></li>
+  <li><a href="http://code.google.com/p/iosched/">Google I/O App source code</a></li>
+</ol>
+
 </div>
 </div>
 
@@ -172,7 +180,8 @@
 application will look and feel consistent with the system and other applications when it is
 enabled.</p>
     <p>Additionally, when an activity uses the holographic theme, the system enables the <a
-href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a> for the activity. The Action Bar
+href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a> for the activity and removes the
+Options Menu button in the system bar. The Action Bar
 replaces the traditional title bar at the top of the activity window and provides the user access to
 the activity's Options Menu.</p>
       </li>
@@ -233,27 +242,26 @@
 
 
 
-
-
 <h2 id="Upgrading">Upgrading or Developing a New App for Tablets</h2>
 
 <div class="sidebox-wrapper">
 <div class="sidebox">
-  <h3>Use new APIs and remain backward-compatible</h3>
+  <h3>Use the Compatibility Library to remain backward-compatible</h3>
 <p>It is possible for you to upgrade your application with some new
 APIs <em>and</em> remain compatible with older versions of Android. Usually, this requires that you
 use techniques such as reflection to check for the availability of certain APIs at runtime. However,
 to help you add features from Android 3.0 without requiring you to change your <a
 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code android:minSdkVersion}</a>
-or build target, we're providing a static library called the "Android Compatibility package"
+or build target, we're providing a static library called the <a
+href="{@docRoot}sdk/compatibility-library.html">Compatibility Library</a>
 (downloadable from the AVD and SDK Manager).</p>
 <p>This library includes APIs for <a
 href="{@docRoot}guide/topics/fundamentals/fragments.html">fragments</a>, <a
 href="{@docRoot}guide/topics/fundamentals/loaders.html">loaders</a>, and some updated classes. By
 simply adding this library to your Android project, you can use these APIs in your application and
-remain compatible with Android 1.6. For more information, see the blog post, <a
-href="http://android-developers.blogspot.com/2011/03/fragments-for-all.html">Fragments for
-All</a>.</p>
+remain compatible with Android 1.6. For information about how to get the library and start
+using it in your application, see the <a
+href="{@docRoot}sdk/compatibility-library.html">Compatibility Library</a> document.</p>
 </div>
 </div>
 
@@ -380,7 +388,6 @@
 href="{@docRoot}sdk/android-3.0.html">Android 3.0 Platform</a> document.</p>
 
 
-
 <h3>Look at some samples</h3>
 
 <p>Many of the new features and APIs that are described above and in the <a
diff --git a/docs/html/sdk/android-2.3.4.jd b/docs/html/sdk/android-2.3.4.jd
index e5765d3..4cb44b9 100644
--- a/docs/html/sdk/android-2.3.4.jd
+++ b/docs/html/sdk/android-2.3.4.jd
@@ -128,7 +128,7 @@
 <a href="{@docRoot}sdk/android-2.3.3.html">Android 2.3.3 version notes</a>.</p>
 
 
-<h2 id="openaccessory">Open Accessory Library</h3>
+<h2 id="openaccessory">Open Accessory Library</h2>
 
 <p><em>Open Accessory</em> is a new capability for integrating
 connected peripherals with applications running on the platform. The capability
@@ -241,7 +241,7 @@
 <li>Camera</li>
 <li>Clock</li>
 <li>Contacts</li>
-<li>Cusom Locale</li>
+<li>Custom Locale</li>
 <li>Dev Tools</li>
 <li>Downloads</li>
 <li>Email</li>
@@ -309,6 +309,7 @@
 </ul>
 </td>
 <td style="border:0;padding-bottom:0;margin-bottom:0;padding-left:5em;">
+<ul>
 <li>Croatian, Croatia (hr_HR)</li>
 <li>Hungarian, Hungary (hu_HU)</li>
 <li>Indonesian, Indonesia (id_ID)</li>
@@ -337,6 +338,7 @@
 <li>Vietnamese, Vietnam (vi_VN)</li>
 <li>Chinese, PRC (zh_CN)</li>
 <li>Chinese, Taiwan (zh_TW)</li>
+</ul>
 </td>
 </tr>
 </table>
diff --git a/docs/html/sdk/compatibility-library.jd b/docs/html/sdk/compatibility-library.jd
new file mode 100644
index 0000000..d4669e5
--- /dev/null
+++ b/docs/html/sdk/compatibility-library.jd
@@ -0,0 +1,224 @@
+page.title=Compatibility Library
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+  
+<h2>In this document</h2>
+<ol>
+  <li><a href="#Notes">Revisions</a></li>
+  <li><a href="#Installing">Installing the Compatibility Library</a></li>
+  <li><a href="#SettingUp">Setting Up a Project to Use the Library</a></li>
+  <li><a href="#Using">Using Some of the Library APIs</a></li>
+  <li><a href="#Samples">Samples</a></li>
+</ol>
+
+<h2>See also</h2>
+<ol>
+  <li><a
+href="{@docRoot}guide/practices/optimizing-for-3.0.html">Optimizing Apps for Android 3.0</a></li>
+  <li><a href="http://code.google.com/p/iosched/">Google I/O App source code</a></li>
+</ol>
+
+</div>
+</div>
+
+<p><em>Minimum API level supported:</em> <b>4</b></p>
+
+<p>The Compatibility Library is a static library you can add to your Android application in order to
+use APIs not available in older versions of the Android platform. The primary goal of the library is
+to provide APIs introduced in Andriod 3.0 for older versions of Android so that all applications can
+use them.</p>
+
+<p>If you're not able to use APIs introduced in Android 3.0 directly, because you want to remain
+backward-compatible, the Compatibility Library provides your application access to self-contained
+versions of some of the latest APIs that you can use with older versions of Android. Most
+importantly, the library provides implementations of the {@link android.app.Fragment} and {@link
+android.content.Loader} APIs, so you can use them in a way that's compatible with devices running
+Android 1.6 (API level 4) and higher. Thus, you can more easily create a single APK that supports a
+majority of devices and provide larger devices (such as tablets) a fully optimized experience by
+using <a href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> in your activity
+design.</p>
+
+
+<h2 id="Notes">Revisions</h2>
+
+<p>The sections below provide notes about successive releases of
+the Compatibility Library, as denoted by revision number.</p>
+
+
+<div class="toggle-content open">
+
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img" />
+    Compatibility Library, revision 2 (May 2011)
+  </a></p>
+
+  <div class="toggle-content-toggleme" style="padding-left:2em"> 
+    <dl>
+    <dt>Changes:</dt>
+    <dd>
+      <ul>
+        <li>Support for fragment animations.</li>
+        <li>Fix {@code Fragment.onActivityResult()} bug.</li>
+      </ul>
+    </dd>
+    </dl>
+  </div>
+
+</div>
+
+
+<div class="toggle-content closed">
+
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img" />
+    Compatibility Library, revision 1 (March 2011)
+  </a></p>
+
+  <div class="toggle-content-toggleme" style="padding-left:2em"> 
+      <p>Initial release of the library.</p>
+  </div>
+
+</div>
+
+
+
+<h2 id="Installing">Installing the Compatibility Library</h2>
+
+<p>The Compatibility Library is provided as a downloadable package from the Android SDK and AVD
+Manager. To install the library:</p>
+
+<ol>
+  <li>Launch the SDK and AVD Manager. 
+    <p>From Eclipse, you can select <strong>Window</strong>
+&gt; <strong>Android SDK and AVD Manager</strong>. Or, launch {@code SDK Manager.exe} from
+the {@code &lt;sdk&gt;/} directory (on Windows only) or {@code android} from the {@code
+&lt;sdk&gt;/tools/} directory.</p></li>
+  <li>Expand the Android Repository, check <strong>Android Compatibility package</strong>
+and click <strong>Install selected</strong>.</li>
+  <li>Proceed to install the package.</li>
+</ol>
+
+<p>When done, all files (including source code, samples, and the {@code .jar} file) are saved
+into the <code>&lt;sdk&gt;/extras/android/compatibility/</code> directory. The next directory
+name is {@code v4}, which indicates the lowest compatible version for the library within. That
+is, the code in {@code v4/} supports API level 4 and above. (There may be future libraries that
+have a different minimum version, so they will be saved alongside this one.)</p>
+
+
+<h2 id="SettingUp">Setting Up a Project to Use the Library</h2>
+
+<p>To add the Compatibility Library to your Android project:</p>
+<ol>
+  <li>In your Android project, create a directory named {@code libs} at the root of your
+project (next to {@code src/}, {@code res/}, etc.)</li>
+  <li>Navigate to {@code &lt;sdk&gt;/extras/android/compatibility/v4/}.</li>
+  <li>Copy the {@code android-support-v4.jar} file into your project {@code libs/} directory.</li>
+  <li>Add the JAR to your project build path. In Eclipse, right-click the JAR file in the
+Package Explorer, select <strong>Build Path</strong> &gt; <strong>Add to Build Path</strong>.
+You should then see the JAR file appear in a new directory called Referenced Libraries.</li>
+</ol>
+
+<p>Your application is now ready to use fragments, loaders and other APIs from the library. All the
+provided APIs are in the {@code android.support.v4} package.</p>
+
+<p class="warning"><strong>Warning:</strong> Be certain that you not confuse the standard
+{@code android} packages with those in {@code android.support.v4}. Some code completion tools might
+get this wrong, especially if you're building against recent versions of the platform. To be safe,
+keep your build target set to the same version as you have defined for your <a
+href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code android:minSdkVersion}</a>
+and double check the import statements for classes that are duplicated in the Compatibility
+Library, such as {@code SimpleCursorAdapter}.</p>
+
+
+<h2 id="Using">Using Some of the Library APIs</h2>
+
+<p>The Compatibility Library provides access to several classes introduced with Android 3.0, plus
+some updated version of existing classes. Some of the most useful and notable classes in the
+library are:</p>
+
+<ul>
+  <li>{@link android.app.Fragment}</li>
+  <li>{@link android.app.FragmentManager}</li>
+  <li>{@link android.app.FragmentTransaction}</li>
+  <li>{@link android.app.ListFragment}</li>
+  <li>{@link android.app.DialogFragment}</li>
+  <li>{@link android.app.LoaderManager}</li>
+  <li>{@link android.content.Loader}</li>
+  <li>{@link android.content.AsyncTaskLoader}</li>
+  <li>{@link android.content.CursorLoader}</li>
+</ul>
+
+<p>For each of the classes above (and others not listed), the APIs work almost exactly the same
+as the counterparts in the latest version of the Android platform. Thus, you can usually refer to
+the latest reference documentation for information about the supported APIs. There are some
+differences, however. Most notably:</p>
+
+<ul>
+  <li>When creating an activity to use fragments, you must declare your activity to extend the
+{@code FragmentActivity} class (instead of the traditional {@link android.app.Activity}
+class).</li>
+  <li>To manage your fragments and loaders, you must use the methods {@code
+FragmentActivity.getSupportFragmentManager()} and {@code
+FragmentActivity.getSupportLoaderManager()} (instead of the {@link
+android.app.Activity#getFragmentManager()} and {@link android.app.Activity#getLoaderManager()}
+methods).</li>
+  <li>The {@link android.app.ActionBar} is <strong>not supported</strong> by the library.
+However, when creating your <a href="{@docRoot}guide/topics/ui/menus.html#options-menu">Options
+Menu</a>, you can declare which items should be added to the Action Bar when it's available (on
+Android 3.0 or later). You can do so with the {@code MenuCompat.setShowAsAction()} method. For
+example:
+<pre>
+public boolean onCreateOptionsMenu(Menu menu) {
+    MenuInflater inflater = getMenuInflater();
+    inflater.inflate(R.menu.options, menu);
+    MenuCompat.setShowAsAction(menu.findItem(R.id.action_search), 1);
+    return true;
+}
+</pre>
+</li>
+</ul>
+
+<p>The Compatibility Library currently does not provide reference documentation for the included
+APIs. To generate your own set, using the {@code javadoc} tool, perform the
+following from a command line:</p>
+
+<pre class="no-pretty-print">
+cd &lt;sdk&gt;/extras/android/compatibility/v4/
+mkdir docs
+javadoc -sourcepath src/java/ -subpackages android.support.v4 -d docs
+</pre>
+<p>Open the {@code docs/index.html} file to begin browsing the generated documentation.</p>
+
+
+<div class="note"><p><strong>Tip:</strong> To enable the Holographic theme on devices
+running Android 3.0 or higher, declare in your manifest file that your application targets
+API level 11. For example:</p>
+<pre>
+&lt;uses-sdk android:minSdkVersion="4" android:targetSdkVersion="11" /&gt;
+</pre>
+<p>This way, your application automatically receives the Holographic theme and the Action Bar for 
+each activity when running on Android 3.0 and higher.</p>
+</div>
+
+<p>For more information about how you can optimize your application for the latest
+Android-powered devices, read <a href="{@docRoot}guide/practices/optimizing-for-3.0.html">Optimizing
+Apps for Android 3.0</a>.</p>
+
+
+<h2 id="Samples">Samples</h2>
+
+<p>If you want to see some sample code that uses the Compatibility Library, take a look at the
+<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/support/index.html">API
+Demos</a> sample code that's included with the Samples package you can download from the AVD and SDK
+Manager.</p>
+
+<p>Additionally, the <a href="http://code.google.com/p/iosched/">Google I/O App</a> is a complete
+application that uses the library to provide a single APK for both handsets and tablets and also
+demonstrates some of Android's best practices in Android UI design.</p>
+
+
+
+
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 7c1c86d..e7b8fbb 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -31,6 +31,16 @@
   <li>Explore the contents of the Android SDK (optional).</li>
 </ol>
 
-<p>To get started, download the appropriate package from the table above, then read the guide to <a
-href="installing.html">Installing the SDK</a>.</p>
+<p class="online-message">To get started, download the appropriate package from the table above,
+then read the guide to <a href="installing.html">Installing the SDK</a>.</p>
+
+<!-- non-inline style and based on only one selector so that
+     it can be overriden by the sdkpage.cs template -->
+<style type="text/css">
+  .offline-message { display:none; }
+</style>
+      
+<p class="offline-message">For more information about how to set up your
+development environment, read the guide to <a href="installing.html">Installing the SDK</a>.</p>
+
 </div>
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index 11f29b1..286307a 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -1,6 +1,5 @@
 <?cs if:!sdk.redirect ?>
-<ul><?cs
-  if:android.whichdoc == "online" ?>
+<ul>
   <li>
     <h2>
       <span class="en">Android SDK Starter Package</span>
@@ -12,7 +11,8 @@
       <span style="display:none" class="zh-CN">当前的 SDK 版本</span>
       <span style="display:none" class="zh-TW">目前 SDK 發行版本</span>
     </h2>
-    <ul>
+    <ul><?cs
+  if:android.whichdoc == "online" ?>
       <li><a href="<?cs var:toroot ?>sdk/index.html">
           <span class="en">Download</span>
           <span style="display:none" class="de">Herunterladen</span>
@@ -22,7 +22,8 @@
           <span style="display:none" class="ja">ダウンロード</span>
           <span style="display:none" class="zh-CN">下载</span>
           <span style="display:none" class="zh-TW">下載</span>
-        </a></li>
+        </a></li><?cs 
+  /if ?>
       <li><a href="<?cs var:toroot ?>sdk/installing.html">
           <span class="en">Installing the SDK</span>
           <span style="display:none" class="de">Installieren</span>
@@ -33,10 +34,8 @@
           <span style="display:none" class="zh-CN">安装</span>
           <span style="display:none" class="zh-TW">安裝</span>
         </a></li>
-
     </ul>
-  </li>
-  <?cs /if ?><?cs
+  </li><?cs
   if:sdk.preview ?>
   <li><h2>Android 3.0 Preview SDK</h2>
     <ul>
@@ -138,6 +137,8 @@
       <li><a href="<?cs var:toroot ?>sdk/tools-notes.html">SDK Tools, r11</a> <span
 class="new">new!</span></li>
       <li><a href="<?cs var:toroot ?>sdk/win-usb.html">Google USB Driver, r4</a></li>
+      <li><a href="<?cs var:toroot ?>sdk/compatibility-library.html">Compatibility Library, r2</a> <span
+class="new">new!</span></li>
     </ul>
   </li>
   <li>
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index 2c7cf75..8a92cd6 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -841,6 +841,7 @@
         DENSITY_DEFAULT = ACONFIGURATION_DENSITY_DEFAULT,
         DENSITY_LOW = ACONFIGURATION_DENSITY_LOW,
         DENSITY_MEDIUM = ACONFIGURATION_DENSITY_MEDIUM,
+        DENSITY_TV = ACONFIGURATION_DENSITY_TV,
         DENSITY_HIGH = ACONFIGURATION_DENSITY_HIGH,
         DENSITY_NONE = ACONFIGURATION_DENSITY_NONE
     };
@@ -1452,24 +1453,20 @@
     // settings is the requested settings
     inline bool match(const ResTable_config& settings) const {
         if (imsi != 0) {
-            if ((settings.mcc != 0 && mcc != 0
-                 && mcc != settings.mcc) || 
-                (settings.mcc == 0 && mcc != 0)) {
+            if (mcc != 0 && mcc != settings.mcc) {
                 return false;
             }
-            if ((settings.mnc != 0 && mnc != 0
-                 && mnc != settings.mnc) ||
-                (settings.mnc == 0 && mnc != 0)) {
+            if (mnc != 0 && mnc != settings.mnc) {
                 return false;
             }
         }
         if (locale != 0) {
-            if (settings.language[0] != 0 && language[0] != 0
+            if (language[0] != 0
                 && (language[0] != settings.language[0]
                     || language[1] != settings.language[1])) {
                 return false;
             }
-            if (settings.country[0] != 0 && country[0] != 0
+            if (country[0] != 0
                 && (country[0] != settings.country[0]
                     || country[1] != settings.country[1])) {
                 return false;
@@ -1480,66 +1477,56 @@
             const int setScreenSize = settings.screenLayout&MASK_SCREENSIZE;
             // Any screen sizes for larger screens than the setting do not
             // match.
-            if ((setScreenSize != 0 && screenSize != 0
-                    && screenSize > setScreenSize) ||
-                    (setScreenSize == 0 && screenSize != 0)) {
+            if (screenSize != 0 && screenSize > setScreenSize) {
                 return false;
             }
             
             const int screenLong = screenLayout&MASK_SCREENLONG;
             const int setScreenLong = settings.screenLayout&MASK_SCREENLONG;
-            if (setScreenLong != 0 && screenLong != 0
-                    && screenLong != setScreenLong) {
+            if (screenLong != 0 && 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) {
+            if (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) {
+            if (uiModeNight != 0 && uiModeNight != setUiModeNight) {
                 return false;
             }
 
-            if (settings.smallestScreenWidthDp != 0 && smallestScreenWidthDp != 0
+            if (smallestScreenWidthDp != 0
                     && smallestScreenWidthDp > settings.smallestScreenWidthDp) {
                 return false;
             }
         }
         if (screenSizeDp != 0) {
-            if (settings.screenWidthDp != 0 && screenWidthDp != 0
-                    && screenWidthDp > settings.screenWidthDp) {
+            if (screenWidthDp != 0 && screenWidthDp > settings.screenWidthDp) {
                 //LOGI("Filtering out width %d in requested %d", screenWidthDp, settings.screenWidthDp);
                 return false;
             }
-            if (settings.screenHeightDp != 0 && screenHeightDp != 0
-                    && screenHeightDp > settings.screenHeightDp) {
+            if (screenHeightDp != 0 && screenHeightDp > settings.screenHeightDp) {
                 //LOGI("Filtering out height %d in requested %d", screenHeightDp, settings.screenHeightDp);
                 return false;
             }
         }
         if (screenType != 0) {
-            if (settings.orientation != 0 && orientation != 0
-                && orientation != settings.orientation) {
+            if (orientation != 0 && orientation != settings.orientation) {
                 return false;
             }
             // density always matches - we can scale it.  See isBetterThan
-            if (settings.touchscreen != 0 && touchscreen != 0
-                && touchscreen != settings.touchscreen) {
+            if (touchscreen != 0 && touchscreen != settings.touchscreen) {
                 return false;
             }
         }
         if (input != 0) {
             const int keysHidden = inputFlags&MASK_KEYSHIDDEN;
             const int setKeysHidden = settings.inputFlags&MASK_KEYSHIDDEN;
-            if (setKeysHidden != 0 && keysHidden != 0
-                && keysHidden != setKeysHidden) {
+            if (keysHidden != 0 && keysHidden != setKeysHidden) {
                 // For compatibility, we count a request for KEYSHIDDEN_NO as also
                 // matching the more recent KEYSHIDDEN_SOFT.  Basically
                 // KEYSHIDDEN_NO means there is some kind of keyboard available.
@@ -1551,36 +1538,29 @@
             }
             const int navHidden = inputFlags&MASK_NAVHIDDEN;
             const int setNavHidden = settings.inputFlags&MASK_NAVHIDDEN;
-            if (setNavHidden != 0 && navHidden != 0
-                && navHidden != setNavHidden) {
+            if (navHidden != 0 && navHidden != setNavHidden) {
                 return false;
             }
-            if (settings.keyboard != 0 && keyboard != 0
-                && keyboard != settings.keyboard) {
+            if (keyboard != 0 && keyboard != settings.keyboard) {
                 return false;
             }
-            if (settings.navigation != 0 && navigation != 0
-                && navigation != settings.navigation) {
+            if (navigation != 0 && navigation != settings.navigation) {
                 return false;
             }
         }
         if (screenSize != 0) {
-            if (settings.screenWidth != 0 && screenWidth != 0
-                && screenWidth > settings.screenWidth) {
+            if (screenWidth != 0 && screenWidth > settings.screenWidth) {
                 return false;
             }
-            if (settings.screenHeight != 0 && screenHeight != 0
-                && screenHeight > settings.screenHeight) {
+            if (screenHeight != 0 && screenHeight > settings.screenHeight) {
                 return false;
             }
         }
         if (version != 0) {
-            if (settings.sdkVersion != 0 && sdkVersion != 0
-                && sdkVersion > settings.sdkVersion) {
+            if (sdkVersion != 0 && sdkVersion > settings.sdkVersion) {
                 return false;
             }
-            if (settings.minorVersion != 0 && minorVersion != 0
-                && minorVersion != settings.minorVersion) {
+            if (minorVersion != 0 && minorVersion != settings.minorVersion) {
                 return false;
             }
         }
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 6339710..e71f16c 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -4256,9 +4256,11 @@
         if (strncmp(componentName, "OMX.", 4)) {
             // Not an OpenMax component but a software codec.
 
+#if HAVE_SOFTWARE_DECODERS
             results->push();
             CodecCapabilities *caps = &results->editItemAt(results->size() - 1);
             caps->mComponentName = componentName;
+#endif
 
             continue;
         }
diff --git a/native/include/android/configuration.h b/native/include/android/configuration.h
index 39fef21..2444c4b 100644
--- a/native/include/android/configuration.h
+++ b/native/include/android/configuration.h
@@ -40,6 +40,7 @@
     ACONFIGURATION_DENSITY_DEFAULT = 0,
     ACONFIGURATION_DENSITY_LOW = 120,
     ACONFIGURATION_DENSITY_MEDIUM = 160,
+    ACONFIGURATION_DENSITY_TV = 213,
     ACONFIGURATION_DENSITY_HIGH = 240,
     ACONFIGURATION_DENSITY_NONE = 0xffff,
 
diff --git a/packages/SystemUI/res/values-sw600dp-port/config.xml b/packages/SystemUI/res/values-sw600dp-port/config.xml
new file mode 100644
index 0000000..ab7661a
--- /dev/null
+++ b/packages/SystemUI/res/values-sw600dp-port/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources>
+    <integer name="config_maxNotificationIcons">3</integer>
+</resources>
+
diff --git a/packages/SystemUI/res/values-sw600dp-port/dimens.xml b/packages/SystemUI/res/values-sw600dp-port/dimens.xml
index 78dd8c4..b8a6cfe 100644
--- a/packages/SystemUI/res/values-sw600dp-port/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp-port/dimens.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
- * Copyright (c) 2010, The Android Open Source Project
+ * Copyright (c) 2011, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); 
  * you may not use this file except in compliance with the License. 
@@ -17,6 +17,6 @@
 -->
 <resources>
     <!-- gap on either side of status bar notification icons -->
-    <dimen name="status_bar_icon_padding">2dp</dimen>
+    <dimen name="status_bar_icon_padding">0dp</dimen>
 </resources>
 
diff --git a/packages/SystemUI/res/values-sw720dp-port/dimens.xml b/packages/SystemUI/res/values-sw720dp-port/dimens.xml
new file mode 100644
index 0000000..74b266d
--- /dev/null
+++ b/packages/SystemUI/res/values-sw720dp-port/dimens.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+-->
+<resources>
+    <!-- gap on either side of status bar notification icons -->
+    <dimen name="status_bar_icon_padding">2dp</dimen>
+</resources>
+
diff --git a/packages/SystemUI/res/values-sw720dp/config.xml b/packages/SystemUI/res/values-sw720dp/config.xml
new file mode 100644
index 0000000..56b8e54
--- /dev/null
+++ b/packages/SystemUI/res/values-sw720dp/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources>
+    <integer name="config_maxNotificationIcons">5</integer>
+</resources>
+
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 48f572f..7a4ac5d 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -40,5 +40,8 @@
          autodetected from the Configuration. -->
     <bool name="config_showNavigationBar">false</bool>
 
+    <!-- How many icons may be shown at once in the system bar. Includes any
+         slots that may be reused for things like IME control. -->
+    <integer name="config_maxNotificationIcons">5</integer>
 </resources>
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 8750a6f..0aaf5e5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -81,9 +81,6 @@
     public static final boolean DEBUG = false;
     public static final String TAG = "TabletStatusBar";
 
-    public static final int MAX_NOTIFICATION_ICONS = 5;
-    // IME switcher icon is big and occupy width of two icons
-    public static final int MAX_NOTIFICATION_ICONS_IME_BUTTON_VISIBLE = MAX_NOTIFICATION_ICONS - 1;
 
     public static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
     public static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
@@ -105,6 +102,7 @@
     int mNaturalBarHeight = -1;
     int mIconSize = -1;
     int mIconHPadding = -1;
+    private int mMaxNotificationIcons = 5;
 
     H mHandler = new H();
 
@@ -344,6 +342,13 @@
             mIconSize = newIconSize;
             reloadAllNotificationIcons(); // reload the tray
         }
+
+        final int numIcons = res.getInteger(R.integer.config_maxNotificationIcons);
+        if (numIcons != mMaxNotificationIcons) {
+            mMaxNotificationIcons = numIcons;
+            if (DEBUG) Slog.d(TAG, "max notification icons: " + mMaxNotificationIcons);
+            reloadAllNotificationIcons();
+        }
     }
 
     protected View makeStatusBarView() {
@@ -1430,9 +1435,11 @@
 
         // When IME button is visible, the number of notification icons should be decremented
         // to fit the upper limit.
+        // IME switcher icon is big and occupy width of one icon
+        final int maxNotificationIconsImeButtonVisible = mMaxNotificationIcons - 1;
         final int maxNotificationIconsCount =
                 (mInputMethodSwitchButton.getVisibility() != View.GONE) ?
-                        MAX_NOTIFICATION_ICONS_IME_BUTTON_VISIBLE : MAX_NOTIFICATION_ICONS;
+                        maxNotificationIconsImeButtonVisible : mMaxNotificationIcons;
         for (int i=0; i< maxNotificationIconsCount; i++) {
             if (i>=N) break;
             toShow.add(mNotificationData.get(N-i-1).icon);
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
index ae23df6..7983278 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
@@ -20,6 +20,7 @@
 
 import android.content.Context;
 import android.content.pm.ActivityInfo;
+import android.content.res.Resources;
 import android.graphics.PixelFormat;
 import android.graphics.Canvas;
 import android.util.Log;
@@ -94,6 +95,8 @@
     public synchronized void show() {
         if (DEBUG) Log.d(TAG, "show(); mKeyguardView==" + mKeyguardView);
 
+        Resources res = mContext.getResources();
+        boolean enableScreenRotation = res.getBoolean(R.bool.config_enableLockScreenRotation);
         if (mKeyguardHost == null) {
             if (DEBUG) Log.d(TAG, "keyguard host is null, creating it...");
 
@@ -116,18 +119,22 @@
             lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
             lp.windowAnimations = com.android.internal.R.style.Animation_LockScreen;
 
-            // TODO: Sometimes we get the wrong value for the sensor resource we use to configure
-            // this.  However, the current UI design has LockScreen always respond to orientation so
-            // we don't need this for the time-being.
-            //
-            // For reference, the configuration variable is R.bool.config_enableLockScreenRotation
-            lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR;
             lp.setTitle("Keyguard");
             mWindowLayoutParams = lp;
 
             mViewManager.addView(mKeyguardHost, lp);
         }
 
+        if (enableScreenRotation) {
+            Log.d(TAG, "Rotation sensor for lock screen On!");
+            mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR;
+        } else {
+            Log.d(TAG, "Rotation sensor for lock screen Off!");
+            mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
+        }
+
+        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
+
         if (mKeyguardView == null) {
             if (DEBUG) Log.d(TAG, "keyguard view is null, creating it...");
             mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mUpdateMonitor, this);
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 6eaba21..d2c0709 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -781,8 +781,9 @@
         // Determine whether the status bar can hide based on the size
         // of the screen.  We assume sizes > 600dp are tablets where we
         // will use the system bar.
-        int shortSizeDp = (shortSize*DisplayMetrics.DENSITY_DEVICE)
-                / DisplayMetrics.DENSITY_DEFAULT;
+        int shortSizeDp = shortSize
+                * DisplayMetrics.DENSITY_DEFAULT
+                / DisplayMetrics.DENSITY_DEVICE;
         mStatusBarCanHide = shortSizeDp < 600;
         mStatusBarHeight = mContext.getResources().getDimensionPixelSize(
                 mStatusBarCanHide
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 35e08d4..6b3046f 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -5376,7 +5376,8 @@
 }
 
 void MultiTouchInputMapper::clearState() {
-    mAccumulator.clear(mSlotCount);
+    mAccumulator.clearSlots(mSlotCount);
+    mAccumulator.clearButtons();
     mButtonState = 0;
 }
 
@@ -5410,13 +5411,13 @@
         }
 
         if (mAccumulator.currentSlot < 0 || size_t(mAccumulator.currentSlot) >= mSlotCount) {
-            if (newSlot) {
 #if DEBUG_POINTERS
+            if (newSlot) {
                 LOGW("MultiTouch device %s emitted invalid slot index %d but it "
                         "should be between 0 and %d; ignoring this slot.",
                         getDeviceName().string(), mAccumulator.currentSlot, mSlotCount);
-#endif
             }
+#endif
             break;
         }
 
@@ -5619,7 +5620,10 @@
 
     syncTouch(when, havePointerIds);
 
-    mAccumulator.clear(mUsingSlotsProtocol ? 0 : mSlotCount);
+    if (!mUsingSlotsProtocol) {
+        mAccumulator.clearSlots(mSlotCount);
+    }
+    mAccumulator.clearButtons();
 }
 
 void MultiTouchInputMapper::configureRawAxes() {
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index 671e194..fa23786 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -1243,8 +1243,7 @@
         uint32_t buttonDown;
         uint32_t buttonUp;
 
-        Accumulator() : slots(NULL) {
-            clear(false);
+        Accumulator() : currentSlot(0), slots(NULL), buttonDown(0), buttonUp(0) {
         }
 
         ~Accumulator() {
@@ -1255,11 +1254,14 @@
             slots = new Slot[slotCount];
         }
 
-        void clear(size_t slotCount) {
+        void clearSlots(size_t slotCount) {
             for (size_t i = 0; i < slotCount; i++) {
                 slots[i].clear();
             }
             currentSlot = 0;
+        }
+
+        void clearButtons() {
             buttonDown = 0;
             buttonUp = 0;
         }
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 5f52056..82e5e80 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -3690,12 +3690,12 @@
                     + processName + " with config " + mConfiguration);
             ApplicationInfo appInfo = app.instrumentationInfo != null
                     ? app.instrumentationInfo : app.info;
+            app.compat = compatibilityInfoForPackageLocked(appInfo);
             thread.bindApplication(processName, appInfo, providers,
                     app.instrumentationClass, app.instrumentationProfileFile,
                     app.instrumentationArguments, app.instrumentationWatcher, testMode, 
                     isRestrictedBackupMode || !normalMode,
-                    mConfiguration, compatibilityInfoForPackageLocked(appInfo),
-                    getCommonServicesLocked(),
+                    mConfiguration, app.compat, getCommonServicesLocked(),
                     mCoreSettingsObserver.getCoreSettingsLocked());
             updateLruProcessLocked(app, false, true);
             app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
@@ -11158,13 +11158,11 @@
         // Special case for adding a package: by default turn on compatibility
         // mode.
         } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
-            if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
-                Uri data = intent.getData();
-                String ssp;
-                if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
-                    mCompatModePackages.setPackageScreenCompatModeLocked(ssp,
-                            ActivityManager.COMPAT_MODE_ENABLED);
-                }
+            Uri data = intent.getData();
+            String ssp;
+            if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
+                mCompatModePackages.handlePackageAddedLocked(ssp,
+                        intent.getBooleanExtra(Intent.EXTRA_REPLACING, false));
             }
         }
 
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index cc9e78e..090e26b 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -24,6 +24,7 @@
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.os.Build;
@@ -79,6 +80,7 @@
     long startTime;         // last time this activity was started
     long cpuTimeAtResume;   // the cpu time of host process at the time of resuming activity
     Configuration configuration; // configuration activity was last running in
+    CompatibilityInfo compat;// last used compatibility mode
     ActivityRecord resultTo; // who started this entry, so will get our reply
     final String resultWho; // additional identifier for use by resultTo.
     final int requestCode;  // code given by requester (resultTo)
@@ -137,6 +139,7 @@
                 pw.print(" componentSpecified="); pw.print(componentSpecified);
                 pw.print(" isHomeActivity="); pw.println(isHomeActivity);
         pw.print(prefix); pw.print("config="); pw.println(configuration);
+        pw.print(prefix); pw.print("compat="); pw.println(compat);
         if (resultTo != null || resultWho != null) {
             pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
                     pw.print(" resultWho="); pw.print(resultWho);
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index af69307..f9be46f 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -549,10 +549,10 @@
             r.sleeping = false;
             r.forceNewConfig = false;
             showAskCompatModeDialogLocked(r);
+            r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
             app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
                     System.identityHashCode(r),
-                    r.info, mService.compatibilityInfoForPackageLocked(r.info.applicationInfo),
-                    r.icicle, results, newIntents, !andResume,
+                    r.info, r.compat, r.icicle, results, newIntents, !andResume,
                     mService.isNextTransitionForward());
             
             if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
diff --git a/services/java/com/android/server/am/CompatModePackages.java b/services/java/com/android/server/am/CompatModePackages.java
index 1277bca..8949f48 100644
--- a/services/java/com/android/server/am/CompatModePackages.java
+++ b/services/java/com/android/server/am/CompatModePackages.java
@@ -17,6 +17,7 @@
 
 import android.app.ActivityManager;
 import android.app.AppGlobals;
+import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.res.CompatibilityInfo;
@@ -117,15 +118,48 @@
         return flags != null ? flags : 0;
     }
 
+    public void handlePackageAddedLocked(String packageName, boolean updated) {
+        ApplicationInfo ai = null;
+        try {
+            ai = AppGlobals.getPackageManager().getApplicationInfo(packageName, 0);
+        } catch (RemoteException e) {
+        }
+        if (ai == null) {
+            return;
+        }
+        CompatibilityInfo ci = compatibilityInfoForPackageLocked(ai);
+        final boolean mayCompat = !ci.alwaysSupportsScreen()
+                && !ci.neverSupportsScreen();
+
+        if (!updated) {
+            // First time -- if the app may run in compat mode, enable that
+            // by default.
+            if (mayCompat) {
+                setPackageScreenCompatModeLocked(ai, ActivityManager.COMPAT_MODE_ENABLED);
+            }
+        } else {
+            // Update -- if the app no longer can run in compat mode, clear
+            // any current settings for it.
+            if (!mayCompat && mPackages.containsKey(packageName)) {
+                mPackages.remove(packageName);
+                mHandler.removeMessages(MSG_WRITE);
+                Message msg = mHandler.obtainMessage(MSG_WRITE);
+                mHandler.sendMessageDelayed(msg, 10000);
+            }
+        }
+    }
+
     public CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) {
         return new CompatibilityInfo(ai, mService.mConfiguration.screenLayout,
+                mService.mConfiguration.smallestScreenWidthDp,
                 (getPackageFlags(ai.packageName)&COMPAT_FLAG_ENABLED) != 0);
     }
 
     public int computeCompatModeLocked(ApplicationInfo ai) {
         boolean enabled = (getPackageFlags(ai.packageName)&COMPAT_FLAG_ENABLED) != 0;
         CompatibilityInfo info = new CompatibilityInfo(ai,
-                mService.mConfiguration.screenLayout, enabled);
+                mService.mConfiguration.screenLayout,
+                mService.mConfiguration.smallestScreenWidthDp, enabled);
         if (info.alwaysSupportsScreen()) {
             return ActivityManager.COMPAT_MODE_NEVER;
         }
@@ -240,28 +274,47 @@
             newFlags &= ~COMPAT_FLAG_ENABLED;
         }
 
+        CompatibilityInfo ci = compatibilityInfoForPackageLocked(ai);
+        if (ci.alwaysSupportsScreen()) {
+            Slog.w(TAG, "Ignoring compat mode change of " + packageName
+                    + "; compatibility never needed");
+            newFlags = 0;
+        }
+        if (ci.neverSupportsScreen()) {
+            Slog.w(TAG, "Ignoring compat mode change of " + packageName
+                    + "; compatibility always needed");
+            newFlags = 0;
+        }
+
         if (newFlags != curFlags) {
             if (newFlags != 0) {
                 mPackages.put(packageName, newFlags);
             } else {
                 mPackages.remove(packageName);
             }
-            CompatibilityInfo ci = compatibilityInfoForPackageLocked(ai);
-            if (ci.alwaysSupportsScreen()) {
-                Slog.w(TAG, "Ignoring compat mode change of " + packageName
-                        + "; compatibility never needed");
-                return;
-            }
-            if (ci.neverSupportsScreen()) {
-                Slog.w(TAG, "Ignoring compat mode change of " + packageName
-                        + "; compatibility always needed");
-                return;
-            }
+
+            // Need to get compatibility info in new state.
+            ci = compatibilityInfoForPackageLocked(ai);
 
             mHandler.removeMessages(MSG_WRITE);
             Message msg = mHandler.obtainMessage(MSG_WRITE);
             mHandler.sendMessageDelayed(msg, 10000);
 
+            ActivityRecord starting = mService.mMainStack.topRunningActivityLocked(null);
+
+            // All activities that came from the package must be
+            // restarted as if there was a config change.
+            for (int i=mService.mMainStack.mHistory.size()-1; i>=0; i--) {
+                ActivityRecord a = (ActivityRecord)mService.mMainStack.mHistory.get(i);
+                if (a.info.packageName.equals(packageName)) {
+                    a.forceNewConfig = true;
+                    if (starting != null && a == starting && a.visible) {
+                        a.startFreezingScreenLocked(starting.app,
+                                ActivityInfo.CONFIG_SCREEN_LAYOUT);
+                    }
+                }
+            }
+
             // Tell all processes that loaded this package about the change.
             for (int i=mService.mLruProcesses.size()-1; i>=0; i--) {
                 ProcessRecord app = mService.mLruProcesses.get(i);
@@ -278,16 +331,6 @@
                 }
             }
 
-            // All activities that came from the packge must be
-            // restarted as if there was a config change.
-            for (int i=mService.mMainStack.mHistory.size()-1; i>=0; i--) {
-                ActivityRecord a = (ActivityRecord)mService.mMainStack.mHistory.get(i);
-                if (a.info.packageName.equals(packageName)) {
-                    a.forceNewConfig = true;
-                }
-            }
-
-            ActivityRecord starting = mService.mMainStack.topRunningActivityLocked(null);
             if (starting != null) {
                 mService.mMainStack.ensureActivityConfigurationLocked(starting, 0);
                 // And we need to make sure at this point that all other activities
@@ -315,6 +358,7 @@
 
             final IPackageManager pm = AppGlobals.getPackageManager();
             final int screenLayout = mService.mConfiguration.screenLayout;
+            final int smallestScreenWidthDp = mService.mConfiguration.smallestScreenWidthDp;
             final Iterator<Map.Entry<String, Integer>> it = pkgs.entrySet().iterator();
             while (it.hasNext()) {
                 Map.Entry<String, Integer> entry = it.next();
@@ -331,7 +375,8 @@
                 if (ai == null) {
                     continue;
                 }
-                CompatibilityInfo info = new CompatibilityInfo(ai, screenLayout, false);
+                CompatibilityInfo info = new CompatibilityInfo(ai, screenLayout,
+                        smallestScreenWidthDp, false);
                 if (info.alwaysSupportsScreen()) {
                     continue;
                 }
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index beef136..3968f66 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -71,6 +71,7 @@
     IBinder forcingToForeground;// Token that is forcing this process to be foreground
     int adjSeq;                 // Sequence id for identifying oom_adj assignment cycles
     int lruSeq;                 // Sequence id for identifying LRU update cycles
+    CompatibilityInfo compat;   // last used compatibility mode
     ComponentName instrumentationClass;// class installed to instrument app
     ApplicationInfo instrumentationInfo; // the application being instrumented
     String instrumentationProfileFile; // where to save profiling
@@ -147,6 +148,7 @@
                 pw.print(" publicDir="); pw.print(info.publicSourceDir);
                 pw.print(" data="); pw.println(info.dataDir);
         pw.print(prefix); pw.print("packageList="); pw.println(pkgList);
+        pw.print(prefix); pw.print("compat="); pw.println(compat);
         if (instrumentationClass != null || instrumentationProfileFile != null
                 || instrumentationArguments != null) {
             pw.print(prefix); pw.print("instrumentationClass=");
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index bb01633..b01ddd3 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -69,7 +69,7 @@
         mContext = context;
         mDisplay = display;
 
-        display.getMetrics(mDisplayMetrics);
+        display.getRealMetrics(mDisplayMetrics);
 
         Bitmap screenshot = Surface.screenshot(0, 0);
 
@@ -244,7 +244,7 @@
                 break;
         }
 
-        mDisplay.getMetrics(mDisplayMetrics);
+        mDisplay.getRealMetrics(mDisplayMetrics);
 
         // Initialize the animations.  This is a hack, redefining what "parent"
         // means to allow supplying the last and next size.  In this definition
diff --git a/services/java/com/android/server/wm/StrictModeFlash.java b/services/java/com/android/server/wm/StrictModeFlash.java
index 2c62080..71b5952 100644
--- a/services/java/com/android/server/wm/StrictModeFlash.java
+++ b/services/java/com/android/server/wm/StrictModeFlash.java
@@ -39,7 +39,7 @@
 
     public StrictModeFlash(Display display, SurfaceSession session) {
         final DisplayMetrics dm = new DisplayMetrics();
-        display.getMetrics(dm);
+        display.getRealMetrics(dm);
 
         try {
             mSurface = new Surface(session, 0, "StrictModeFlash", -1, 1, 1, PixelFormat.TRANSLUCENT, 0);
diff --git a/services/java/com/android/server/wm/Watermark.java b/services/java/com/android/server/wm/Watermark.java
index 22126f3..375abe5 100644
--- a/services/java/com/android/server/wm/Watermark.java
+++ b/services/java/com/android/server/wm/Watermark.java
@@ -52,7 +52,7 @@
 
     Watermark(Display display, SurfaceSession session, String[] tokens) {
         final DisplayMetrics dm = new DisplayMetrics();
-        display.getMetrics(dm);
+        display.getRealMetrics(dm);
 
         if (false) {
             Log.i(WindowManagerService.TAG, "*********************** WATERMARK");
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
index 57a3b15..ba3e6e5 100644
--- a/services/sensorservice/Android.mk
+++ b/services/sensorservice/Android.mk
@@ -8,7 +8,6 @@
     LinearAccelerationSensor.cpp \
     OrientationSensor.cpp \
     RotationVectorSensor.cpp \
-    SecondOrderLowPassFilter.cpp \
     SensorDevice.cpp \
     SensorFusion.cpp \
     SensorInterface.cpp \
diff --git a/services/sensorservice/CorrectedGyroSensor.cpp b/services/sensorservice/CorrectedGyroSensor.cpp
index 9b75b70..1857443 100644
--- a/services/sensorservice/CorrectedGyroSensor.cpp
+++ b/services/sensorservice/CorrectedGyroSensor.cpp
@@ -45,7 +45,7 @@
         const sensors_event_t& event)
 {
     if (event.type == SENSOR_TYPE_GYROSCOPE) {
-        const vec3_t bias(mSensorFusion.getGyroBias() * mSensorFusion.getEstimatedRate());
+        const vec3_t bias(mSensorFusion.getGyroBias());
         *outEvent = event;
         outEvent->data[0] -= bias.x;
         outEvent->data[1] -= bias.y;
diff --git a/services/sensorservice/Fusion.cpp b/services/sensorservice/Fusion.cpp
index 56ac9f9..b5f97e0 100644
--- a/services/sensorservice/Fusion.cpp
+++ b/services/sensorservice/Fusion.cpp
@@ -24,15 +24,14 @@
 
 // -----------------------------------------------------------------------
 
-template <typename TYPE>
-static inline TYPE sqr(TYPE x) {
-    return x*x;
-}
+static const float gyroSTDEV = 3.16e-4; // rad/s^3/2
+static const float accSTDEV  = 0.05f;   // m/s^2 (measured 0.08 / CDD 0.05)
+static const float magSTDEV  = 0.5f;    // uT    (measured 0.7  / CDD 0.5)
+static const float biasSTDEV = 3.16e-5; // rad/s^1/2 (guessed)
 
-template <typename T>
-static inline T clamp(T v) {
-    return v < 0 ? 0 : v;
-}
+static const float FREE_FALL_THRESHOLD = 0.981f;
+
+// -----------------------------------------------------------------------
 
 template <typename TYPE, size_t C, size_t R>
 static mat<TYPE, R, R> scaleCovariance(
@@ -71,33 +70,6 @@
     return r;
 }
 
-template <typename TYPE>
-static mat<TYPE, 3, 3> MRPsToMatrix(const vec<TYPE, 3>& p) {
-    mat<TYPE, 3, 3> res(1);
-    const mat<TYPE, 3, 3> px(crossMatrix(p, 0));
-    const TYPE ptp(dot_product(p,p));
-    const TYPE t = 4/sqr(1+ptp);
-    res -= t * (1-ptp) * px;
-    res += t * 2 * sqr(px);
-    return res;
-}
-
-template <typename TYPE>
-vec<TYPE, 3> matrixToMRPs(const mat<TYPE, 3, 3>& R) {
-    // matrix to MRPs
-    vec<TYPE, 3> q;
-    const float Hx = R[0].x;
-    const float My = R[1].y;
-    const float Az = R[2].z;
-    const float w = 1 / (1 + sqrtf( clamp( Hx + My + Az + 1) * 0.25f ));
-    q.x = sqrtf( clamp( Hx - My - Az + 1) * 0.25f ) * w;
-    q.y = sqrtf( clamp(-Hx + My - Az + 1) * 0.25f ) * w;
-    q.z = sqrtf( clamp(-Hx - My + Az + 1) * 0.25f ) * w;
-    q.x = copysignf(q.x, R[2].y - R[1].z);
-    q.y = copysignf(q.y, R[0].z - R[2].x);
-    q.z = copysignf(q.z, R[1].x - R[0].y);
-    return q;
-}
 
 template<typename TYPE, size_t SIZE>
 class Covariance {
@@ -128,11 +100,8 @@
 // -----------------------------------------------------------------------
 
 Fusion::Fusion() {
-    // process noise covariance matrix
-    const float w1 = gyroSTDEV;
-    const float w2 = biasSTDEV;
-    Q[0] = w1*w1;
-    Q[1] = w2*w2;
+    Phi[0][1] = 0;
+    Phi[1][1] = 1;
 
     Ba.x = 0;
     Ba.y = 0;
@@ -146,25 +115,46 @@
 }
 
 void Fusion::init() {
-    // initial estimate: E{ x(t0) }
-    x = 0;
-
-    // initial covariance: Var{ x(t0) }
-    P = 0;
-
     mInitState = 0;
+    mGyroRate = 0;
     mCount[0] = 0;
     mCount[1] = 0;
     mCount[2] = 0;
     mData = 0;
 }
 
+void Fusion::initFusion(const vec4_t& q, float dT)
+{
+    // initial estimate: E{ x(t0) }
+    x0 = q;
+    x1 = 0;
+
+    // process noise covariance matrix
+    //  G = | -1 0 |
+    //      |  0 1 |
+
+    const float v = gyroSTDEV;
+    const float u = biasSTDEV;
+    const float q00 = v*v*dT + 0.33333f*(dT*dT*dT)*u*u;
+    const float q10 =              0.5f*(dT*dT)   *u*u;
+    const float q01 = q10;
+    const float q11 = u*u*dT;
+    GQGt[0][0] =  q00;
+    GQGt[1][0] = -q10;
+    GQGt[0][1] = -q01;
+    GQGt[1][1] =  q11;
+
+
+    // initial covariance: Var{ x(t0) }
+    P = 0;
+}
+
 bool Fusion::hasEstimate() const {
     return (mInitState == (MAG|ACC|GYRO));
 }
 
-bool Fusion::checkInitComplete(int what, const vec3_t& d) {
-    if (mInitState == (MAG|ACC|GYRO))
+bool Fusion::checkInitComplete(int what, const vec3_t& d, float dT) {
+    if (hasEstimate())
         return true;
 
     if (what == ACC) {
@@ -176,7 +166,8 @@
         mCount[1]++;
         mInitState |= MAG;
     } else if (what == GYRO) {
-        mData[2] += d;
+        mGyroRate = dT;
+        mData[2] += d*dT;
         mCount[2]++;
         if (mCount[2] == 64) {
             // 64 samples is good enough to estimate the gyro drift and
@@ -199,37 +190,29 @@
         east *= 1/length(east);
         vec3_t north(cross_product(up, east));
         R << east << north << up;
-        x[0] = matrixToMRPs(R);
+        const vec4_t q = matrixToQuat(R);
 
-        // NOTE: we could try to use the average of the gyro data
-        // to estimate the initial bias, but this only works if
-        // the device is not moving. For now, we don't use that value
-        // and start with a bias of 0.
-        x[1] = 0;
-
-        // initial covariance
-        P = 0;
+        initFusion(q, mGyroRate);
     }
 
     return false;
 }
 
 void Fusion::handleGyro(const vec3_t& w, float dT) {
-    const vec3_t wdT(w * dT);   // rad/s * s -> rad
-    if (!checkInitComplete(GYRO, wdT))
+    if (!checkInitComplete(GYRO, w, dT))
         return;
 
-    predict(wdT);
+    predict(w, dT);
 }
 
 status_t Fusion::handleAcc(const vec3_t& a) {
-    if (length(a) < 0.981f)
+    // ignore acceleration data if we're close to free-fall
+    if (length(a) < FREE_FALL_THRESHOLD)
         return BAD_VALUE;
 
     if (!checkInitComplete(ACC, a))
         return BAD_VALUE;
 
-    // ignore acceleration data if we're close to free-fall
     const float l = 1/length(a);
     update(a*l, Ba, accSTDEV*l);
     return NO_ERROR;
@@ -251,20 +234,6 @@
     const float l = 1 / length(north);
     north *= l;
 
-#if 0
-    // in practice the magnetic-field sensor is so wrong
-    // that there is no point trying to use it to constantly
-    // correct the gyro. instead, we use the mag-sensor only when
-    // the device points north (just to give us a reference).
-    // We're hoping that it'll actually point north, if it doesn't
-    // we'll be offset, but at least the instantaneous posture
-    // of the device will be correct.
-
-    const float cos_30 = 0.8660254f;
-    if (dot_product(north, Bm) < cos_30)
-        return BAD_VALUE;
-#endif
-
     update(north, Bm, magSTDEV*l);
     return NO_ERROR;
 }
@@ -273,7 +242,7 @@
     if (isnanf(length(v))) {
         LOGW("9-axis fusion diverged. reseting state.");
         P = 0;
-        x[1] = 0;
+        x1 = 0;
         mInitState = 0;
         mCount[0] = 0;
         mCount[1] = 0;
@@ -284,145 +253,89 @@
     return true;
 }
 
-vec3_t Fusion::getAttitude() const {
-    return x[0];
+vec4_t Fusion::getAttitude() const {
+    return x0;
 }
 
 vec3_t Fusion::getBias() const {
-    return x[1];
+    return x1;
 }
 
 mat33_t Fusion::getRotationMatrix() const {
-    return MRPsToMatrix(x[0]);
+    return quatToMatrix(x0);
 }
 
-mat33_t Fusion::getF(const vec3_t& p) {
-    const float p0 = p.x;
-    const float p1 = p.y;
-    const float p2 = p.z;
-
-    // f(p, w)
-    const float p0p1 = p0*p1;
-    const float p0p2 = p0*p2;
-    const float p1p2 = p1*p2;
-    const float p0p0 = p0*p0;
-    const float p1p1 = p1*p1;
-    const float p2p2 = p2*p2;
-    const float pp = 0.5f * (1 - (p0p0 + p1p1 + p2p2));
-
-    mat33_t F;
-    F[0][0] = 0.5f*(p0p0 + pp);
-    F[0][1] = 0.5f*(p0p1 + p2);
-    F[0][2] = 0.5f*(p0p2 - p1);
-    F[1][0] = 0.5f*(p0p1 - p2);
-    F[1][1] = 0.5f*(p1p1 + pp);
-    F[1][2] = 0.5f*(p1p2 + p0);
-    F[2][0] = 0.5f*(p0p2 + p1);
-    F[2][1] = 0.5f*(p1p2 - p0);
-    F[2][2] = 0.5f*(p2p2 + pp);
+mat34_t Fusion::getF(const vec4_t& q) {
+    mat34_t F;
+    F[0].x = q.w;   F[1].x =-q.z;   F[2].x = q.y;
+    F[0].y = q.z;   F[1].y = q.w;   F[2].y =-q.x;
+    F[0].z =-q.y;   F[1].z = q.x;   F[2].z = q.w;
+    F[0].w =-q.x;   F[1].w =-q.y;   F[2].w =-q.z;
     return F;
 }
 
-mat33_t Fusion::getdFdp(const vec3_t& p, const vec3_t& we) {
+void Fusion::predict(const vec3_t& w, float dT) {
+    const vec4_t q  = x0;
+    const vec3_t b  = x1;
+    const vec3_t we = w - b;
+    const vec4_t dq = getF(q)*((0.5f*dT)*we);
+    x0 = normalize_quat(q + dq);
 
-    // dF = | A = df/dp  -F |
-    //      |   0         0 |
+    // P(k+1) = F*P(k)*Ft + G*Q*Gt
 
-    mat33_t A;
-    A[0][0] = A[1][1] = A[2][2] = 0.5f * (p.x*we.x + p.y*we.y + p.z*we.z);
-    A[0][1] = 0.5f * (p.y*we.x - p.x*we.y - we.z);
-    A[0][2] = 0.5f * (p.z*we.x - p.x*we.z + we.y);
-    A[1][2] = 0.5f * (p.z*we.y - p.y*we.z - we.x);
-    A[1][0] = -A[0][1];
-    A[2][0] = -A[0][2];
-    A[2][1] = -A[1][2];
-    return A;
-}
+    //  Phi = | Phi00 Phi10 |
+    //        |   0     1   |
+    const mat33_t I33(1);
+    const mat33_t I33dT(dT);
+    const mat33_t wx(crossMatrix(we, 0));
+    const mat33_t wx2(wx*wx);
+    const float lwedT = length(we)*dT;
+    const float ilwe = 1/length(we);
+    const float k0 = (1-cosf(lwedT))*(ilwe*ilwe);
+    const float k1 = sinf(lwedT);
 
-void Fusion::predict(const vec3_t& w) {
-    // f(p, w)
-    vec3_t& p(x[0]);
+    Phi[0][0] = I33 - wx*(k1*ilwe) + wx2*k0;
+    Phi[1][0] = wx*k0 - I33dT - wx2*(ilwe*ilwe*ilwe)*(lwedT-k1);
 
-    // There is a discontinuity at 2.pi, to avoid it we need to switch to
-    // the shadow of p when pT.p gets too big.
-    const float ptp(dot_product(p,p));
-    if (ptp >= 2.0f) {
-        p = -p * (1/ptp);
-    }
-
-    const mat33_t F(getF(p));
-
-    // compute w with the bias correction:
-    //  w_estimated = w - b_estimated
-    const vec3_t& b(x[1]);
-    const vec3_t we(w - b);
-
-    // prediction
-    const vec3_t dX(F*we);
-
-    if (!checkState(dX))
-        return;
-
-    p += dX;
-
-    const mat33_t A(getdFdp(p, we));
-
-    // G  = | G0  0 |  =  | -F  0 |
-    //      |  0  1 |     |  0  1 |
-
-    // P += A*P + P*At + F*Q*Ft
-    const mat33_t AP(A*transpose(P[0][0]));
-    const mat33_t PAt(P[0][0]*transpose(A));
-    const mat33_t FPSt(F*transpose(P[1][0]));
-    const mat33_t PSFt(P[1][0]*transpose(F));
-    const mat33_t FQFt(scaleCovariance(F, Q[0]));
-    P[0][0] += AP + PAt - FPSt - PSFt + FQFt;
-    P[1][0] += A*P[1][0] - F*P[1][1];
-    P[1][1] += Q[1];
+    P = Phi*P*transpose(Phi) + GQGt;
 }
 
 void Fusion::update(const vec3_t& z, const vec3_t& Bi, float sigma) {
-    const vec3_t p(x[0]);
+    vec4_t q(x0);
     // measured vector in body space: h(p) = A(p)*Bi
-    const mat33_t A(MRPsToMatrix(p));
+    const mat33_t A(quatToMatrix(q));
     const vec3_t Bb(A*Bi);
 
     // Sensitivity matrix H = dh(p)/dp
     // H = [ L 0 ]
-    const float ptp(dot_product(p,p));
-    const mat33_t px(crossMatrix(p, 0.5f*(ptp-1)));
-    const mat33_t ppt(p*transpose(p));
-    const mat33_t L((8 / sqr(1+ptp))*crossMatrix(Bb, 0)*(ppt-px));
+    const mat33_t L(crossMatrix(Bb, 0));
 
-    // update...
+    // gain...
+    // K = P*Ht / [H*P*Ht + R]
+    vec<mat33_t, 2> K;
     const mat33_t R(sigma*sigma);
     const mat33_t S(scaleCovariance(L, P[0][0]) + R);
     const mat33_t Si(invert(S));
     const mat33_t LtSi(transpose(L)*Si);
-
-    vec<mat33_t, 2> K;
     K[0] = P[0][0] * LtSi;
     K[1] = transpose(P[1][0])*LtSi;
 
-    const vec3_t e(z - Bb);
-    const vec3_t K0e(K[0]*e);
-    const vec3_t K1e(K[1]*e);
-
-    if (!checkState(K0e))
-        return;
-
-    if (!checkState(K1e))
-        return;
-
-    x[0] += K0e;
-    x[1] += K1e;
-
+    // update...
     // P -= K*H*P;
     const mat33_t K0L(K[0] * L);
     const mat33_t K1L(K[1] * L);
     P[0][0] -= K0L*P[0][0];
     P[1][1] -= K1L*P[1][0];
     P[1][0] -= K0L*P[1][0];
+    P[0][1] = transpose(P[1][0]);
+
+    const vec3_t e(z - Bb);
+    const vec3_t dq(K[0]*e);
+    const vec3_t db(K[1]*e);
+
+    q += getF(q)*(0.5f*dq);
+    x0 = normalize_quat(q);
+    x1 += db;
 }
 
 // -----------------------------------------------------------------------
diff --git a/services/sensorservice/Fusion.h b/services/sensorservice/Fusion.h
index 571a415..556944b 100644
--- a/services/sensorservice/Fusion.h
+++ b/services/sensorservice/Fusion.h
@@ -19,42 +19,39 @@
 
 #include <utils/Errors.h>
 
-#include "vec.h"
+#include "quat.h"
 #include "mat.h"
+#include "vec.h"
 
 namespace android {
 
+typedef mat<float, 3, 4> mat34_t;
+
 class Fusion {
     /*
      * the state vector is made of two sub-vector containing respectively:
      * - modified Rodrigues parameters
      * - the estimated gyro bias
      */
-    vec<vec3_t, 2> x;
+    quat_t  x0;
+    vec3_t  x1;
 
     /*
      * the predicated covariance matrix is made of 4 3x3 sub-matrices and it
      * semi-definite positive.
      *
      * P = | P00  P10 | = | P00  P10 |
-     *     | P01  P11 |   | P10t  Q1 |
+     *     | P01  P11 |   | P10t P11 |
      *
      * Since P01 = transpose(P10), the code below never calculates or
-     * stores P01. P11 is always equal to Q1, so we don't store it either.
+     * stores P01.
      */
     mat<mat33_t, 2, 2> P;
 
     /*
-     * the process noise covariance matrix is made of 2 3x3 sub-matrices
-     * Q0 encodes the attitude's noise
-     * Q1 encodes the bias' noise
+     * the process noise covariance matrix
      */
-    vec<mat33_t, 2> Q;
-
-    static const float gyroSTDEV = 1.0e-5;  // rad/s (measured 1.2e-5)
-    static const float accSTDEV  = 0.05f;   // m/s^2 (measured 0.08 / CDD 0.05)
-    static const float magSTDEV  = 0.5f;    // uT    (measured 0.7  / CDD 0.5)
-    static const float biasSTDEV = 2e-9;    // rad/s^2 (guessed)
+    mat<mat33_t, 2, 2> GQGt;
 
 public:
     Fusion();
@@ -62,23 +59,25 @@
     void handleGyro(const vec3_t& w, float dT);
     status_t handleAcc(const vec3_t& a);
     status_t handleMag(const vec3_t& m);
-    vec3_t getAttitude() const;
+    vec4_t getAttitude() const;
     vec3_t getBias() const;
     mat33_t getRotationMatrix() const;
     bool hasEstimate() const;
 
 private:
+    mat<mat33_t, 2, 2> Phi;
     vec3_t Ba, Bm;
     uint32_t mInitState;
+    float mGyroRate;
     vec<vec3_t, 3> mData;
     size_t mCount[3];
     enum { ACC=0x1, MAG=0x2, GYRO=0x4 };
-    bool checkInitComplete(int, const vec3_t&);
+    bool checkInitComplete(int, const vec3_t& w, float d = 0);
+    void initFusion(const vec4_t& q0, float dT);
     bool checkState(const vec3_t& v);
-    void predict(const vec3_t& w);
+    void predict(const vec3_t& w, float dT);
     void update(const vec3_t& z, const vec3_t& Bi, float sigma);
-    static mat33_t getF(const vec3_t& p);
-    static mat33_t getdFdp(const vec3_t& p, const vec3_t& we);
+    static mat34_t getF(const vec4_t& p);
 };
 
 }; // namespace android
diff --git a/services/sensorservice/GravitySensor.cpp b/services/sensorservice/GravitySensor.cpp
index 541fad2..c57715f 100644
--- a/services/sensorservice/GravitySensor.cpp
+++ b/services/sensorservice/GravitySensor.cpp
@@ -31,10 +31,7 @@
 
 GravitySensor::GravitySensor(sensor_t const* list, size_t count)
     : mSensorDevice(SensorDevice::getInstance()),
-      mSensorFusion(SensorFusion::getInstance()),
-      mAccTime(0),
-      mLowPass(M_SQRT1_2, 1.5f),
-      mX(mLowPass), mY(mLowPass), mZ(mLowPass)
+      mSensorFusion(SensorFusion::getInstance())
 {
     for (size_t i=0 ; i<count ; i++) {
         if (list[i].type == SENSOR_TYPE_ACCELEROMETER) {
@@ -50,30 +47,14 @@
     const static double NS2S = 1.0 / 1000000000.0;
     if (event.type == SENSOR_TYPE_ACCELEROMETER) {
         vec3_t g;
-        if (mSensorFusion.hasGyro()) {
-            if (!mSensorFusion.hasEstimate())
-                return false;
-            const mat33_t R(mSensorFusion.getRotationMatrix());
-            // FIXME: we need to estimate the length of gravity because
-            // the accelerometer may have a small scaling error. This
-            // translates to an offset in the linear-acceleration sensor.
-            g = R[2] * GRAVITY_EARTH;
-        } else {
-            const double now = event.timestamp * NS2S;
-            if (mAccTime == 0) {
-                g.x = mX.init(event.acceleration.x);
-                g.y = mY.init(event.acceleration.y);
-                g.z = mZ.init(event.acceleration.z);
-            } else {
-                double dT = now - mAccTime;
-                mLowPass.setSamplingPeriod(dT);
-                g.x = mX(event.acceleration.x);
-                g.y = mY(event.acceleration.y);
-                g.z = mZ(event.acceleration.z);
-            }
-            g *= (GRAVITY_EARTH / length(g));
-            mAccTime = now;
-        }
+        if (!mSensorFusion.hasEstimate())
+            return false;
+        const mat33_t R(mSensorFusion.getRotationMatrix());
+        // FIXME: we need to estimate the length of gravity because
+        // the accelerometer may have a small scaling error. This
+        // translates to an offset in the linear-acceleration sensor.
+        g = R[2] * GRAVITY_EARTH;
+
         *outEvent = event;
         outEvent->data[0] = g.x;
         outEvent->data[1] = g.y;
@@ -86,42 +67,24 @@
 }
 
 status_t GravitySensor::activate(void* ident, bool enabled) {
-    status_t err;
-    if (mSensorFusion.hasGyro()) {
-        err = mSensorFusion.activate(this, enabled);
-    } else {
-        err = mSensorDevice.activate(this, mAccelerometer.getHandle(), enabled);
-        if (err == NO_ERROR) {
-            if (enabled) {
-                mAccTime = 0;
-            }
-        }
-    }
-    return err;
+    return mSensorFusion.activate(this, enabled);
 }
 
-status_t GravitySensor::setDelay(void* ident, int handle, int64_t ns)
-{
-    if (mSensorFusion.hasGyro()) {
-        return mSensorFusion.setDelay(this, ns);
-    } else {
-        return mSensorDevice.setDelay(this, mAccelerometer.getHandle(), ns);
-    }
+status_t GravitySensor::setDelay(void* ident, int handle, int64_t ns) {
+    return mSensorFusion.setDelay(this, ns);
 }
 
 Sensor GravitySensor::getSensor() const {
     sensor_t hwSensor;
     hwSensor.name       = "Gravity Sensor";
     hwSensor.vendor     = "Google Inc.";
-    hwSensor.version    = mSensorFusion.hasGyro() ? 3 : 2;
+    hwSensor.version    = 3;
     hwSensor.handle     = '_grv';
     hwSensor.type       = SENSOR_TYPE_GRAVITY;
     hwSensor.maxRange   = GRAVITY_EARTH * 2;
     hwSensor.resolution = mAccelerometer.getResolution();
-    hwSensor.power      = mSensorFusion.hasGyro() ?
-            mSensorFusion.getPowerUsage() : mAccelerometer.getPowerUsage();
-    hwSensor.minDelay   = mSensorFusion.hasGyro() ?
-            mSensorFusion.getMinDelay() : mAccelerometer.getMinDelay();
+    hwSensor.power      = mSensorFusion.getPowerUsage();
+    hwSensor.minDelay   = mSensorFusion.getMinDelay();
     Sensor sensor(&hwSensor);
     return sensor;
 }
diff --git a/services/sensorservice/GravitySensor.h b/services/sensorservice/GravitySensor.h
index 0ca3a3c..ac177c4 100644
--- a/services/sensorservice/GravitySensor.h
+++ b/services/sensorservice/GravitySensor.h
@@ -23,7 +23,6 @@
 #include <gui/Sensor.h>
 
 #include "SensorInterface.h"
-#include "SecondOrderLowPassFilter.h"
 
 // ---------------------------------------------------------------------------
 namespace android {
@@ -36,10 +35,6 @@
     SensorDevice& mSensorDevice;
     SensorFusion& mSensorFusion;
     Sensor mAccelerometer;
-    double mAccTime;
-
-    SecondOrderLowPassFilter mLowPass;
-    CascadedBiquadFilter<float> mX, mY, mZ;
 
 public:
     GravitySensor(sensor_t const* list, size_t count);
diff --git a/services/sensorservice/OrientationSensor.cpp b/services/sensorservice/OrientationSensor.cpp
index c9e5080..037adaa 100644
--- a/services/sensorservice/OrientationSensor.cpp
+++ b/services/sensorservice/OrientationSensor.cpp
@@ -50,9 +50,10 @@
                 g[0] += 360;
 
             *outEvent = event;
-            outEvent->data[0] = g.x;
-            outEvent->data[1] = g.y;
-            outEvent->data[2] = g.z;
+            outEvent->orientation.azimuth = g.x;
+            outEvent->orientation.pitch   = g.y;
+            outEvent->orientation.roll    = g.z;
+            outEvent->orientation.status  = SENSOR_STATUS_ACCURACY_HIGH;
             outEvent->sensor = '_ypr';
             outEvent->type = SENSOR_TYPE_ORIENTATION;
             return true;
diff --git a/services/sensorservice/RotationVectorSensor.cpp b/services/sensorservice/RotationVectorSensor.cpp
index cba89c9..5ea9568 100644
--- a/services/sensorservice/RotationVectorSensor.cpp
+++ b/services/sensorservice/RotationVectorSensor.cpp
@@ -27,11 +27,6 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-template <typename T>
-static inline T clamp(T v) {
-    return v < 0 ? 0 : v;
-}
-
 RotationVectorSensor::RotationVectorSensor()
     : mSensorDevice(SensorDevice::getInstance()),
       mSensorFusion(SensorFusion::getInstance())
@@ -43,29 +38,12 @@
 {
     if (event.type == SENSOR_TYPE_ACCELEROMETER) {
         if (mSensorFusion.hasEstimate()) {
-            const mat33_t R(mSensorFusion.getRotationMatrix());
-
-            // matrix to rotation vector (normalized quaternion)
-            const float Hx = R[0].x;
-            const float My = R[1].y;
-            const float Az = R[2].z;
-
-            float qw = sqrtf( clamp( Hx + My + Az + 1) * 0.25f );
-            float qx = sqrtf( clamp( Hx - My - Az + 1) * 0.25f );
-            float qy = sqrtf( clamp(-Hx + My - Az + 1) * 0.25f );
-            float qz = sqrtf( clamp(-Hx - My + Az + 1) * 0.25f );
-            qx = copysignf(qx, R[2].y - R[1].z);
-            qy = copysignf(qy, R[0].z - R[2].x);
-            qz = copysignf(qz, R[1].x - R[0].y);
-
-            // this quaternion is guaranteed to be normalized, by construction
-            // of the rotation matrix.
-
+            const vec4_t q(mSensorFusion.getAttitude());
             *outEvent = event;
-            outEvent->data[0] = qx;
-            outEvent->data[1] = qy;
-            outEvent->data[2] = qz;
-            outEvent->data[3] = qw;
+            outEvent->data[0] = q.x;
+            outEvent->data[1] = q.y;
+            outEvent->data[2] = q.z;
+            outEvent->data[3] = q.w;
             outEvent->sensor = '_rov';
             outEvent->type = SENSOR_TYPE_ROTATION_VECTOR;
             return true;
@@ -86,7 +64,7 @@
     sensor_t hwSensor;
     hwSensor.name       = "Rotation Vector Sensor";
     hwSensor.vendor     = "Google Inc.";
-    hwSensor.version    = mSensorFusion.hasGyro() ? 3 : 2;
+    hwSensor.version    = 3;
     hwSensor.handle     = '_rov';
     hwSensor.type       = SENSOR_TYPE_ROTATION_VECTOR;
     hwSensor.maxRange   = 1;
@@ -98,5 +76,54 @@
 }
 
 // ---------------------------------------------------------------------------
+
+GyroDriftSensor::GyroDriftSensor()
+    : mSensorDevice(SensorDevice::getInstance()),
+      mSensorFusion(SensorFusion::getInstance())
+{
+}
+
+bool GyroDriftSensor::process(sensors_event_t* outEvent,
+        const sensors_event_t& event)
+{
+    if (event.type == SENSOR_TYPE_ACCELEROMETER) {
+        if (mSensorFusion.hasEstimate()) {
+            const vec3_t b(mSensorFusion.getGyroBias());
+            *outEvent = event;
+            outEvent->data[0] = b.x;
+            outEvent->data[1] = b.y;
+            outEvent->data[2] = b.z;
+            outEvent->sensor = '_gbs';
+            outEvent->type = SENSOR_TYPE_ACCELEROMETER;
+            return true;
+        }
+    }
+    return false;
+}
+
+status_t GyroDriftSensor::activate(void* ident, bool enabled) {
+    return mSensorFusion.activate(this, enabled);
+}
+
+status_t GyroDriftSensor::setDelay(void* ident, int handle, int64_t ns) {
+    return mSensorFusion.setDelay(this, ns);
+}
+
+Sensor GyroDriftSensor::getSensor() const {
+    sensor_t hwSensor;
+    hwSensor.name       = "Gyroscope Bias (debug)";
+    hwSensor.vendor     = "Google Inc.";
+    hwSensor.version    = 1;
+    hwSensor.handle     = '_gbs';
+    hwSensor.type       = SENSOR_TYPE_ACCELEROMETER;
+    hwSensor.maxRange   = 1;
+    hwSensor.resolution = 1.0f / (1<<24);
+    hwSensor.power      = mSensorFusion.getPowerUsage();
+    hwSensor.minDelay   = mSensorFusion.getMinDelay();
+    Sensor sensor(&hwSensor);
+    return sensor;
+}
+
+// ---------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/services/sensorservice/RotationVectorSensor.h b/services/sensorservice/RotationVectorSensor.h
index ac76487..bb97fe1 100644
--- a/services/sensorservice/RotationVectorSensor.h
+++ b/services/sensorservice/RotationVectorSensor.h
@@ -24,7 +24,6 @@
 
 #include "SensorDevice.h"
 #include "SensorInterface.h"
-#include "SecondOrderLowPassFilter.h"
 
 #include "Fusion.h"
 #include "SensorFusion.h"
@@ -47,6 +46,20 @@
     virtual bool isVirtual() const { return true; }
 };
 
+class GyroDriftSensor : public SensorInterface {
+    SensorDevice& mSensorDevice;
+    SensorFusion& mSensorFusion;
+
+public:
+    GyroDriftSensor();
+    virtual bool process(sensors_event_t* outEvent,
+            const sensors_event_t& event);
+    virtual status_t activate(void* ident, bool enabled);
+    virtual status_t setDelay(void* ident, int handle, int64_t ns);
+    virtual Sensor getSensor() const;
+    virtual bool isVirtual() const { return true; }
+};
+
 // ---------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/services/sensorservice/SecondOrderLowPassFilter.cpp b/services/sensorservice/SecondOrderLowPassFilter.cpp
deleted file mode 100644
index c76dd4c..0000000
--- a/services/sensorservice/SecondOrderLowPassFilter.cpp
+++ /dev/null
@@ -1,103 +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.
- */
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <math.h>
-
-#include <cutils/log.h>
-
-#include "SecondOrderLowPassFilter.h"
-#include "vec.h"
-
-// ---------------------------------------------------------------------------
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-SecondOrderLowPassFilter::SecondOrderLowPassFilter(float Q, float fc)
-    : iQ(1.0f / Q), fc(fc)
-{
-}
-
-void SecondOrderLowPassFilter::setSamplingPeriod(float dT)
-{
-    K = tanf(float(M_PI) * fc * dT);
-    iD = 1.0f / (K*K + K*iQ + 1);
-    a0 = K*K*iD;
-    a1 = 2.0f * a0;
-    b1 = 2.0f*(K*K - 1)*iD;
-    b2 = (K*K - K*iQ + 1)*iD;
-}
-
-// ---------------------------------------------------------------------------
-
-template<typename T>
-BiquadFilter<T>::BiquadFilter(const SecondOrderLowPassFilter& s)
-    : s(s)
-{
-}
-
-template<typename T>
-T BiquadFilter<T>::init(const T& x)
-{
-    x1 = x2 = x;
-    y1 = y2 = x;
-    return x;
-}
-
-template<typename T>
-T BiquadFilter<T>::operator()(const T& x)
-{
-    T y = (x + x2)*s.a0 + x1*s.a1 - y1*s.b1 - y2*s.b2;
-    x2 = x1;
-    y2 = y1;
-    x1 = x;
-    y1 = y;
-    return y;
-}
-
-// ---------------------------------------------------------------------------
-
-template<typename T>
-CascadedBiquadFilter<T>::CascadedBiquadFilter(const SecondOrderLowPassFilter& s)
-    : mA(s), mB(s)
-{
-}
-
-template<typename T>
-T CascadedBiquadFilter<T>::init(const T& x)
-{
-    mA.init(x);
-    mB.init(x);
-    return x;
-}
-
-template<typename T>
-T CascadedBiquadFilter<T>::operator()(const T& x)
-{
-    return mB(mA(x));
-}
-
-// ---------------------------------------------------------------------------
-
-template class BiquadFilter<float>;
-template class CascadedBiquadFilter<float>;
-template class BiquadFilter<vec3_t>;
-template class CascadedBiquadFilter<vec3_t>;
-
-// ---------------------------------------------------------------------------
-}; // namespace android
diff --git a/services/sensorservice/SecondOrderLowPassFilter.h b/services/sensorservice/SecondOrderLowPassFilter.h
deleted file mode 100644
index 0cc2446..0000000
--- a/services/sensorservice/SecondOrderLowPassFilter.h
+++ /dev/null
@@ -1,77 +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.
- */
-
-#ifndef ANDROID_SECOND_ORDER_LOW_PASS_FILTER_H
-#define ANDROID_SECOND_ORDER_LOW_PASS_FILTER_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-// ---------------------------------------------------------------------------
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-template<typename T>
-class BiquadFilter;
-
-/*
- * State of a 2nd order low-pass IIR filter
- */
-class SecondOrderLowPassFilter {
-    template<typename T>
-    friend class BiquadFilter;
-    float iQ, fc;
-    float K, iD;
-    float a0, a1;
-    float b1, b2;
-public:
-    SecondOrderLowPassFilter(float Q, float fc);
-    void setSamplingPeriod(float dT);
-};
-
-/*
- * Implements a Biquad IIR filter
- */
-template<typename T>
-class BiquadFilter {
-    T x1, x2;
-    T y1, y2;
-    const SecondOrderLowPassFilter& s;
-public:
-    BiquadFilter(const SecondOrderLowPassFilter& s);
-    T init(const T& in);
-    T operator()(const T& in);
-};
-
-/*
- * Two cascaded biquad IIR filters
- * (4-poles IIR)
- */
-template<typename T>
-class CascadedBiquadFilter {
-    BiquadFilter<T> mA;
-    BiquadFilter<T> mB;
-public:
-    CascadedBiquadFilter(const SecondOrderLowPassFilter& s);
-    T init(const T& in);
-    T operator()(const T& in);
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_SECOND_ORDER_LOW_PASS_FILTER_H
diff --git a/services/sensorservice/SensorFusion.cpp b/services/sensorservice/SensorFusion.cpp
index d4226ec..4ec0c8c 100644
--- a/services/sensorservice/SensorFusion.cpp
+++ b/services/sensorservice/SensorFusion.cpp
@@ -25,9 +25,7 @@
 
 SensorFusion::SensorFusion()
     : mSensorDevice(SensorDevice::getInstance()),
-      mEnabled(false), mHasGyro(false), mGyroTime(0), mRotationMatrix(1),
-      mLowPass(M_SQRT1_2, 1.0f), mAccData(mLowPass),
-      mFilteredMag(0.0f), mFilteredAcc(0.0f)
+      mEnabled(false), mGyroTime(0)
 {
     sensor_t const* list;
     size_t count = mSensorDevice.getSensorList(&list);
@@ -42,55 +40,32 @@
             mGyro = Sensor(list + i);
             // 200 Hz for gyro events is a good compromise between precision
             // and power/cpu usage.
-            mTargetDelayNs = 1000000000LL/200;
-            mGyroRate = 1000000000.0f / mTargetDelayNs;
-            mHasGyro = true;
+            mGyroRate = 200;
+            mTargetDelayNs = 1000000000LL/mGyroRate;
         }
     }
     mFusion.init();
-    mAccData.init(vec3_t(0.0f));
 }
 
 void SensorFusion::process(const sensors_event_t& event) {
-
-    if (event.type == SENSOR_TYPE_GYROSCOPE && mHasGyro) {
+    if (event.type == SENSOR_TYPE_GYROSCOPE) {
         if (mGyroTime != 0) {
             const float dT = (event.timestamp - mGyroTime) / 1000000000.0f;
             const float freq = 1 / dT;
-            const float alpha = 2 / (2 + dT); // 2s time-constant
-            mGyroRate = mGyroRate*alpha +  freq*(1 - alpha);
+            if (freq >= 100 && freq<1000) { // filter values obviously wrong
+                const float alpha = 1 / (1 + dT); // 1s time-constant
+                mGyroRate = freq + (mGyroRate - freq)*alpha;
+            }
         }
         mGyroTime = event.timestamp;
         mFusion.handleGyro(vec3_t(event.data), 1.0f/mGyroRate);
     } else if (event.type == SENSOR_TYPE_MAGNETIC_FIELD) {
         const vec3_t mag(event.data);
-        if (mHasGyro) {
-            mFusion.handleMag(mag);
-        } else {
-            const float l(length(mag));
-            if (l>5 && l<100) {
-                mFilteredMag = mag * (1/l);
-            }
-        }
+        mFusion.handleMag(mag);
     } else if (event.type == SENSOR_TYPE_ACCELEROMETER) {
         const vec3_t acc(event.data);
-        if (mHasGyro) {
-            mFusion.handleAcc(acc);
-            mRotationMatrix = mFusion.getRotationMatrix();
-        } else {
-            const float l(length(acc));
-            if (l > 0.981f) {
-                // remove the linear-acceleration components
-                mFilteredAcc = mAccData(acc * (1/l));
-            }
-            if (length(mFilteredAcc)>0 && length(mFilteredMag)>0) {
-                vec3_t up(mFilteredAcc);
-                vec3_t east(cross_product(mFilteredMag, up));
-                east *= 1/length(east);
-                vec3_t north(cross_product(up, east));
-                mRotationMatrix << east << north << up;
-            }
-        }
+        mFusion.handleAcc(acc);
+        mAttitude = mFusion.getAttitude();
     }
 }
 
@@ -116,40 +91,31 @@
 
     mSensorDevice.activate(ident, mAcc.getHandle(), enabled);
     mSensorDevice.activate(ident, mMag.getHandle(), enabled);
-    if (mHasGyro) {
-        mSensorDevice.activate(ident, mGyro.getHandle(), enabled);
-    }
+    mSensorDevice.activate(ident, mGyro.getHandle(), enabled);
 
     const bool newState = mClients.size() != 0;
     if (newState != mEnabled) {
         mEnabled = newState;
         if (newState) {
             mFusion.init();
+            mGyroTime = 0;
         }
     }
     return NO_ERROR;
 }
 
 status_t SensorFusion::setDelay(void* ident, int64_t ns) {
-    if (mHasGyro) {
-        mSensorDevice.setDelay(ident, mAcc.getHandle(), ns);
-        mSensorDevice.setDelay(ident, mMag.getHandle(), ms2ns(20));
-        mSensorDevice.setDelay(ident, mGyro.getHandle(), mTargetDelayNs);
-    } else {
-        const static double NS2S = 1.0 / 1000000000.0;
-        mSensorDevice.setDelay(ident, mAcc.getHandle(), ns);
-        mSensorDevice.setDelay(ident, mMag.getHandle(), max(ns, mMag.getMinDelayNs()));
-        mLowPass.setSamplingPeriod(ns*NS2S);
-    }
+    mSensorDevice.setDelay(ident, mAcc.getHandle(), ns);
+    mSensorDevice.setDelay(ident, mMag.getHandle(), ms2ns(20));
+    mSensorDevice.setDelay(ident, mGyro.getHandle(), mTargetDelayNs);
     return NO_ERROR;
 }
 
 
 float SensorFusion::getPowerUsage() const {
-    float power = mAcc.getPowerUsage() + mMag.getPowerUsage();
-    if (mHasGyro) {
-        power += mGyro.getPowerUsage();
-    }
+    float power =   mAcc.getPowerUsage() +
+                    mMag.getPowerUsage() +
+                    mGyro.getPowerUsage();
     return power;
 }
 
@@ -159,17 +125,17 @@
 
 void SensorFusion::dump(String8& result, char* buffer, size_t SIZE) {
     const Fusion& fusion(mFusion);
-    snprintf(buffer, SIZE, "Fusion (%s) %s (%d clients), gyro-rate=%7.2fHz, "
-            "MRPS=< %g, %g, %g > (%g), "
-            "BIAS=< %g, %g, %g >\n",
-            mHasGyro ? "9-axis" : "6-axis",
+    snprintf(buffer, SIZE, "9-axis fusion %s (%d clients), gyro-rate=%7.2fHz, "
+            "q=< %g, %g, %g, %g > (%g), "
+            "b=< %g, %g, %g >\n",
             mEnabled ? "enabled" : "disabled",
             mClients.size(),
             mGyroRate,
             fusion.getAttitude().x,
             fusion.getAttitude().y,
             fusion.getAttitude().z,
-            dot_product(fusion.getAttitude(), fusion.getAttitude()),
+            fusion.getAttitude().w,
+            length(fusion.getAttitude()),
             fusion.getBias().x,
             fusion.getBias().y,
             fusion.getBias().z);
diff --git a/services/sensorservice/SensorFusion.h b/services/sensorservice/SensorFusion.h
index c7eab12..4c99bcb 100644
--- a/services/sensorservice/SensorFusion.h
+++ b/services/sensorservice/SensorFusion.h
@@ -27,7 +27,6 @@
 #include <gui/Sensor.h>
 
 #include "Fusion.h"
-#include "SecondOrderLowPassFilter.h"
 
 // ---------------------------------------------------------------------------
 
@@ -45,15 +44,10 @@
     Sensor mGyro;
     Fusion mFusion;
     bool mEnabled;
-    bool mHasGyro;
     float mGyroRate;
     nsecs_t mTargetDelayNs;
     nsecs_t mGyroTime;
-    mat33_t mRotationMatrix;
-    SecondOrderLowPassFilter mLowPass;
-    BiquadFilter<vec3_t> mAccData;
-    vec3_t mFilteredMag;
-    vec3_t mFilteredAcc;
+    vec4_t mAttitude;
     SortedVector<void*> mClients;
 
     SensorFusion();
@@ -62,9 +56,9 @@
     void process(const sensors_event_t& event);
 
     bool isEnabled() const { return mEnabled; }
-    bool hasGyro() const { return mHasGyro; }
-    bool hasEstimate() const { return !mHasGyro || mFusion.hasEstimate(); }
-    mat33_t getRotationMatrix() const { return mRotationMatrix; }
+    bool hasEstimate() const { return mFusion.hasEstimate(); }
+    mat33_t getRotationMatrix() const { return mFusion.getRotationMatrix(); }
+    vec4_t getAttitude() const { return mAttitude; }
     vec3_t getGyroBias() const { return mFusion.getBias(); }
     float getEstimatedRate() const { return mGyroRate; }
 
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 5b86d10..d1b10f7 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -18,6 +18,8 @@
 #include <math.h>
 #include <sys/types.h>
 
+#include <cutils/properties.h>
+
 #include <utils/SortedVector.h>
 #include <utils/KeyedVector.h>
 #include <utils/threads.h>
@@ -46,6 +48,16 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
+/*
+ * Notes:
+ *
+ * - what about a gyro-corrected magnetic-field sensor?
+ * - option to "hide" the HAL sensors
+ * - run mag sensor from time to time to force calibration
+ * - gravity sensor length is wrong (=> drift in linear-acc sensor)
+ *
+ */
+
 SensorService::SensorService()
     : mDump("android.permission.DUMP"),
       mInitCheck(NO_INIT)
@@ -59,6 +71,7 @@
     SensorDevice& dev(SensorDevice::getInstance());
 
     if (dev.initCheck() == NO_ERROR) {
+        bool hasGyro = false;
         uint32_t virtualSensorsNeeds =
                 (1<<SENSOR_TYPE_GRAVITY) |
                 (1<<SENSOR_TYPE_LINEAR_ACCELERATION) |
@@ -69,6 +82,9 @@
         for (int i=0 ; i<count ; i++) {
             registerSensor( new HardwareSensor(list[i]) );
             switch (list[i].type) {
+                case SENSOR_TYPE_GYROSCOPE:
+                    hasGyro = true;
+                    break;
                 case SENSOR_TYPE_GRAVITY:
                 case SENSOR_TYPE_LINEAR_ACCELERATION:
                 case SENSOR_TYPE_ROTATION_VECTOR:
@@ -82,21 +98,26 @@
         // registered)
         const SensorFusion& fusion(SensorFusion::getInstance());
 
-        // Always instantiate Android's virtual sensors. Since they are
-        // instantiated behind sensors from the HAL, they won't
-        // interfere with applications, unless they looks specifically
-        // for them (by name).
+        if (hasGyro) {
+            // Always instantiate Android's virtual sensors. Since they are
+            // instantiated behind sensors from the HAL, they won't
+            // interfere with applications, unless they looks specifically
+            // for them (by name).
 
-        registerVirtualSensor( new RotationVectorSensor() );
-        registerVirtualSensor( new GravitySensor(list, count) );
-        registerVirtualSensor( new LinearAccelerationSensor(list, count) );
+            registerVirtualSensor( new RotationVectorSensor() );
+            registerVirtualSensor( new GravitySensor(list, count) );
+            registerVirtualSensor( new LinearAccelerationSensor(list, count) );
 
-        // if we have a gyro, we have the option of enabling these
-        // "better" orientation and gyro sensors
-        if (fusion.hasGyro()) {
-            // FIXME: OrientationSensor buggy when not pointing north
+            // these are optional
             registerVirtualSensor( new OrientationSensor() );
             registerVirtualSensor( new CorrectedGyroSensor(list, count) );
+
+            // virtual debugging sensors...
+            char value[PROPERTY_VALUE_MAX];
+            property_get("debug.sensors", value, "0");
+            if (atoi(value)) {
+                registerVirtualSensor( new GyroDriftSensor() );
+            }
         }
 
         run("SensorService", PRIORITY_URGENT_DISPLAY);
diff --git a/services/sensorservice/quat.h b/services/sensorservice/quat.h
new file mode 100644
index 0000000..fea1afe
--- /dev/null
+++ b/services/sensorservice/quat.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_QUAT_H
+#define ANDROID_QUAT_H
+
+#include <math.h>
+
+#include "vec.h"
+#include "mat.h"
+
+// -----------------------------------------------------------------------
+namespace android {
+// -----------------------------------------------------------------------
+
+template <typename TYPE>
+mat<TYPE, 3, 3> quatToMatrix(const vec<TYPE, 4>& q) {
+    mat<TYPE, 3, 3> R;
+    TYPE q0(q.w);
+    TYPE q1(q.x);
+    TYPE q2(q.y);
+    TYPE q3(q.z);
+    TYPE sq_q1 = 2 * q1 * q1;
+    TYPE sq_q2 = 2 * q2 * q2;
+    TYPE sq_q3 = 2 * q3 * q3;
+    TYPE q1_q2 = 2 * q1 * q2;
+    TYPE q3_q0 = 2 * q3 * q0;
+    TYPE q1_q3 = 2 * q1 * q3;
+    TYPE q2_q0 = 2 * q2 * q0;
+    TYPE q2_q3 = 2 * q2 * q3;
+    TYPE q1_q0 = 2 * q1 * q0;
+    R[0][0] = 1 - sq_q2 - sq_q3;
+    R[0][1] = q1_q2 - q3_q0;
+    R[0][2] = q1_q3 + q2_q0;
+    R[1][0] = q1_q2 + q3_q0;
+    R[1][1] = 1 - sq_q1 - sq_q3;
+    R[1][2] = q2_q3 - q1_q0;
+    R[2][0] = q1_q3 - q2_q0;
+    R[2][1] = q2_q3 + q1_q0;
+    R[2][2] = 1 - sq_q1 - sq_q2;
+    return R;
+}
+
+template <typename TYPE>
+vec<TYPE, 4> matrixToQuat(const mat<TYPE, 3, 3>& R) {
+    // matrix to quaternion
+
+    struct {
+        inline TYPE operator()(TYPE v) {
+            return v < 0 ? 0 : v;
+        }
+    } clamp;
+
+    vec<TYPE, 4> q;
+    const float Hx = R[0].x;
+    const float My = R[1].y;
+    const float Az = R[2].z;
+    q.x = sqrtf( clamp( Hx - My - Az + 1) * 0.25f );
+    q.y = sqrtf( clamp(-Hx + My - Az + 1) * 0.25f );
+    q.z = sqrtf( clamp(-Hx - My + Az + 1) * 0.25f );
+    q.w = sqrtf( clamp( Hx + My + Az + 1) * 0.25f );
+    q.x = copysignf(q.x, R[2].y - R[1].z);
+    q.y = copysignf(q.y, R[0].z - R[2].x);
+    q.z = copysignf(q.z, R[1].x - R[0].y);
+    // guaranteed to be unit-quaternion
+    return q;
+}
+
+template <typename TYPE>
+vec<TYPE, 4> normalize_quat(const vec<TYPE, 4>& q) {
+    vec<TYPE, 4> r(q);
+    if (r.w < 0) {
+        r = -r;
+    }
+    return normalize(r);
+}
+
+// -----------------------------------------------------------------------
+
+typedef vec4_t quat_t;
+
+// -----------------------------------------------------------------------
+}; // namespace android
+
+#endif /* ANDROID_QUAT_H */
diff --git a/services/sensorservice/vec.h b/services/sensorservice/vec.h
index 736ff37..f74ccc5 100644
--- a/services/sensorservice/vec.h
+++ b/services/sensorservice/vec.h
@@ -208,6 +208,15 @@
 }
 
 template <
+    template<typename T, size_t S> class V,
+    typename TYPE,
+    size_t SIZE
+>
+V<TYPE, SIZE> PURE normalize(const V<TYPE, SIZE>& v) {
+    return v * (1/length(v));
+}
+
+template <
     template<typename T, size_t S> class VLHS,
     template<typename T, size_t S> class VRHS,
     typename TYPE
diff --git a/telephony/java/com/android/internal/telephony/DataConnection.java b/telephony/java/com/android/internal/telephony/DataConnection.java
index e8d4f98..c21a96a 100644
--- a/telephony/java/com/android/internal/telephony/DataConnection.java
+++ b/telephony/java/com/android/internal/telephony/DataConnection.java
@@ -142,7 +142,7 @@
         static {
             sErrorCodeToFailCauseMap = new HashMap<Integer, FailCause>();
             for (FailCause fc : values()) {
-                sErrorCodeToFailCauseMap.put(fc.ordinal(), fc);
+                sErrorCodeToFailCauseMap.put(fc.getErrorCode(), fc);
             }
         }
 
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 5ddfcd1..5d6aaa6 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -304,7 +304,7 @@
                 mIsScreenOn = false;
                 stopNetStatPoll();
                 startNetStatPoll();
-            } else if (action.equals(getActionIntentReconnectAlarm())) {
+            } else if (action.startsWith(getActionIntentReconnectAlarm())) {
                 log("Reconnect alarm. Previous state was " + mState);
                 onActionIntentReconnectAlarm(intent);
 
diff --git a/telephony/java/com/android/internal/telephony/IccCard.java b/telephony/java/com/android/internal/telephony/IccCard.java
index a516b49..5d8fc78 100644
--- a/telephony/java/com/android/internal/telephony/IccCard.java
+++ b/telephony/java/com/android/internal/telephony/IccCard.java
@@ -722,52 +722,88 @@
             currentRadioState == RadioState.RUIM_READY ||
             (currentRadioState == RadioState.NV_READY &&
                     (mPhone.getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE))) {
-            int index;
+
+            State csimState =
+                getAppState(mIccCardStatus.getCdmaSubscriptionAppIndex());
+            State usimState =
+                getAppState(mIccCardStatus.getGsmUmtsSubscriptionAppIndex());
+
+            if(mDbg) log("USIM=" + usimState + " CSIM=" + csimState);
+
+            if (mPhone.getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE) {
+                // UICC card contains both USIM and CSIM
+                // Return consolidated status
+                return getConsolidatedState(csimState, usimState, csimState);
+            }
 
             // check for CDMA radio technology
             if (currentRadioState == RadioState.RUIM_LOCKED_OR_ABSENT ||
                 currentRadioState == RadioState.RUIM_READY) {
-                index = mIccCardStatus.getCdmaSubscriptionAppIndex();
+                return csimState;
             }
-            else {
-                index = mIccCardStatus.getGsmUmtsSubscriptionAppIndex();
-            }
-
-            IccCardApplication app;
-            if (index >= 0 && index < IccCardStatus.CARD_MAX_APPS) {
-                app = mIccCardStatus.getApplication(index);
-            } else {
-                Log.e(mLogTag, "[IccCard] Invalid Subscription Application index:" + index);
-                return IccCard.State.ABSENT;
-            }
-
-            if (app == null) {
-                Log.e(mLogTag, "[IccCard] Subscription Application in not present");
-                return IccCard.State.ABSENT;
-            }
-
-            // check if PIN required
-            if (app.app_state.isPinRequired()) {
-                return IccCard.State.PIN_REQUIRED;
-            }
-            if (app.app_state.isPukRequired()) {
-                return IccCard.State.PUK_REQUIRED;
-            }
-            if (app.app_state.isSubscriptionPersoEnabled()) {
-                return IccCard.State.NETWORK_LOCKED;
-            }
-            if (app.app_state.isAppReady()) {
-                return IccCard.State.READY;
-            }
-            if (app.app_state.isAppNotReady()) {
-                return IccCard.State.NOT_READY;
-            }
-            return IccCard.State.NOT_READY;
+            return usimState;
         }
 
         return IccCard.State.ABSENT;
     }
 
+    private State getAppState(int appIndex) {
+        IccCardApplication app;
+        if (appIndex >= 0 && appIndex < IccCardStatus.CARD_MAX_APPS) {
+            app = mIccCardStatus.getApplication(appIndex);
+        } else {
+            Log.e(mLogTag, "[IccCard] Invalid Subscription Application index:" + appIndex);
+            return IccCard.State.ABSENT;
+        }
+
+        if (app == null) {
+            Log.e(mLogTag, "[IccCard] Subscription Application in not present");
+            return IccCard.State.ABSENT;
+        }
+
+        // check if PIN required
+        if (app.app_state.isPinRequired()) {
+            return IccCard.State.PIN_REQUIRED;
+        }
+        if (app.app_state.isPukRequired()) {
+            return IccCard.State.PUK_REQUIRED;
+        }
+        if (app.app_state.isSubscriptionPersoEnabled()) {
+            return IccCard.State.NETWORK_LOCKED;
+        }
+        if (app.app_state.isAppReady()) {
+            return IccCard.State.READY;
+        }
+        if (app.app_state.isAppNotReady()) {
+            return IccCard.State.NOT_READY;
+        }
+        return IccCard.State.NOT_READY;
+    }
+
+    private State getConsolidatedState(State left, State right, State preferredState) {
+        // Check if either is absent.
+        if (right == IccCard.State.ABSENT) return left;
+        if (left == IccCard.State.ABSENT) return right;
+
+        // Only if both are ready, return ready
+        if ((left == IccCard.State.READY) && (right == IccCard.State.READY)) {
+            return State.READY;
+        }
+
+        // Case one is ready, but the other is not.
+        if (((right == IccCard.State.NOT_READY) && (left == IccCard.State.READY)) ||
+            ((left == IccCard.State.NOT_READY) && (right == IccCard.State.READY))) {
+            return IccCard.State.NOT_READY;
+        }
+
+        // At this point, the other state is assumed to be one of locked state
+        if (right == IccCard.State.NOT_READY) return left;
+        if (left == IccCard.State.NOT_READY) return right;
+
+        // At this point, FW currently just assumes the status will be
+        // consistent across the applications...
+        return preferredState;
+    }
 
     public boolean isApplicationOnIcc(IccCardApplication.AppType type) {
         if (mIccCardStatus == null) return false;
diff --git a/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java b/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
index 2f22d74..45562ca 100644
--- a/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
@@ -24,6 +24,7 @@
 import android.os.ServiceManager;
 
 import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * SimPhoneBookInterfaceManager to provide an inter-process communication to
@@ -63,14 +64,14 @@
                                     " total " + recordSize[1] +
                                     " #record " + recordSize[2]);
                         }
-                        mLock.notifyAll();
+                        notifyPending(ar);
                     }
                     break;
                 case EVENT_UPDATE_DONE:
                     ar = (AsyncResult) msg.obj;
                     synchronized (mLock) {
                         success = (ar.exception == null);
-                        mLock.notifyAll();
+                        notifyPending(ar);
                     }
                     break;
                 case EVENT_LOAD_DONE:
@@ -84,11 +85,20 @@
                                 records.clear();
                             }
                         }
-                        mLock.notifyAll();
+                        notifyPending(ar);
                     }
                     break;
             }
         }
+
+        private void notifyPending(AsyncResult ar) {
+            if (ar.userObj == null) {
+                return;
+            }
+            AtomicBoolean status = (AtomicBoolean) ar.userObj;
+            status.set(true);
+            mLock.notifyAll();
+        }
     };
 
     public IccPhoneBookInterfaceManager(PhoneBase phone) {
@@ -150,15 +160,12 @@
         synchronized(mLock) {
             checkThread();
             success = false;
-            Message response = mBaseHandler.obtainMessage(EVENT_UPDATE_DONE);
+            AtomicBoolean status = new AtomicBoolean(false);
+            Message response = mBaseHandler.obtainMessage(EVENT_UPDATE_DONE, status);
             AdnRecord oldAdn = new AdnRecord(oldTag, oldPhoneNumber);
             AdnRecord newAdn = new AdnRecord(newTag, newPhoneNumber);
             adnCache.updateAdnBySearch(efid, oldAdn, newAdn, pin2, response);
-            try {
-                mLock.wait();
-            } catch (InterruptedException e) {
-                logd("interrupted while trying to update by search");
-            }
+            waitForResult(status);
         }
         return success;
     }
@@ -197,14 +204,11 @@
         synchronized(mLock) {
             checkThread();
             success = false;
-            Message response = mBaseHandler.obtainMessage(EVENT_UPDATE_DONE);
+            AtomicBoolean status = new AtomicBoolean(false);
+            Message response = mBaseHandler.obtainMessage(EVENT_UPDATE_DONE, status);
             AdnRecord newAdn = new AdnRecord(newTag, newPhoneNumber);
             adnCache.updateAdnByIndex(efid, newAdn, index, pin2, response);
-            try {
-                mLock.wait();
-            } catch (InterruptedException e) {
-                logd("interrupted while trying to update by index");
-            }
+            waitForResult(status);
         }
         return success;
     }
@@ -243,15 +247,12 @@
 
         synchronized(mLock) {
             checkThread();
-            Message response = mBaseHandler.obtainMessage(EVENT_LOAD_DONE);
+            AtomicBoolean status = new AtomicBoolean(false);
+            Message response = mBaseHandler.obtainMessage(EVENT_LOAD_DONE, status);
             adnCache.requestLoadAllAdnLike(efid, adnCache.extensionEfForEf(efid), response);
-            try {
-                mLock.wait();
-            } catch (InterruptedException e) {
-                logd("interrupted while trying to load from the SIM");
-            }
+            waitForResult(status);
         }
-            return records;
+        return records;
     }
 
     protected void checkThread() {
@@ -265,6 +266,16 @@
         }
     }
 
+    protected void waitForResult(AtomicBoolean status) {
+        while (!status.get()) {
+            try {
+                mLock.wait();
+            } catch (InterruptedException e) {
+                logd("interrupted while trying to update by search");
+            }
+        }
+    }
+
     private int updateEfForIccType(int efid) {
         // Check if we are trying to read ADN records
         if (efid == IccConstants.EF_ADN) {
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
index d79f0a1e..e593bd0 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteServiceStateTracker.java
@@ -48,22 +48,37 @@
 
     public CdmaLteServiceStateTracker(CDMALTEPhone phone) {
         super(phone);
+        cm.registerForSIMReady(this, EVENT_SIM_READY, null);
         mCdmaLtePhone = phone;
 
         mLteSS = new ServiceState();
         if (DBG) log("CdmaLteServiceStateTracker Constructors");
     }
 
+    public void dispose() {
+        cm.unregisterForSIMReady(this);
+        super.dispose();
+    }
+
     @Override
     public void handleMessage(Message msg) {
         AsyncResult ar;
         int[] ints;
         String[] strings;
-        if (msg.what == EVENT_POLL_STATE_GPRS) {
+        switch (msg.what) {
+        case EVENT_POLL_STATE_GPRS:
             if (DBG) log("handleMessage EVENT_POLL_STATE_GPRS");
             ar = (AsyncResult)msg.obj;
             handlePollStateResult(msg.what, ar);
-        } else {
+            break;
+        case EVENT_SIM_READY:
+            isSubscriptionFromRuim = false;
+            cm.getCDMASubscription( obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION));
+            pollState();
+            // Signal strength polling stops when radio is off.
+            queueNextSignalStrengthPoll();
+            break;
+        default:
             super.handleMessage(msg);
         }
     }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index 35a98edc..0fd0614 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -137,7 +137,7 @@
     private boolean mIsMinInfoReady = false;
 
     private boolean isEriTextLoaded = false;
-    private boolean isSubscriptionFromRuim = false;
+    protected boolean isSubscriptionFromRuim = false;
 
     /* Used only for debugging purposes. */
     private String mRegistrationDeniedReason;
@@ -1120,7 +1120,7 @@
      * This code should probably be hoisted to the base class so
      * the fix, when added, works for both.
      */
-    private void
+    protected void
     queueNextSignalStrengthPoll() {
         if (dontPollSignalStrength || (cm.getRadioState().isGsm())) {
             // The radio is telling us about signal strength changes
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java b/telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java
index ce33066..04ee2dd8 100644
--- a/telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimPhoneBookInterfaceManager.java
@@ -16,6 +16,8 @@
 
 package com.android.internal.telephony.cdma;
 
+import java.util.concurrent.atomic.AtomicBoolean;
+
 import android.os.Message;
 import android.util.Log;
 
@@ -56,14 +58,11 @@
             recordSize = new int[3];
 
             //Using mBaseHandler, no difference in EVENT_GET_SIZE_DONE handling
-            Message response = mBaseHandler.obtainMessage(EVENT_GET_SIZE_DONE);
+            AtomicBoolean status = new AtomicBoolean(false);
+            Message response = mBaseHandler.obtainMessage(EVENT_GET_SIZE_DONE, status);
 
             phone.getIccFileHandler().getEFLinearRecordSize(efid, response);
-            try {
-                mLock.wait();
-            } catch (InterruptedException e) {
-                logd("interrupted while trying to load from the RUIM");
-            }
+            waitForResult(status);
         }
 
         return recordSize;
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 3f4cd67..be5c616 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -18,6 +18,7 @@
 
 import android.os.Parcel;
 import android.os.SystemProperties;
+import android.telephony.PhoneNumberUtils;
 import android.util.Log;
 import com.android.internal.telephony.IccUtils;
 import com.android.internal.telephony.SmsHeader;
@@ -806,7 +807,12 @@
          * mechanism, and avoid null pointer exceptions.
          */
 
-        CdmaSmsAddress destAddr = CdmaSmsAddress.parse(destAddrStr);
+        /**
+         * North America Plus Code :
+         * Convert + code to 011 and dial out for international SMS
+         */
+        CdmaSmsAddress destAddr = CdmaSmsAddress.parse(
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode(destAddrStr));
         if (destAddr == null) return null;
 
         BearerData bearerData = new BearerData();
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index e1a6fef..f6485a4 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -22,6 +22,7 @@
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.net.ConnectivityManager;
@@ -1427,7 +1428,13 @@
 
         AlarmManager am =
             (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
-        Intent intent = new Intent(INTENT_RECONNECT_ALARM);
+
+        // TODO : Register the receiver only once maybe in baseclass.
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(INTENT_RECONNECT_ALARM + '.'+apnContext.getApnType());
+        mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
+
+        Intent intent = new Intent(INTENT_RECONNECT_ALARM + '.' + apnContext.getApnType());
         intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON, apnContext.getReason());
         intent.putExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE, apnContext.getApnType());
         apnContext.setReconnectIntent(PendingIntent.getBroadcast (
diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
index 891c7cb..4cd9440 100755
--- a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
@@ -181,8 +181,11 @@
         // recordsToLoad is set to 0 because no requests are made yet
         recordsToLoad = 0;
 
-
-        p.mCM.registerForSIMReady(this, EVENT_SIM_READY, null);
+        // SIMRecord is used by CDMA+LTE mode, and SIM_READY event
+        // will be subscribed by CdmaLteServiceStateTracker.
+        if (phone.getLteOnCdmaMode() != Phone.LTE_ON_CDMA_TRUE) {
+            p.mCM.registerForSIMReady(this, EVENT_SIM_READY, null);
+        }
         p.mCM.registerForOffOrNotAvailable(
                         this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
         p.mCM.setOnSmsOnSim(this, EVENT_SMS_ON_SIM, null);
@@ -196,7 +199,9 @@
     @Override
     public void dispose() {
         //Unregister for all events
-        phone.mCM.unregisterForSIMReady(this);
+        if (phone.getLteOnCdmaMode() != Phone.LTE_ON_CDMA_TRUE) {
+            phone.mCM.unregisterForSIMReady(this);
+        }
         phone.mCM.unregisterForOffOrNotAvailable( this);
         phone.mCM.unregisterForIccRefresh(this);
     }
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java b/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java
index 377f8f0..35ba0d1 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimPhoneBookInterfaceManager.java
@@ -16,6 +16,8 @@
 
 package com.android.internal.telephony.gsm;
 
+import java.util.concurrent.atomic.AtomicBoolean;
+
 import android.os.Message;
 import android.util.Log;
 
@@ -56,14 +58,11 @@
             recordSize = new int[3];
 
             //Using mBaseHandler, no difference in EVENT_GET_SIZE_DONE handling
-            Message response = mBaseHandler.obtainMessage(EVENT_GET_SIZE_DONE);
+            AtomicBoolean status = new AtomicBoolean(false);
+            Message response = mBaseHandler.obtainMessage(EVENT_GET_SIZE_DONE, status);
 
             phone.getIccFileHandler().getEFLinearRecordSize(efid, response);
-            try {
-                mLock.wait();
-            } catch (InterruptedException e) {
-                logd("interrupted while trying to load from the SIM");
-            }
+            waitForResult(status);
         }
 
         return recordSize;
diff --git a/test-runner/src/android/test/BundlePrinter.java b/test-runner/src/android/test/BundlePrinter.java
deleted file mode 100644
index 3c47379..0000000
--- a/test-runner/src/android/test/BundlePrinter.java
+++ /dev/null
@@ -1,79 +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 java.io.PrintStream;
-
-import android.os.Bundle;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.runner.BaseTestRunner;
-import junit.textui.ResultPrinter;
-
-
-/**
- * Subclass of ResultPrinter that adds test case results to a bundle.
- * 
- * {@hide} - This class is deprecated, and will be going away.  Please don't use it.
- */
-public class BundlePrinter extends ResultPrinter {
-
-    private Bundle mResults;
-    private boolean mFailure;
-    private boolean mError;
-    
-    public BundlePrinter(PrintStream writer, Bundle result) {
-        super(writer);
-        mResults = result;
-    }
-    
-    @Override
-    public void addError(Test test, Throwable t) {
-        mResults.putString(getComboName(test), BaseTestRunner.getFilteredTrace(t));
-        mFailure = true;
-        super.addError(test, t);
-    }
-
-    @Override
-    public void addFailure(Test test, AssertionFailedError t) {
-        mResults.putString(getComboName(test), BaseTestRunner.getFilteredTrace(t));
-        mError = true;
-        super.addFailure(test, t);
-    }
-
-    @Override
-    public void endTest(Test test) {
-        if (!mFailure && !mError) {
-            mResults.putString(getComboName(test), "passed");
-        }
-        super.endTest(test);
-    }
-
-    @Override
-    public void startTest(Test test) {
-        mFailure = false;
-        mError = false;
-        super.startTest(test);
-    }
-    
-    private String getComboName(Test test) {
-        return test.getClass().getName() + ":" + ((TestCase) test).getName();
-    }
-    
-}
diff --git a/test-runner/src/android/test/BundleTestListener.java b/test-runner/src/android/test/BundleTestListener.java
deleted file mode 100644
index 772713f..0000000
--- a/test-runner/src/android/test/BundleTestListener.java
+++ /dev/null
@@ -1,63 +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.test;
-
-import junit.framework.*;
-import junit.framework.TestCase;
-import junit.runner.BaseTestRunner;
-import android.os.Bundle;
-
-/**
- * A {@link TestListener} that adds test case results to a bundle.
- * 
- * {@hide} - This class is deprecated, and will be going away.  Please don't use it.
- */
-public class BundleTestListener implements TestListener {
-
-    private Bundle mBundle;
-    private boolean mFailed;
-
-    public BundleTestListener(Bundle bundle) {
-        mBundle = bundle;
-    }
-
-
-    public void addError(Test test, Throwable t) {
-        mBundle.putString(getComboName(test), BaseTestRunner.getFilteredTrace(t));
-        mFailed = true;
-    }
-
-    public void addFailure(Test test, junit.framework.AssertionFailedError t) {
-        mBundle.putString(getComboName(test), BaseTestRunner.getFilteredTrace(t));
-        mFailed = true;
-    }
-
-    public void endTest(Test test) {
-        if (!mFailed) {
-            mBundle.putString(getComboName(test), "passed");
-        }
-    }
-
-    public void startTest(Test test) {
-        mFailed = false;
-    }
-
-    private String getComboName(Test test) {
-        return test.getClass().getName() + ":" + ((TestCase) test).getName();
-    }
-
-}
diff --git a/test-runner/src/android/test/ServiceLocator.java b/test-runner/src/android/test/ServiceLocator.java
deleted file mode 100644
index 3324008..0000000
--- a/test-runner/src/android/test/ServiceLocator.java
+++ /dev/null
@@ -1,35 +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;
-
-/**
- * @hide - This is part of a framework that is under development and should not be used for
- * active development.
- */
-public class ServiceLocator {
-
-    private static TestBrowserController mTestBrowserController =
-            new TestBrowserControllerImpl();
-
-    public static TestBrowserController getTestBrowserController() {
-        return mTestBrowserController;
-    }
-
-    static void setTestBrowserController(TestBrowserController testBrowserController) {
-        mTestBrowserController = testBrowserController;
-    }
-}
diff --git a/test-runner/src/android/test/TestBrowserActivity.java b/test-runner/src/android/test/TestBrowserActivity.java
deleted file mode 100644
index ea5f91e..0000000
--- a/test-runner/src/android/test/TestBrowserActivity.java
+++ /dev/null
@@ -1,127 +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 com.android.internal.R;
-
-import android.app.ListActivity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-import java.util.List;
-
-/**
- * @hide - This is part of a framework that is under development and should not be used for
- * active development.
- */
-public abstract class TestBrowserActivity extends ListActivity
-        implements android.test.TestBrowserView, AdapterView.OnItemClickListener,
-        TestSuiteProvider {
-
-    private TestBrowserController mTestBrowserController;
-    public static final String BUNDLE_EXTRA_PACKAGE = "package";
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        getListView().setOnItemClickListener(this);
-
-        mTestBrowserController = ServiceLocator.getTestBrowserController();
-        mTestBrowserController.setTargetPackageName(getPackageName());
-        mTestBrowserController.registerView(this);
-        mTestBrowserController.setTargetBrowserActivityClassName(this.getClass().getName());
-
-        // Apk paths used to search for test classes when using TestSuiteBuilders.
-        String[] apkPaths = {getPackageCodePath()};
-        ClassPathPackageInfoSource.setApkPaths(apkPaths);
-    }
-
-    @Override
-    protected void onStart() {
-        super.onStart();
-        TestSuite testSuite = getTestSuiteToBrowse();
-        mTestBrowserController.setTestSuite(testSuite);
-        
-        String name = testSuite.getName();
-        if (name != null) {
-            setTitle(name.substring(name.lastIndexOf(".") + 1));
-        }
-    }
-
-    /**
-     * Subclasses will override this method and return the TestSuite specific to their .apk.
-     * When this method is invoked due to an intent fired from
-     * {@link #onItemClick(android.widget.AdapterView, android.view.View, int, long)} then get the
-     * targeted TestSuite from the intent.
-     *
-     * @return testSuite to browse
-     */
-    @SuppressWarnings("unchecked")
-    private TestSuite getTestSuiteToBrowse() {
-        Intent intent = getIntent();
-        if (Intent.ACTION_RUN.equals(intent.getAction())) {
-            String testClassName = intent.getData().toString();
-
-            try {
-                Class<Test> testClass = (Class<Test>) getClassLoader().loadClass(testClassName);
-                return TestCaseUtil.createTestSuite(testClass);
-            } catch (ClassNotFoundException e) {
-                Log.e("TestBrowserActivity", "ClassNotFoundException for " + testClassName, e);
-                throw new RuntimeException(e);
-            } catch (IllegalAccessException e) {
-                Log.e("TestBrowserActivity", "IllegalAccessException for " + testClassName, e);
-                throw new RuntimeException(e);
-            } catch (InstantiationException e) {
-                Log.e("TestBrowserActivity", "InstantiationException for " + testClassName, e);
-                throw new RuntimeException(e);
-            }
-        } else {
-            // get test classes to browwes from subclass
-            return getTopTestSuite();
-        }
-
-    }
-
-    public TestSuite getTestSuite() {
-        return getTopTestSuite();
-    }
-
-    /**
-     * @return A TestSuite that should be run for a given application.
-     */
-    public abstract TestSuite getTopTestSuite();
-
-    public void onItemClick(AdapterView parent, View v, int position, long id) {
-        Intent intent = mTestBrowserController.getIntentForTestAt(position);
-        intent.putExtra(BUNDLE_EXTRA_PACKAGE, getPackageName());
-        startActivity(intent);
-    }
-
-    public void setTestNames(List<String> testNames) {
-        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this,
-                R.layout.test_list_item, testNames);
-        setListAdapter(arrayAdapter);
-    }
-}
-
diff --git a/test-runner/src/android/test/TestBrowserController.java b/test-runner/src/android/test/TestBrowserController.java
deleted file mode 100644
index 044e39f..0000000
--- a/test-runner/src/android/test/TestBrowserController.java
+++ /dev/null
@@ -1,38 +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.content.Intent;
-import junit.framework.TestSuite;
-
-/**
- * @hide - This is part of a framework that is under development and should not be used for
- * active development.
- */
-public interface TestBrowserController {
-    String BUNDLE_EXTRA_TEST_METHOD_NAME = "testMethodName";
-
-    Intent getIntentForTestAt(int position);
-
-    void setTestSuite(TestSuite testSuite);
-
-    void registerView(TestBrowserView testBrowserView);
-
-    void setTargetBrowserActivityClassName(String targetBrowserActivityClassName);
-
-    void setTargetPackageName(String targetPackageName);
-}
diff --git a/test-runner/src/android/test/TestBrowserControllerImpl.java b/test-runner/src/android/test/TestBrowserControllerImpl.java
deleted file mode 100644
index b8f8975..0000000
--- a/test-runner/src/android/test/TestBrowserControllerImpl.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.test;
-
-import android.content.Intent;
-import android.net.Uri;
-import com.google.android.collect.Lists;
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-import java.util.List;
-
-/**
- * @hide - This is part of a framework that is under development and should not be used for
- * active development.
- */
-public class TestBrowserControllerImpl implements TestBrowserController {
-
-    static final String TEST_RUNNER_ACTIVITY_CLASS_NAME =
-           "com.android.testharness.TestRunnerActivity";
-
-    private TestSuite mTestSuite;
-    private TestBrowserView mTestBrowserView;
-    private static final int RUN_ALL_INDEX = 0;
-    private String mTargetBrowserActivityClassName;
-    private String mTargetPackageName;
-
-    public void setTargetPackageName(String targetPackageName) {
-        mTargetPackageName = targetPackageName;
-    }
-
-    public Intent getIntentForTestAt(int position) {
-        Intent intent = new Intent();
-        intent.setAction(Intent.ACTION_RUN);
-        // We must add the following two flags to make sure that we create a new activity when
-        // we browse nested test suites.
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
-
-        String packageName = getDefaultPackageNameForTestRunner();
-        String className = "";
-        String testName = "";
-        if (shouldAllTestsBeRun(position)) {
-            testName = mTestSuite.getName();
-            className = TEST_RUNNER_ACTIVITY_CLASS_NAME;
-        } else {
-            Test test = TestCaseUtil.getTestAtIndex(mTestSuite, position - 1);
-            if (TestSuite.class.isAssignableFrom(test.getClass())) {
-                TestSuite testSuite = (TestSuite) test;
-                testName = testSuite.getName();
-                className = mTargetBrowserActivityClassName;
-                packageName = mTargetPackageName;
-            } else if (TestCase.class.isAssignableFrom(test.getClass())) {
-                TestCase testCase = (TestCase) test;
-                testName = testCase.getClass().getName();
-                className = TEST_RUNNER_ACTIVITY_CLASS_NAME;
-                String testMethodName = testCase.getName();
-                intent.putExtra(BUNDLE_EXTRA_TEST_METHOD_NAME, testMethodName);
-            }
-        }
-
-        intent.setClassName(packageName, className);
-        intent.setData(Uri.parse(testName));
-
-        return intent;
-    }
-
-    private String getDefaultPackageNameForTestRunner() {
-        return TEST_RUNNER_ACTIVITY_CLASS_NAME.substring(0,
-                TEST_RUNNER_ACTIVITY_CLASS_NAME.lastIndexOf("."));
-    }
-
-    private boolean shouldAllTestsBeRun(int position) {
-        return position == RUN_ALL_INDEX;
-    }
-
-    public void setTestSuite(TestSuite testSuite) {
-        mTestSuite = testSuite;
-
-        List<String> testCaseNames = Lists.newArrayList();
-        testCaseNames.add("Run All");
-        testCaseNames.addAll(TestCaseUtil.getTestCaseNames(testSuite, false));
-
-        mTestBrowserView.setTestNames(testCaseNames);
-    }
-
-    public void registerView(TestBrowserView testBrowserView) {
-        mTestBrowserView = testBrowserView;
-    }
-
-
-    public void setTargetBrowserActivityClassName(String targetBrowserActivityClassName) {
-        mTargetBrowserActivityClassName = targetBrowserActivityClassName;
-    }
-}
diff --git a/test-runner/src/android/test/TestBrowserView.java b/test-runner/src/android/test/TestBrowserView.java
deleted file mode 100644
index 4799f196..0000000
--- a/test-runner/src/android/test/TestBrowserView.java
+++ /dev/null
@@ -1,27 +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 java.util.List;
-
-/**
- * @hide - This is part of a framework that is under development and should not be used for
- * active development.
- */
-public interface TestBrowserView {
-    void setTestNames(List<String> testNames);
-}
diff --git a/test-runner/src/android/test/TestListActivity.java b/test-runner/src/android/test/TestListActivity.java
deleted file mode 100644
index a076a70..0000000
--- a/test-runner/src/android/test/TestListActivity.java
+++ /dev/null
@@ -1,253 +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.app.ListActivity;
-import android.content.Intent;
-import android.database.MatrixCursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.View;
-import android.widget.CursorAdapter;
-import android.widget.ListView;
-import android.widget.SimpleCursorAdapter;
-
-import java.util.Arrays;
-import java.util.Comparator;
-
-/**
- * Activity base class to use to implement your application's tests.
- *
- * <p>Implement the getTestSuite() method to return the name of your
- * test suite class.
- *
- * <p>See the android.test package documentation (click the more... link)
- * for a full description
- * 
- * {@hide} Not needed for SDK
- */
-public abstract class TestListActivity extends ListActivity {
-    /** Supplied in the intent extras if we are running performance tests. */
-    public static final String PERFORMANCE_TESTS = "android.test.performance";
-
-    /** "Mode" group in the menu. */
-    static final int MODE_GROUP = Menu.FIRST;
-
-    /** Our suite */
-    String mSuite;
-
-    /** Our children tests */
-    String[] mTests;
-
-    /** which mode, REGRESSION, PERFORMANCE or PROFILING */
-    private int mMode = TestRunner.REGRESSION;
-
-    /** "Regression" menu item */
-    private MenuItem mRegressionItem;
-
-    /** "Performance" menu item */
-    private MenuItem mPerformanceItem;
-
-    /** "Profiling" menu item */
-    private MenuItem mProfilingItem;
-
-    private final Comparator<String> sComparator = new Comparator<String>() {
-        public final int compare(String a, String b) {
-            String s1 = makeCompareName(a);
-            String s2 = makeCompareName(b);
-            
-            return s1.compareToIgnoreCase(s2);
-        }
-    };
-
-    /**
-     * Constructor that doesn't do much.
-     */
-    public TestListActivity() {
-        super();
-    }
-
-    /**
-     * Subclasses should implement this to return the names of the classes
-     * of their tests.
-     *
-     * @return test suite class name
-     */
-    public abstract String getTestSuite();
-
-    /**
-     * Typical onCreate(Bundle icicle) implementation.
-     */
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-
-        Intent intent = getIntent();
-
-        mMode = intent.getIntExtra(TestListActivity.PERFORMANCE_TESTS, mMode);
-
-
-        if (intent.getAction().equals(Intent.ACTION_MAIN)) {
-            // if we were called as MAIN, get the test suites,
-            mSuite = getTestSuite();
-        } else if (intent.getAction().equals(Intent.ACTION_RUN)) {
-            // We should have been provided a status channel.  Bail out and
-            // run the test instead.  This is how the TestHarness gets us
-            // loaded in our process for "Run All Tests."
-            Intent ntent = new Intent(Intent.ACTION_RUN,
-                    intent.getData() != null
-                            ? intent.getData()
-                            : Uri.parse(getTestSuite()));
-            ntent.setClassName("com.android.testharness",
-                    "com.android.testharness.RunTest");
-            ntent.putExtras(intent);
-            ntent.putExtra("package", getPackageName());
-            startActivity(ntent);
-            finish();
-            return;
-        } else if (intent.getAction().equals(Intent.ACTION_VIEW)) {
-            // otherwise use the one in the intent
-            mSuite = intent.getData() != null ? intent.getData().toString()
-                    : null;
-        }
-
-        String[] children = TestRunner.getChildren(this, mSuite);
-
-        Arrays.sort(children, sComparator);
-
-        int len = children.length;
-        mTests = new String[len];
-        System.arraycopy(children, 0, mTests, 0, len);
-
-        setTitle(TestRunner.getTitle(mSuite));
-
-        MatrixCursor cursor = new MatrixCursor(new String[] { "name", "_id" });
-        addTestRows(cursor);
-
-        CursorAdapter adapter = new SimpleCursorAdapter(
-                this,
-                com.android.internal.R.layout.simple_list_item_1,
-                cursor,
-                new String[] {"name"},
-                new int[] {com.android.internal.R.id.text1});
-        
-        setListAdapter(adapter);
-    }
-
-    private void addTestRows(MatrixCursor cursor) {
-        int id = 0;
-        cursor.newRow().add("Run All").add(id++);       
-        for (String test : mTests) {
-            String title = TestRunner.getTitle(test);
-            String prefix = TestRunner.isTestSuite(this, test)
-                    ? "Browse " : "Run ";
-
-            // I'd rather do this with an icon column, but I don't know how
-            cursor.newRow().add(prefix + title).add(id++);
-        }
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(Menu menu) {
-        super.onCreateOptionsMenu(menu);
-        mRegressionItem = menu.add(MODE_GROUP, -1, 0, "Regression Mode");
-        mPerformanceItem = menu.add(MODE_GROUP, -1, 0, "Performance Mode");
-        mProfilingItem = menu.add(MODE_GROUP, -1, 0, "Profiling Mode");
-        menu.setGroupCheckable(MODE_GROUP, true, true);
-        return true;
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        if (item == mRegressionItem) {
-            mMode = TestRunner.REGRESSION;
-        } else if (item == mPerformanceItem) {
-            mMode = TestRunner.PERFORMANCE;
-        } else if (item == mProfilingItem) {
-            mMode = TestRunner.PROFILING;
-        }
-        
-        return true;
-    }
-
-    @Override
-    public boolean onPrepareOptionsMenu(Menu menu) {
-        super.onPrepareOptionsMenu(menu);
-        switch (mMode) {
-        case TestRunner.REGRESSION:
-            mRegressionItem.setChecked(true);
-            break;
-
-        case TestRunner.PERFORMANCE:
-            mPerformanceItem.setChecked(true);
-            break;
-
-        case TestRunner.PROFILING:
-            mProfilingItem.setChecked(true);
-            break;
-        }
-        return true;
-    }
-
-    @Override
-    protected void onListItemClick(ListView l, View v, int position, long id) {
-        Intent intent = new Intent();
-
-        if (position == 0) {
-            if (false) {
-                intent.setClassName("com.android.testharness",
-                        "com.android.testharness.RunAll");
-                intent.putExtra("tests", new String[]{mSuite});
-            } else {
-                intent.setClassName("com.android.testharness",
-                        "com.android.testharness.RunTest");
-                intent.setAction(Intent.ACTION_RUN);
-                intent.setData(Uri.parse(mSuite));
-            }
-        } else {
-            String test = mTests[position - 1];
-            if (TestRunner.isTestSuite(this, test)) {
-                intent.setClassName(getPackageName(), this.getClass().getName());
-                intent.setAction(Intent.ACTION_VIEW);
-            } else {
-                intent.setClassName("com.android.testharness",
-                        "com.android.testharness.RunTest");
-            }
-            intent.setData(Uri.parse(test));
-        }
-
-        intent.putExtra(PERFORMANCE_TESTS, mMode);
-        intent.putExtra("package", getPackageName());
-        startActivity(intent);
-    }
-
-    private String makeCompareName(String s) {
-        int index = s.lastIndexOf('.');
-        
-        if (index == -1) {
-            return s;
-        }
-        
-        return s.substring(index + 1);
-    }
-}
diff --git a/test-runner/src/android/test/TestRecorder.java b/test-runner/src/android/test/TestRecorder.java
deleted file mode 100644
index 7c368a0..0000000
--- a/test-runner/src/android/test/TestRecorder.java
+++ /dev/null
@@ -1,186 +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.test;
-
-import android.content.ContentValues;
-import android.database.sqlite.SQLiteDatabase;
-import android.os.Environment;
-import android.os.FileUtils;
-import android.test.TestRunner.IntermediateTime;
-import android.util.Log;
-import junit.framework.Test;
-import junit.framework.TestListener;
-
-import java.io.File;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * {@hide} Not needed for 1.0 SDK.
- */
-public class TestRecorder implements TestRunner.Listener, TestListener {
-    private static final int DATABASE_VERSION = 1;
-    private static SQLiteDatabase sDb;
-    private Set<String> mFailedTests = new HashSet<String>();
-
-    private static SQLiteDatabase getDatabase() {
-        if (sDb == null) {
-            File dir = new File(Environment.getDataDirectory(), "test_results");
-
-            /* TODO: add a DB version number and bootstrap/upgrade methods
-            * if the format of the table changes.
-            */
-            String dbName = "TestHarness.db";
-            File file = new File(dir, dbName);
-            sDb = SQLiteDatabase.openOrCreateDatabase(file.getPath(), null);
-
-            if (sDb.getVersion() == 0) {
-                int code = FileUtils.setPermissions(file.getPath(),
-                        FileUtils.S_IRUSR | FileUtils.S_IWUSR |
-                                FileUtils.S_IRGRP | FileUtils.S_IWGRP |
-                                FileUtils.S_IROTH | FileUtils.S_IWOTH, -1, -1);
-    
-                if (code != 0) {
-                    Log.w("TestRecorder",
-                            "Set permissions for " + file.getPath() + " returned = " + code);
-                }
-    
-                try {
-                    sDb.execSQL("CREATE TABLE IF NOT EXISTS tests (_id INT PRIMARY KEY," +
-                            "name TEXT," +
-                            "result TEXT," +
-                            "exception TEXT," +
-                            "started INTEGER," +
-                            "finished INTEGER," +
-                            "time INTEGER," +
-                            "iterations INTEGER," +
-                            "allocations INTEGER," +
-                            "parent INTEGER);");
-                    sDb.setVersion(DATABASE_VERSION);
-                } catch (Exception e) {
-                    Log.e("TestRecorder", "failed to create table 'tests'", e);
-                    sDb = null;
-                }
-            }
-        }
-
-        return sDb;
-    }
-
-    public TestRecorder() {
-    }
-
-    public void started(String className) {
-        ContentValues map = new ContentValues(2);
-        map.put("name", className);
-        map.put("started", System.currentTimeMillis());
-
-        // try to update the row first in case we've ran this test before.
-        int rowsAffected = getDatabase().update("tests", map, "name = '" + className + "'", null);
-
-        if (rowsAffected == 0) {
-            getDatabase().insert("tests", null, map);
-        }
-    }
-
-    public void finished(String className) {
-        ContentValues map = new ContentValues(1);
-        map.put("finished", System.currentTimeMillis());
-
-        getDatabase().update("tests", map, "name = '" + className + "'", null);
-    }
-
-    public void performance(String className, long itemTimeNS, int iterations, List<IntermediateTime> intermediates) {
-        ContentValues map = new ContentValues();
-        map.put("time", itemTimeNS);
-        map.put("iterations", iterations);
-
-        getDatabase().update("tests", map, "name = '" + className + "'", null);
-
-        if (intermediates != null && intermediates.size() > 0) {
-            int n = intermediates.size();
-            for (int i = 0; i < n; i++) {
-                TestRunner.IntermediateTime time = intermediates.get(i);
-
-                getDatabase().execSQL("INSERT INTO tests (name, time, parent) VALUES ('" +
-                        time.name + "', " + time.timeInNS + ", " +
-                        "(SELECT _id FROM tests WHERE name = '" + className + "'));");
-            }
-        }
-    }
-
-    public void passed(String className) {
-        ContentValues map = new ContentValues();
-        map.put("result", "passed");
-
-        getDatabase().update("tests", map, "name = '" + className + "'", null);
-    }
-
-    public void failed(String className, Throwable exception) {
-        StringWriter stringWriter = new StringWriter();
-        PrintWriter printWriter = new PrintWriter(stringWriter);
-        try {
-            exception.printStackTrace(printWriter);
-        } finally {
-            printWriter.close();
-        }
-        ContentValues map = new ContentValues();
-        map.put("result", "failed");
-        map.put("exception", stringWriter.toString());
-
-        getDatabase().update("tests", map, "name = '" + className + "'", null);
-    }
-
-    /**
-     * Reports a test case failure.
-     *
-     * @param className Name of the class/test.
-     * @param reason    Reason for failure.
-     */
-    public void failed(String className, String reason) {
-        ContentValues map = new ContentValues();
-        map.put("result", "failed");
-        // The reason is put as the exception.
-        map.put("exception", reason);
-        getDatabase().update("tests", map, "name = '" + className + "'", null);
-    }
-
-    public void addError(Test test, Throwable t) {
-        mFailedTests.add(test.toString());
-        failed(test.toString(), t);
-    }
-
-    public void addFailure(Test test, junit.framework.AssertionFailedError t) {
-        mFailedTests.add(test.toString());
-        failed(test.toString(), t.getMessage());
-    }
-
-    public void endTest(Test test) {
-        finished(test.toString());
-        if (!mFailedTests.contains(test.toString())) {
-            passed(test.toString());
-        }
-        mFailedTests.remove(test.toString());
-    }
-
-    public void startTest(Test test) {
-        started(test.toString());
-    }
-}
diff --git a/test-runner/src/android/test/TestRunnerView.java b/test-runner/src/android/test/TestRunnerView.java
deleted file mode 100644
index be90951..0000000
--- a/test-runner/src/android/test/TestRunnerView.java
+++ /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.test;
-
-import java.util.List;
-
-/**
- * @hide - This is part of a framework that is under development and should not be used for
- * active development.
- */
-public interface TestRunnerView {
-    void setTestNames(List<String> testNames);
-
-    void setItemColorAt(int position, int color);
-
-    void setFailureCount(int failureCount);
-
-    void setRunCount(int runCount);
-
-    void setErrorCount(int errorCount);
-
-    void setTotalCount(int totalCount);
-
-    void setProgressBarColor(int color);
-
-    void testsCompleted();
-}
diff --git a/test-runner/src/junit/runner/logo.gif b/test-runner/src/junit/runner/logo.gif
deleted file mode 100644
index d0e1547..0000000
--- a/test-runner/src/junit/runner/logo.gif
+++ /dev/null
Binary files differ
diff --git a/test-runner/src/junit/runner/smalllogo.gif b/test-runner/src/junit/runner/smalllogo.gif
deleted file mode 100644
index 7b25eaf6..0000000
--- a/test-runner/src/junit/runner/smalllogo.gif
+++ /dev/null
Binary files differ
diff --git a/test-runner/tests/src/android/test/StubTestBrowserActivity.java b/test-runner/tests/src/android/test/StubTestBrowserActivity.java
deleted file mode 100644
index 97ed3ce..0000000
--- a/test-runner/tests/src/android/test/StubTestBrowserActivity.java
+++ /dev/null
@@ -1,33 +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 junit.framework.TestSuite;
-
-public class StubTestBrowserActivity extends TestBrowserActivity {
-
-    private static TestSuite mTestSuite;
-
-    static void setTopTestSuite(TestSuite testSuite) {
-        mTestSuite = testSuite;
-    }
-
-    @Override
-    public TestSuite getTopTestSuite() {
-        return mTestSuite;
-    }
-}
diff --git a/test-runner/tests/src/android/test/TestBrowserActivityTest.java b/test-runner/tests/src/android/test/TestBrowserActivityTest.java
deleted file mode 100644
index 355409e..0000000
--- a/test-runner/tests/src/android/test/TestBrowserActivityTest.java
+++ /dev/null
@@ -1,275 +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.app.Activity;
-import android.app.Instrumentation;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.view.IWindowManager;
-import android.widget.ListView;
-
-import com.google.android.collect.Lists;
-
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-import java.util.List;
-
-public class TestBrowserActivityTest extends InstrumentationTestCase {
-
-    private TestBrowserActivity mTestBrowserActivity;
-    private StubTestBrowserController mTestBrowserController;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        StubTestBrowserActivity.setTopTestSuite(null);
-        mTestBrowserController = new StubTestBrowserController();
-        ServiceLocator.setTestBrowserController(mTestBrowserController);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        if (mTestBrowserActivity != null) {
-            mTestBrowserActivity.finish();
-        }
-        mTestBrowserActivity = null;
-        super.tearDown();
-    }
-
-    public void testEmptyListContent() throws Exception {
-        StubTestBrowserActivity.setTopTestSuite(new TestSuite());
-
-        mTestBrowserActivity = createActivity();
-
-        ListView listView = getListView();
-        // There is always an item on the list for running all tests.
-        assertEquals("Unexpected number of items on list view.", 1, listView.getCount());
-
-        assertEquals("Stubbed Test Browser", mTestBrowserActivity.getTitle().toString());
-    }
-
-    public void testOneListContent() throws Exception {
-        List<String> testCaseNames = Lists.newArrayList("AllTests");
-        StubTestBrowserActivity.setTopTestSuite(createTestSuite(testCaseNames));
-
-        mTestBrowserActivity = createActivity();
-
-        ListView listView = getListView();
-        assertListViewContents(testCaseNames, listView);
-    }
-
-    public void testListWithTestCases() throws Exception {
-        List<String> testCaseNames = Lists.newArrayList("AllTests", "Apples", "Bananas", "Oranges");
-        StubTestBrowserActivity.setTopTestSuite(createTestSuite(testCaseNames));
-
-        mTestBrowserActivity = createActivity();
-
-        ListView listView = getListView();
-        assertListViewContents(testCaseNames, listView);
-    }
-
-    public void testListWithTestSuite() throws Exception {
-        List<String> testCaseNames = Lists.newArrayList(OneTestTestCase.class.getSimpleName());
-        StubTestBrowserActivity.setTopTestSuite(new OneTestInTestSuite());
-
-        mTestBrowserActivity = createActivity();
-
-        ListView listView = getListView();
-        assertListViewContents(testCaseNames, listView);
-    }
-
-    public void testSelectATestCase() throws Exception {
-        List<String> testCaseNames = Lists.newArrayList("AllTests");
-        TestSuite testSuite = createTestSuite(testCaseNames);
-        StubTestBrowserActivity.setTopTestSuite(testSuite);
-
-        mTestBrowserController.setTestCase(OneTestTestCase.class);
-        mTestBrowserActivity = createActivity();
-
-        Instrumentation.ActivityMonitor activityMonitor = getInstrumentation().addMonitor(
-                TestBrowserControllerImpl.TEST_RUNNER_ACTIVITY_CLASS_NAME, null, false);
-        try {
-            assertEquals(0, activityMonitor.getHits());
-
-            ListView listView = getListView();
-            int invokedTestCaseIndex = 0;
-            listView.performItemClick(listView, invokedTestCaseIndex, 0);
-
-            Activity activity = activityMonitor.waitForActivityWithTimeout(2000);
-            assertNotNull(activity);
-            try {
-                assertEquals(1, activityMonitor.getHits());
-                assertEquals(invokedTestCaseIndex, mTestBrowserController.getLastPosition());
-            } finally {
-                activity.finish();
-            }
-        } finally {
-            getInstrumentation().removeMonitor(activityMonitor);
-        }
-    }
-
-    public void testCreateFromIntentWithOneTest() throws Exception {
-        List<String> testCaseNames = Lists.newArrayList("testOne");
-
-        mTestBrowserActivity = launchTestBrowserActivity(new TestSuite(OneTestTestCase.class));
-
-        ListView listView = getListView();
-        assertListViewContents(testCaseNames, listView);
-    }
-
-    public void testUpdateListOnStart() throws Exception {
-        StubTestBrowserActivity.setTopTestSuite(new TestSuite());
-
-        mTestBrowserActivity = createActivity();
-
-        ListView listView = getListView();
-        assertEquals("Unexpected number of items on list view.", 1, listView.getCount());
-
-        List<String> testCaseNames = Lists.newArrayList("AllTests");
-        StubTestBrowserActivity.setTopTestSuite(createTestSuite(testCaseNames));
-
-        getInstrumentation().runOnMainSync(new Runnable() {
-            public void run() {
-                ((StubTestBrowserActivity) mTestBrowserActivity).onStart();
-            }
-        });
-
-        listView = getListView();
-        assertListViewContents(testCaseNames, listView);
-    }
-
-    public void testTitleHasTestSuiteName() throws Exception {
-        final String testSuiteName = "com.android.TestSuite";
-        StubTestBrowserActivity.setTopTestSuite(new TestSuite(testSuiteName));
-
-        mTestBrowserActivity = createActivity();
-
-        assertEquals("TestSuite", mTestBrowserActivity.getTitle().toString());
-    }
-    
-    private TestSuite createTestSuite(List<String> testCaseNames) {
-        return createTestSuite(testCaseNames.toArray(new String[testCaseNames.size()]));
-    }
-
-    private TestSuite createTestSuite(String... testCaseNames) {
-        TestSuite testSuite = new TestSuite();
-        for (String testCaseName : testCaseNames) {
-            testSuite.addTest(new FakeTestCase(testCaseName));
-        }
-
-        return testSuite;
-    }
-
-    public static class FakeTestCase extends TestCase {
-        public FakeTestCase(String name) {
-            super(name);
-        }
-    }
-
-    public static class OneTestTestCase extends TestCase {
-        public void testOne() throws Exception {
-        }
-    }
-
-    public static class OneTestInTestSuite extends TestSuite {
-        public static Test suite() {
-            TestSuite suite = new TestSuite(OneTestInTestSuite.class.getName());
-            suite.addTestSuite(OneTestTestCase.class);
-            return suite;
-        }
-    }
-
-    private void assertListViewContents(List<String> expectedTestCaseNames, ListView listView) {
-        assertEquals("Run All", listView.getItemAtPosition(0).toString());
-        assertEquals("Unexpected number of items on list view.",
-                expectedTestCaseNames.size() + 1, listView.getCount());
-        for (int i = 0; i < expectedTestCaseNames.size(); i++) {
-            String expectedTestCaseName = expectedTestCaseNames.get(i);
-            String actualTestCaseName = listView.getItemAtPosition(i + 1).toString();
-            assertEquals("Unexpected test case name. Index: " + i,
-                    expectedTestCaseName, actualTestCaseName);
-        }
-    }
-
-    private ListView getListView() {
-        return mTestBrowserActivity.getListView();
-    }
-
-    private TestBrowserActivity createActivity() throws RemoteException {
-        return launchActivity(getAndroidPackageName(), StubTestBrowserActivity.class, null);
-    }
-
-    private Intent createIntent(TestSuite testSuite) {
-        Intent intent = new Intent(Intent.ACTION_RUN);
-        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        String className = StubTestBrowserActivity.class.getName();
-        String packageName = getAndroidPackageName();
-        intent.setClassName(packageName, className);
-        intent.setData(Uri.parse(testSuite.getName()));
-        return intent;
-    }
-
-    private String getAndroidPackageName() {
-        String packageName = getInstrumentation().getTargetContext().getPackageName();
-        return packageName;
-    }
-
-    private TestBrowserActivity launchTestBrowserActivity(TestSuite testSuite)
-            throws RemoteException {
-        getInstrumentation().setInTouchMode(false);
-
-        TestBrowserActivity activity =
-                (TestBrowserActivity) getInstrumentation().startActivitySync(
-                        createIntent(testSuite));
-        getInstrumentation().waitForIdleSync();
-        return activity;
-    }
-
-    private static class StubTestBrowserController extends TestBrowserControllerImpl {
-        private int mPosition;
-        private Class<? extends TestCase> mTestCaseClass;
-
-        public Intent getIntentForTestAt(int position) {
-            mPosition = position;
-
-            Intent intent = new Intent();
-            intent.setAction(Intent.ACTION_RUN);
-
-            String className = TestBrowserControllerImpl.TEST_RUNNER_ACTIVITY_CLASS_NAME;
-            String testName = mTestCaseClass.getClass().getName();
-
-            String packageName = className.substring(0, className.lastIndexOf("."));
-            intent.setClassName(packageName, className);
-            intent.setData(Uri.parse(testName));
-
-            return intent;
-        }
-
-        public void setTestCase(Class<? extends TestCase> testCaseClass) {
-            mTestCaseClass = testCaseClass;
-        }
-
-        public int getLastPosition() {
-            return mPosition;
-        }
-    }
-}
diff --git a/test-runner/tests/src/android/test/TestBrowserControllerImplTest.java b/test-runner/tests/src/android/test/TestBrowserControllerImplTest.java
deleted file mode 100644
index 1315606..0000000
--- a/test-runner/tests/src/android/test/TestBrowserControllerImplTest.java
+++ /dev/null
@@ -1,134 +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.content.Intent;
-
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
-import java.util.Arrays;
-import java.util.List;
-
-public class TestBrowserControllerImplTest extends TestCase {
-    private TestBrowserControllerImpl mTestBrowserController;
-    private TestBrowserViewStub mTestBrowserView;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mTestBrowserController = new TestBrowserControllerImpl();
-        mTestBrowserView = new TestBrowserViewStub();
-        mTestBrowserController.registerView(mTestBrowserView);
-    }
-
-    public void testSetTestSuite() throws Exception {
-        TestSuite testSuite = new TestSuite();
-        testSuite.addTestSuite(DummyTestCase.class);
-
-        mTestBrowserController.setTestSuite(testSuite);
-
-        verifyTestNames(Arrays.asList("Run All", DummyTestCase.class.getSimpleName()),
-                mTestBrowserView.getTestNames());
-    }
-
-    private static void verifyTestNames(List<String> expectedTestNames,
-            List<String> actualTestNames) {
-        assertEquals(expectedTestNames.size(), actualTestNames.size());
-
-        // We use endsWith instead of equals because the return value of
-        // class.getSimpleName(), when called on an inner class, varies
-        // from one vm to another.
-        // This allows the test to pass in multiple environments.
-        for (int i = 0; i < expectedTestNames.size(); i++) {
-            assertTrue(actualTestNames.get(i).endsWith(expectedTestNames.get(i)));
-        }
-    }
-
-    public void testGetIntentForTestSuite() throws Exception {
-        TestSuite testSuite = new TestSuite();
-        testSuite.addTestSuite(DummyTestCase.class);
-
-        String targetBrowserActvityClassName = "com.android.bogus.DummyActivity";
-        String expectedTargetPackageName = "com.android.bogus";
-        mTestBrowserController.setTargetBrowserActivityClassName(targetBrowserActvityClassName);
-        mTestBrowserController.setTestSuite(testSuite);
-        mTestBrowserController.setTargetPackageName(expectedTargetPackageName);
-        Intent intent = mTestBrowserController.getIntentForTestAt(1);
-        verifyIntent(intent, DummyTestCase.class, expectedTargetPackageName);
-        assertEquals(targetBrowserActvityClassName, intent.getComponent().getClassName());
-    }
-
-    public void testGetIntentForTestCase() throws Exception {
-        TestSuite testSuite = new TestSuite();
-        testSuite.addTest(new DummyTestCase());
-
-        mTestBrowserController.setTestSuite(testSuite);
-        Intent intent = mTestBrowserController.getIntentForTestAt(1);
-        verifyIntent(intent, DummyTestCase.class, "com.android.testharness");
-        assertEquals(TestBrowserControllerImpl.TEST_RUNNER_ACTIVITY_CLASS_NAME,
-                intent.getComponent().getClassName());
-        assertEquals("testDummyTest",
-                intent.getStringExtra(TestBrowserController.BUNDLE_EXTRA_TEST_METHOD_NAME));
-    }
-
-    public void testGetIntentForRunAll() throws Exception {
-        TestSuite testSuite = new DummyTestSuite();
-        testSuite.addTestSuite(DummyTestCase.class);
-
-        mTestBrowserController.setTestSuite(testSuite);
-        Intent intent = mTestBrowserController.getIntentForTestAt(0);
-        verifyIntent(intent, DummyTestSuite.class, "com.android.testharness");
-    }
-
-    private static void verifyIntent(Intent intent, Class testClass, String expectedPackageName) {
-        assertEquals(Intent.ACTION_RUN, intent.getAction());
-        assertEquals(Intent.FLAG_ACTIVITY_NEW_TASK,
-                intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK);
-        assertEquals(Intent.FLAG_ACTIVITY_MULTIPLE_TASK,
-                intent.getFlags() & Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
-        assertEquals(testClass.getName(), intent.getData().toString());
-        assertEquals(expectedPackageName, intent.getComponent().getPackageName());
-    }
-
-    private static class DummyTestSuite extends TestSuite {
-        private DummyTestSuite() {
-            super(DummyTestSuite.class.getName());
-        }
-    }
-
-    private static class DummyTestCase extends TestCase {
-        private DummyTestCase() {
-            super("testDummyTest");
-        }
-
-        public void testDummyTest() throws Exception {
-        }
-    }
-
-    private class TestBrowserViewStub implements TestBrowserView {
-        private List<String> mTestNames;
-
-        public void setTestNames(List<String> testNames) {
-            mTestNames = testNames;
-        }
-
-        public List<String> getTestNames() {
-            return mTestNames;
-        }
-    }
-}
diff --git a/test-runner/tests/src/android/test/TestBrowserTests.java b/test-runner/tests/src/android/test/TestBrowserTests.java
deleted file mode 100644
index 535e2f8..0000000
--- a/test-runner/tests/src/android/test/TestBrowserTests.java
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2007 The Android Open Source Project
-
-
-package android.test;
-
-import junit.framework.TestSuite;
-
-public class TestBrowserTests extends TestBrowserActivity {
-
-    @Override
-    public TestSuite getTopTestSuite() {
-        return suite();
-    }
-
-    public static TestSuite suite() {
-        TestSuite testSuite = new TestSuite(TestBrowserTests.class.getName());
-        testSuite.addTestSuite(TestBrowserControllerImplTest.class);
-        testSuite.addTestSuite(TestCaseUtilTest.class);
-
-        return testSuite;
-    }
-}
diff --git a/tests/BiDiTests/res/layout/table_layout_ltr.xml b/tests/BiDiTests/res/layout/table_layout_ltr.xml
index 62b1819..f44de8e 100644
--- a/tests/BiDiTests/res/layout/table_layout_ltr.xml
+++ b/tests/BiDiTests/res/layout/table_layout_ltr.xml
@@ -34,13 +34,13 @@
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button2_text"
+                    android:text="@string/button_right_text"
                     android:textSize="24dip"
                     android:gravity="right"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button3_text"
+                    android:text="@string/button_after_text"
                     android:textSize="24dip"
                     android:gravity="after"
              />
@@ -49,18 +49,18 @@
         <TableRow>
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button4_text"
+                    android:text="@string/button2_text"
                     android:textSize="24dip"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button5_text"
+                    android:text="@string/button_left_text"
                     android:textSize="24dip"
                     android:gravity="left"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button6_text"
+                    android:text="@string/button_before_text"
                     android:textSize="24dip"
                     android:gravity="before"
              />
@@ -82,13 +82,13 @@
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button2_text"
+                    android:text="@string/button_right_text"
                     android:textSize="24dip"
                     android:gravity="right"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button3_text"
+                    android:text="@string/button_after_text"
                     android:textSize="24dip"
                     android:gravity="after"
              />
@@ -97,18 +97,18 @@
         <TableRow>
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button4_text"
+                    android:text="@string/button2_text"
                     android:textSize="24dip"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button5_text"
+                    android:text="@string/button_left_text"
                     android:textSize="24dip"
                     android:gravity="left"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button6_text"
+                    android:text="@string/button_before_text"
                     android:textSize="24dip"
                     android:gravity="before"
              />
@@ -130,13 +130,13 @@
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button2_text"
+                    android:text="@string/button_right_text"
                     android:textSize="24dip"
                     android:gravity="right"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button3_text"
+                    android:text="@string/button_after_text"
                     android:textSize="24dip"
                     android:gravity="after"
              />
@@ -145,18 +145,18 @@
         <TableRow>
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button4_text"
+                    android:text="@string/button2_text"
                     android:textSize="24dip"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button5_text"
+                    android:text="@string/button_left_text"
                     android:textSize="24dip"
                     android:gravity="left"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button6_text"
+                    android:text="@string/button_before_text"
                     android:textSize="24dip"
                     android:gravity="before"
              />
@@ -178,13 +178,13 @@
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button2_text"
+                    android:text="@string/button_right_text"
                     android:textSize="24dip"
                     android:gravity="right"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button3_text"
+                    android:text="@string/button_after_text"
                     android:textSize="24dip"
                     android:gravity="after"
              />
@@ -193,18 +193,18 @@
         <TableRow>
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button4_text"
+                    android:text="@string/button2_text"
                     android:textSize="24dip"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button5_text"
+                    android:text="@string/button_left_text"
                     android:textSize="24dip"
                     android:gravity="left"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button6_text"
+                    android:text="@string/button_before_text"
                     android:textSize="24dip"
                     android:gravity="before"
              />
diff --git a/tests/BiDiTests/res/layout/table_layout_rtl.xml b/tests/BiDiTests/res/layout/table_layout_rtl.xml
index 74e6286..84270ba 100644
--- a/tests/BiDiTests/res/layout/table_layout_rtl.xml
+++ b/tests/BiDiTests/res/layout/table_layout_rtl.xml
@@ -34,13 +34,13 @@
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button2_text"
+                    android:text="@string/button_right_text"
                     android:textSize="24dip"
                     android:gravity="right"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button3_text"
+                    android:text="@string/button_after_text"
                     android:textSize="24dip"
                     android:gravity="after"
              />
@@ -49,18 +49,18 @@
         <TableRow>
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button4_text"
+                    android:text="@string/button2_text"
                     android:textSize="24dip"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button5_text"
+                    android:text="@string/button_left_text"
                     android:textSize="24dip"
                     android:gravity="left"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button6_text"
+                    android:text="@string/button_before_text"
                     android:textSize="24dip"
                     android:gravity="before"
              />
@@ -82,13 +82,13 @@
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button2_text"
+                    android:text="@string/button_right_text"
                     android:textSize="24dip"
                     android:gravity="right"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button3_text"
+                    android:text="@string/button_after_text"
                     android:textSize="24dip"
                     android:gravity="after"
              />
@@ -97,18 +97,18 @@
         <TableRow>
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button4_text"
+                    android:text="@string/button2_text"
                     android:textSize="24dip"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button5_text"
+                    android:text="@string/button_left_text"
                     android:textSize="24dip"
                     android:gravity="left"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button6_text"
+                    android:text="@string/button_before_text"
                     android:textSize="24dip"
                     android:gravity="before"
              />
@@ -130,13 +130,13 @@
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button2_text"
+                    android:text="@string/button_right_text"
                     android:textSize="24dip"
                     android:gravity="right"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button3_text"
+                    android:text="@string/button_after_text"
                     android:textSize="24dip"
                     android:gravity="after"
              />
@@ -145,18 +145,18 @@
         <TableRow>
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button4_text"
+                    android:text="@string/button2_text"
                     android:textSize="24dip"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button5_text"
+                    android:text="@string/button_left_text"
                     android:textSize="24dip"
                     android:gravity="left"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button6_text"
+                    android:text="@string/button_before_text"
                     android:textSize="24dip"
                     android:gravity="before"
              />
@@ -178,13 +178,13 @@
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button2_text"
+                    android:text="@string/button_right_text"
                     android:textSize="24dip"
                     android:gravity="right"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button3_text"
+                    android:text="@string/button_after_text"
                     android:textSize="24dip"
                     android:gravity="after"
              />
@@ -193,18 +193,18 @@
         <TableRow>
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button4_text"
+                    android:text="@string/button2_text"
                     android:textSize="24dip"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button5_text"
+                    android:text="@string/button_left_text"
                     android:textSize="24dip"
                     android:gravity="left"
              />
             <Button android:layout_height="wrap_content"
                     android:layout_width="wrap_content"
-                    android:text="@string/button6_text"
+                    android:text="@string/button_before_text"
                     android:textSize="24dip"
                     android:gravity="before"
              />
diff --git a/tests/BiDiTests/res/values/strings.xml b/tests/BiDiTests/res/values/strings.xml
index 5af7a273..2aeb9e1 100644
--- a/tests/BiDiTests/res/values/strings.xml
+++ b/tests/BiDiTests/res/values/strings.xml
@@ -18,8 +18,10 @@
     <string name="button2_text">Button2</string>
     <string name="button3_text">Button3</string>
     <string name="button4_text">Button4</string>
-    <string name="button5_text">Button5</string>
-    <string name="button6_text">Button6</string>
+    <string name="button_right_text">Right</string>
+    <string name="button_after_text">After</string>
+    <string name="button_left_text">Left</string>
+    <string name="button_before_text">Before</string>
     <string name="button_requestlayout_text">Request Layout</string>
     <string name="textview_text">This is a text for a TextView</string>
     <string name="edittext_text">mmmmmmmmmmmmmmmmmmmmmmmm</string>
diff --git a/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java b/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java
index 2a40c57..01c1c70 100644
--- a/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java
+++ b/tests/DpiTest/src/com/google/android/test/dpi/DpiTestActivity.java
@@ -63,7 +63,8 @@
                     | ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS
                     | ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
                 app.getResources().setCompatibilityInfo(new CompatibilityInfo(ai,
-                        getResources().getConfiguration().screenLayout, false));
+                        getResources().getConfiguration().screenLayout,
+                        getResources().getConfiguration().smallestScreenWidthDp, false));
             }
         } catch (PackageManager.NameNotFoundException e) {
             throw new RuntimeException("ouch", e);
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 4894196..29d2b87 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -969,6 +969,11 @@
         return true;
     }
     
+    if (strcmp(name, "tvdpi") == 0) {
+        if (out) out->density = ResTable_config::DENSITY_TV;
+        return true;
+    }
+    
     if (strcmp(name, "hdpi") == 0) {
         if (out) out->density = ResTable_config::DENSITY_HIGH;
         return true;
diff --git a/wifi/java/android/net/wifi/SupplicantState.java b/wifi/java/android/net/wifi/SupplicantState.java
index 6b79210..91e685f 100644
--- a/wifi/java/android/net/wifi/SupplicantState.java
+++ b/wifi/java/android/net/wifi/SupplicantState.java
@@ -39,6 +39,15 @@
     DISCONNECTED,
 
     /**
+     * Interface is disabled
+     * <p/>
+     * This state is entered if the network interface is disabled.
+     * wpa_supplicant refuses any new operations that would
+     * use the radio until the interface has been enabled.
+     */
+    INTERFACE_DISABLED,
+
+    /**
      * Inactive state (wpa_supplicant disabled).
      * <p/>
      * This state is entered if there are no enabled networks in the
@@ -57,6 +66,15 @@
     SCANNING,
 
     /**
+     * Trying to authenticate with a BSS/SSID
+     * <p/>
+     * This state is entered when wpa_supplicant has found a suitable BSS
+     * to authenticate with and the driver is configured to try to
+     * authenticate with this BSS.
+     */
+    AUTHENTICATING,
+
+    /**
      * Trying to associate with a BSS/SSID.
      * <p/>
      * This state is entered when wpa_supplicant has found a suitable BSS
@@ -152,8 +170,33 @@
         return state != UNINITIALIZED && state != INVALID;
     }
 
+
+    /* Supplicant associating or authenticating is considered a handshake state */
+    static boolean isHandshakeState(SupplicantState state) {
+        switch(state) {
+            case AUTHENTICATING:
+            case ASSOCIATING:
+            case ASSOCIATED:
+            case FOUR_WAY_HANDSHAKE:
+            case GROUP_HANDSHAKE:
+                return true;
+            case COMPLETED:
+            case DISCONNECTED:
+            case INTERFACE_DISABLED:
+            case INACTIVE:
+            case SCANNING:
+            case DORMANT:
+            case UNINITIALIZED:
+            case INVALID:
+                return false;
+            default:
+                throw new IllegalArgumentException("Unknown supplicant state");
+        }
+    }
+
     static boolean isConnecting(SupplicantState state) {
         switch(state) {
+            case AUTHENTICATING:
             case ASSOCIATING:
             case ASSOCIATED:
             case FOUR_WAY_HANDSHAKE:
@@ -161,6 +204,7 @@
             case COMPLETED:
                 return true;
             case DISCONNECTED:
+            case INTERFACE_DISABLED:
             case INACTIVE:
             case SCANNING:
             case DORMANT:
diff --git a/wifi/java/android/net/wifi/SupplicantStateTracker.java b/wifi/java/android/net/wifi/SupplicantStateTracker.java
index 9ae26da..0c4f9f6 100644
--- a/wifi/java/android/net/wifi/SupplicantStateTracker.java
+++ b/wifi/java/android/net/wifi/SupplicantStateTracker.java
@@ -98,12 +98,16 @@
         if (DBG) Log.d(TAG, "Supplicant state: " + supState.toString() + "\n");
 
         switch (supState) {
-            case DISCONNECTED:
+           case DISCONNECTED:
                 transitionTo(mDisconnectState);
                 break;
+            case INTERFACE_DISABLED:
+                //we should have received a disconnection already, do nothing
+                break;
             case SCANNING:
                 transitionTo(mScanState);
                 break;
+            case AUTHENTICATING:
             case ASSOCIATING:
             case ASSOCIATED:
             case FOUR_WAY_HANDSHAKE:
@@ -250,10 +254,7 @@
                 case WifiStateMachine.SUPPLICANT_STATE_CHANGE_EVENT:
                     StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
                     SupplicantState state = stateChangeResult.state;
-                    if (state == SupplicantState.ASSOCIATING ||
-                            state == SupplicantState.ASSOCIATED ||
-                            state == SupplicantState.FOUR_WAY_HANDSHAKE ||
-                            state == SupplicantState.GROUP_HANDSHAKE) {
+                    if (SupplicantState.isHandshakeState(state)) {
                         if (mLoopDetectIndex > state.ordinal()) {
                             mLoopDetectCount++;
                         }
@@ -296,12 +297,11 @@
                     StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
                     SupplicantState state = stateChangeResult.state;
                     sendSupplicantStateChangedBroadcast(state, mAuthFailureInSupplicantBroadcast);
-                    /* Ignore a re-auth in completed state */
-                    if (state == SupplicantState.ASSOCIATING ||
-                            state == SupplicantState.ASSOCIATED ||
-                            state == SupplicantState.FOUR_WAY_HANDSHAKE ||
-                            state == SupplicantState.GROUP_HANDSHAKE ||
-                            state == SupplicantState.COMPLETED) {
+                    /* Ignore any connecting state in completed state. Group re-keying
+                     * events and other auth events that do not affect connectivity are
+                     * ignored
+                     */
+                    if (SupplicantState.isConnecting(state)) {
                         break;
                     }
                     transitionOnSupplicantStateChange(stateChangeResult);
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index f60ae48..e3661bf 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -41,8 +41,10 @@
 
     static {
         stateMap.put(SupplicantState.DISCONNECTED, DetailedState.DISCONNECTED);
+        stateMap.put(SupplicantState.INTERFACE_DISABLED, DetailedState.DISCONNECTED);
         stateMap.put(SupplicantState.INACTIVE, DetailedState.IDLE);
         stateMap.put(SupplicantState.SCANNING, DetailedState.SCANNING);
+        stateMap.put(SupplicantState.AUTHENTICATING, DetailedState.CONNECTING);
         stateMap.put(SupplicantState.ASSOCIATING, DetailedState.CONNECTING);
         stateMap.put(SupplicantState.ASSOCIATED, DetailedState.CONNECTING);
         stateMap.put(SupplicantState.FOUR_WAY_HANDSHAKE, DetailedState.AUTHENTICATING);