Merge "use quaternions instead of MRPs"
diff --git a/Android.mk b/Android.mk
index c838600..e987f91 100644
--- a/Android.mk
+++ b/Android.mk
@@ -110,7 +110,9 @@
 	core/java/android/net/IConnectivityManager.aidl \
 	core/java/android/net/INetworkManagementEventObserver.aidl \
 	core/java/android/net/IThrottleManager.aidl \
+	core/java/android/net/INetworkPolicyListener.aidl \
 	core/java/android/net/INetworkPolicyManager.aidl \
+	core/java/android/net/INetworkStatsService.aidl \
 	core/java/android/nfc/ILlcpConnectionlessSocket.aidl \
 	core/java/android/nfc/ILlcpServiceSocket.aidl \
 	core/java/android/nfc/ILlcpSocket.aidl \
@@ -123,7 +125,6 @@
 	core/java/android/os/IHardwareService.aidl \
 	core/java/android/os/IMessenger.aidl \
 	core/java/android/os/INetworkManagementService.aidl \
-	core/java/android/os/INetStatService.aidl \
 	core/java/android/os/IPermissionController.aidl \
 	core/java/android/os/IPowerManager.aidl \
     core/java/android/os/IRemoteCallback.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index b19bed0..1e59ff6 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -98,6 +98,7 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/nfc)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libstagefright_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/os)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/api/current.txt b/api/current.txt
index 9e87e9c..edce92a 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;
@@ -6814,6 +6818,7 @@
     method public void setCursorFactory(android.database.sqlite.SQLiteDatabase.CursorFactory);
     method public void setDistinct(boolean);
     method public void setProjectionMap(java.util.Map<java.lang.String, java.lang.String>);
+    method public void setStrict(boolean);
     method public void setTables(java.lang.String);
   }
 
@@ -11041,6 +11046,7 @@
     method public static android.net.NetworkInfo.DetailedState valueOf(java.lang.String);
     method public static final android.net.NetworkInfo.DetailedState[] values();
     enum_constant public static final android.net.NetworkInfo.DetailedState AUTHENTICATING;
+    enum_constant public static final android.net.NetworkInfo.DetailedState BLOCKED;
     enum_constant public static final android.net.NetworkInfo.DetailedState CONNECTED;
     enum_constant public static final android.net.NetworkInfo.DetailedState CONNECTING;
     enum_constant public static final android.net.NetworkInfo.DetailedState DISCONNECTED;
@@ -11594,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;
@@ -19890,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;
@@ -20970,6 +20979,8 @@
   }
 
   public abstract interface MenuItem {
+    method public abstract boolean collapseActionView();
+    method public abstract boolean expandActionView();
     method public abstract android.view.View getActionView();
     method public abstract char getAlphabeticShortcut();
     method public abstract int getGroupId();
@@ -20983,6 +20994,7 @@
     method public abstract java.lang.CharSequence getTitle();
     method public abstract java.lang.CharSequence getTitleCondensed();
     method public abstract boolean hasSubMenu();
+    method public abstract boolean isActionViewExpanded();
     method public abstract boolean isCheckable();
     method public abstract boolean isChecked();
     method public abstract boolean isEnabled();
@@ -20997,19 +21009,27 @@
     method public abstract android.view.MenuItem setIcon(int);
     method public abstract android.view.MenuItem setIntent(android.content.Intent);
     method public abstract android.view.MenuItem setNumericShortcut(char);
+    method public abstract android.view.MenuItem setOnActionExpandListener(android.view.MenuItem.OnActionExpandListener);
     method public abstract android.view.MenuItem setOnMenuItemClickListener(android.view.MenuItem.OnMenuItemClickListener);
     method public abstract android.view.MenuItem setShortcut(char, char);
     method public abstract void setShowAsAction(int);
+    method public abstract android.view.MenuItem setShowAsActionFlags(int);
     method public abstract android.view.MenuItem setTitle(java.lang.CharSequence);
     method public abstract android.view.MenuItem setTitle(int);
     method public abstract android.view.MenuItem setTitleCondensed(java.lang.CharSequence);
     method public abstract android.view.MenuItem setVisible(boolean);
     field public static final int SHOW_AS_ACTION_ALWAYS = 2; // 0x2
+    field public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = 8; // 0x8
     field public static final int SHOW_AS_ACTION_IF_ROOM = 1; // 0x1
     field public static final int SHOW_AS_ACTION_NEVER = 0; // 0x0
     field public static final int SHOW_AS_ACTION_WITH_TEXT = 4; // 0x4
   }
 
+  public static abstract interface MenuItem.OnActionExpandListener {
+    method public abstract boolean onMenuItemActionCollapse(android.view.MenuItem);
+    method public abstract boolean onMenuItemActionExpand(android.view.MenuItem);
+  }
+
   public static abstract interface MenuItem.OnMenuItemClickListener {
     method public abstract boolean onMenuItemClick(android.view.MenuItem);
   }
@@ -23177,6 +23197,7 @@
   public final class InputMethodSubtype implements android.os.Parcelable {
     method public boolean containsExtraValueKey(java.lang.String);
     method public int describeContents();
+    method public java.lang.CharSequence getDisplayName(android.content.Context, java.lang.String, android.content.pm.ApplicationInfo);
     method public java.lang.String getExtraValue();
     method public java.lang.String getExtraValueOf(java.lang.String);
     method public int getIconResId();
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/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 51f1e3d..73170bb 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -425,9 +425,6 @@
 
         registerService(WINDOW_SERVICE, new ServiceFetcher() {
                 public Object getService(ContextImpl ctx) {
-                    RuntimeException e = new RuntimeException("foo");
-                    e.fillInStackTrace();
-                    Log.i(TAG, "Getting window manager", e);
                     CompatibilityInfo ci = ctx.mResources.getCompatibilityInfo();
                     return WindowManagerImpl.getDefault(ci);
                 }});
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index e1c9044..26707c9 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -699,7 +699,7 @@
     public boolean cancelDiscovery() {
         if (getState() != STATE_ON) return false;
         try {
-            mService.cancelDiscovery();
+            return mService.cancelDiscovery();
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index a660bd7..aecec66 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1545,6 +1545,8 @@
     public static final String NETWORKMANAGEMENT_SERVICE = "network_management";
 
     /** {@hide} */
+    public static final String NETWORK_STATS_SERVICE = "netstats";
+    /** {@hide} */
     public static final String NETWORK_POLICY_SERVICE = "netpolicy";
 
     /**
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 dca53a8..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;
     }
 
     /**
@@ -392,8 +408,8 @@
             // compatible with large screens, so diddle it.
             CompatibilityInfo.updateCompatibleScreenFrame(inoutDm, null, inoutDm);
         } else {
-            inoutDm.widthPixels = inoutDm.realWidthPixels;
-            inoutDm.heightPixels = inoutDm.realHeightPixels;
+            inoutDm.widthPixels = inoutDm.unscaledWidthPixels;
+            inoutDm.heightPixels = inoutDm.unscaledHeightPixels;
         }
 
         if (isScalingRequired()) {
@@ -429,8 +445,8 @@
      */
     public static float updateCompatibleScreenFrame(DisplayMetrics dm,
             Rect outRect, DisplayMetrics outDm) {
-        final int width = dm.realWidthPixels;
-        final int height = dm.realHeightPixels;
+        final int width = dm.unscaledWidthPixels;
+        final int height = dm.unscaledHeightPixels;
         int shortSize, longSize;
         if (width < height) {
             shortSize = width;
@@ -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 b6aca2b..8f8eb6e 100644
--- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java
+++ b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
@@ -24,8 +24,8 @@
 
 import java.util.Iterator;
 import java.util.Map;
-import java.util.Set;
 import java.util.Map.Entry;
+import java.util.Set;
 import java.util.regex.Pattern;
 
 /**
@@ -43,7 +43,7 @@
     private StringBuilder mWhereClause = null;  // lazily created
     private boolean mDistinct;
     private SQLiteDatabase.CursorFactory mFactory;
-    private boolean mStrictProjectionMap;
+    private boolean mStrict;
 
     public SQLiteQueryBuilder() {
         mDistinct = false;
@@ -145,10 +145,28 @@
     }
 
     /**
-     * @hide
+     * 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)},
+     * non-numeric limits will raise an exception. If a projection map is specified, fields
+     * not in that map will be ignored.
+     * If this class is used to execute the statement directly using
+     * {@link #query(SQLiteDatabase, String[], String, String[], String, String, String)}
+     * or
+     * {@link #query(SQLiteDatabase, String[], String, String[], String, String, String, String)},
+     * additionally also parenthesis escaping selection are caught.
+     *
+     * To summarize: To get maximum protection against malicious third party apps (for example
+     * content provider consumers), make sure to do the following:
+     * <ul>
+     * <li>Set this value to true</li>
+     * <li>Use a projection map</li>
+     * <li>Use one of the query overloads instead of getting the statement as a sql string</li>
+     * </ul>
+     * By default, this value is false.
      */
-    public void setStrictProjectionMap(boolean flag) {
-        mStrictProjectionMap = flag;
+    public void setStrict(boolean flag) {
+        mStrict = flag;
     }
 
     /**
@@ -217,13 +235,6 @@
         }
     }
 
-    private static void appendClauseEscapeClause(StringBuilder s, String name, String clause) {
-        if (!TextUtils.isEmpty(clause)) {
-            s.append(name);
-            DatabaseUtils.appendEscapedSQLString(s, clause);
-        }
-    }
-
     /**
      * Add the names that are non-null in columns to s, separating
      * them with commas.
@@ -320,6 +331,19 @@
             return null;
         }
 
+        if (mStrict && selection != null && selection.length() > 0) {
+            // Validate the user-supplied selection to detect syntactic anomalies
+            // in the selection string that could indicate a SQL injection attempt.
+            // The idea is to ensure that the selection clause is a valid SQL expression
+            // by compiling it twice: once wrapped in parentheses and once as
+            // originally specified. An attacker cannot create an expression that
+            // would escape the SQL expression while maintaining balanced parentheses
+            // in both the wrapped and original forms.
+            String sqlForValidation = buildQuery(projectionIn, "(" + selection + ")", groupBy,
+                    having, sortOrder, limit);
+            validateSql(db, sqlForValidation); // will throw if query is invalid
+        }
+
         String sql = buildQuery(
                 projectionIn, selection, groupBy, having,
                 sortOrder, limit);
@@ -329,7 +353,20 @@
         }
         return db.rawQueryWithFactory(
                 mFactory, sql, selectionArgs,
-                SQLiteDatabase.findEditTable(mTables));
+                SQLiteDatabase.findEditTable(mTables)); // will throw if query is invalid
+    }
+
+    /**
+     * Verifies that a SQL statement is valid by compiling it.
+     * If the SQL statement is not valid, this method will throw a {@link SQLiteException}.
+     */
+    private void validateSql(SQLiteDatabase db, String sql) {
+        db.lock(sql);
+        try {
+            new SQLiteCompiledSql(db, sql).releaseSqlStatement();
+        } finally {
+            db.unlock();
+        }
     }
 
     /**
@@ -541,7 +578,7 @@
                         continue;
                     }
 
-                    if (!mStrictProjectionMap &&
+                    if (!mStrict &&
                             ( userColumn.contains(" AS ") || userColumn.contains(" as "))) {
                         /* A column alias already exist */
                         projection[i] = userColumn;
diff --git a/core/java/android/inputmethodservice/ExtractButton.java b/core/java/android/inputmethodservice/ExtractButton.java
index f91cd4e..b6b7595 100644
--- a/core/java/android/inputmethodservice/ExtractButton.java
+++ b/core/java/android/inputmethodservice/ExtractButton.java
@@ -41,6 +41,6 @@
      * highlight when selected.
      */
     @Override public boolean hasWindowFocus() {
-        return this.isEnabled() ? true : false;
+        return isEnabled() && getVisibility() == VISIBLE ? true : false;
     }
 }
diff --git a/core/java/android/inputmethodservice/ExtractEditLayout.java b/core/java/android/inputmethodservice/ExtractEditLayout.java
new file mode 100644
index 0000000..eafff49
--- /dev/null
+++ b/core/java/android/inputmethodservice/ExtractEditLayout.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.inputmethodservice;
+
+import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.view.menu.MenuPopupHelper;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.ActionMode;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+/**
+ * ExtractEditLayout provides an ActionMode presentation for the
+ * limited screen real estate in extract mode.
+ *
+ * @hide
+ */
+public class ExtractEditLayout extends LinearLayout {
+    ExtractActionMode mActionMode;
+    Button mExtractActionButton;
+    Button mEditButton;
+
+    public ExtractEditLayout(Context context) {
+        super(context);
+    }
+
+    public ExtractEditLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public ActionMode startActionModeForChild(View sourceView, ActionMode.Callback cb) {
+        final ExtractActionMode mode = new ExtractActionMode(cb);
+        if (mode.dispatchOnCreate()) {
+            mode.invalidate();
+            mExtractActionButton.setVisibility(INVISIBLE);
+            mEditButton.setVisibility(VISIBLE);
+            mActionMode = mode;
+            return mode;
+        }
+        return null;
+    }
+
+    @Override
+    public void onFinishInflate() {
+        super.onFinishInflate();
+        mExtractActionButton = (Button) findViewById(com.android.internal.R.id.inputExtractAction);
+        mEditButton = (Button) findViewById(com.android.internal.R.id.inputExtractEditButton);
+        mEditButton.setOnClickListener(new OnClickListener() {
+            public void onClick(View clicked) {
+                if (mActionMode != null) {
+                    new MenuPopupHelper(getContext(), mActionMode.mMenu, clicked).show();
+                }
+            }
+        });
+    }
+
+    private class ExtractActionMode extends ActionMode implements MenuBuilder.Callback {
+        private ActionMode.Callback mCallback;
+        MenuBuilder mMenu;
+
+        public ExtractActionMode(Callback cb) {
+            mMenu = new MenuBuilder(getContext());
+            mMenu.setCallback(this);
+            mCallback = cb;
+        }
+
+        @Override
+        public void setTitle(CharSequence title) {
+            // Title will not be shown.
+        }
+
+        @Override
+        public void setTitle(int resId) {
+            // Title will nor be shown.
+        }
+
+        @Override
+        public void setSubtitle(CharSequence subtitle) {
+            // Subtitle will not be shown.
+        }
+
+        @Override
+        public void setSubtitle(int resId) {
+            // Subtitle will not be shown.
+        }
+
+        @Override
+        public void setCustomView(View view) {
+            // Custom view is not supported here.
+        }
+
+        @Override
+        public void invalidate() {
+            mMenu.stopDispatchingItemsChanged();
+            try {
+                mCallback.onPrepareActionMode(this, mMenu);
+            } finally {
+                mMenu.startDispatchingItemsChanged();
+            }
+        }
+
+        public boolean dispatchOnCreate() {
+            mMenu.stopDispatchingItemsChanged();
+            try {
+                return mCallback.onCreateActionMode(this, mMenu);
+            } finally {
+                mMenu.startDispatchingItemsChanged();
+            }
+        }
+
+        @Override
+        public void finish() {
+            if (mActionMode != this) {
+                // Not the active action mode - no-op
+                return;
+            }
+
+            mCallback.onDestroyActionMode(this);
+            mCallback = null;
+
+            mExtractActionButton.setVisibility(VISIBLE);
+            mEditButton.setVisibility(INVISIBLE);
+
+            mActionMode = null;
+        }
+
+        @Override
+        public Menu getMenu() {
+            return mMenu;
+        }
+
+        @Override
+        public CharSequence getTitle() {
+            return null;
+        }
+
+        @Override
+        public CharSequence getSubtitle() {
+            return null;
+        }
+
+        @Override
+        public View getCustomView() {
+            return null;
+        }
+
+        @Override
+        public MenuInflater getMenuInflater() {
+            return new MenuInflater(getContext());
+        }
+
+        @Override
+        public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
+            return mCallback.onActionItemClicked(this, item);
+        }
+
+        @Override
+        public void onMenuModeChange(MenuBuilder menu) {
+        }
+
+    }
+}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 419288b..c72c4b0 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -22,7 +22,6 @@
 import android.os.RemoteException;
 
 import java.net.InetAddress;
-import java.net.UnknownHostException;
 
 /**
  * Class that answers queries about the state of network connectivity. It also
@@ -40,8 +39,9 @@
  * state of the available networks</li>
  * </ol>
  */
-public class ConnectivityManager
-{
+public class ConnectivityManager {
+    private static final String TAG = "ConnectivityManager";
+
     /**
      * A change in network connectivity has occurred. A connection has either
      * been established or lost. The NetworkInfo for the affected network is
@@ -109,7 +109,7 @@
      * The lookup key for an int that provides information about
      * our connection to the internet at large.  0 indicates no connection,
      * 100 indicates a great connection.  Retrieve it with
-     * {@link android.content.Intent@getIntExtra(String)}.
+     * {@link android.content.Intent#getIntExtra(String, int)}.
      * {@hide}
      */
     public static final String EXTRA_INET_CONDITION = "inetCondition";
@@ -120,13 +120,12 @@
      * <p>
      * If an application uses the network in the background, it should listen
      * for this broadcast and stop using the background data if the value is
-     * false.
+     * {@code false}.
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_BACKGROUND_DATA_SETTING_CHANGED =
             "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
 
-
     /**
      * Broadcast Action: The network connection may not be good
      * uses {@code ConnectivityManager.EXTRA_INET_CONDITION} and
@@ -255,7 +254,7 @@
 
     public static final int DEFAULT_NETWORK_PREFERENCE = TYPE_WIFI;
 
-    private IConnectivityManager mService;
+    private final IConnectivityManager mService;
 
     static public boolean isNetworkTypeValid(int networkType) {
         return networkType >= 0 && networkType <= MAX_NETWORK_TYPE;
@@ -284,6 +283,15 @@
         }
     }
 
+    /** {@hide} */
+    public NetworkInfo getActiveNetworkInfoForUid(int uid) {
+        try {
+            return mService.getActiveNetworkInfoForUid(uid);
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
     public NetworkInfo getNetworkInfo(int networkType) {
         try {
             return mService.getNetworkInfo(networkType);
@@ -300,7 +308,7 @@
         }
     }
 
-    /** @hide */
+    /** {@hide} */
     public LinkProperties getActiveLinkProperties() {
         try {
             return mService.getActiveLinkProperties();
@@ -309,7 +317,7 @@
         }
     }
 
-    /** @hide */
+    /** {@hide} */
     public LinkProperties getLinkProperties(int networkType) {
         try {
             return mService.getLinkProperties(networkType);
@@ -479,19 +487,11 @@
     }
 
     /**
-     * Don't allow use of default constructor.
-     */
-    @SuppressWarnings({"UnusedDeclaration"})
-    private ConnectivityManager() {
-    }
-
-    /**
      * {@hide}
      */
     public ConnectivityManager(IConnectivityManager service) {
         if (service == null) {
-            throw new IllegalArgumentException(
-                "ConnectivityManager() cannot be constructed with null service");
+            throw new IllegalArgumentException("missing IConnectivityManager");
         }
         mService = service;
     }
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 8be492c..647a60a 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -33,13 +33,11 @@
     int getNetworkPreference();
 
     NetworkInfo getActiveNetworkInfo();
-
+    NetworkInfo getActiveNetworkInfoForUid(int uid);
     NetworkInfo getNetworkInfo(int networkType);
-
     NetworkInfo[] getAllNetworkInfo();
 
     LinkProperties getActiveLinkProperties();
-
     LinkProperties getLinkProperties(int networkType);
 
     boolean setRadios(boolean onOff);
diff --git a/test-runner/src/android/test/TestBrowserView.java b/core/java/android/net/INetworkPolicyListener.aidl
similarity index 64%
rename from test-runner/src/android/test/TestBrowserView.java
rename to core/java/android/net/INetworkPolicyListener.aidl
index 4799f196..9230151 100644
--- a/test-runner/src/android/test/TestBrowserView.java
+++ b/core/java/android/net/INetworkPolicyListener.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 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.
@@ -14,14 +14,11 @@
  * limitations under the License.
  */
 
-package android.test;
+package android.net;
 
-import java.util.List;
+/** {@hide} */
+oneway interface INetworkPolicyListener {
 
-/**
- * @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);
+    void onRulesChanged(int uid, int uidRules);
+
 }
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index d9351ee..c1f3530 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -16,6 +16,8 @@
 
 package android.net;
 
+import android.net.INetworkPolicyListener;
+
 /**
  * Interface that creates and modifies network policy rules.
  *
@@ -26,6 +28,11 @@
     void setUidPolicy(int uid, int policy);
     int getUidPolicy(int uid);
 
+    boolean isUidForeground(int uid);
+
+    void registerListener(INetworkPolicyListener listener);
+    void unregisterListener(INetworkPolicyListener listener);
+
     // TODO: build API to surface stats details for settings UI
 
 }
diff --git a/test-runner/src/android/test/TestBrowserView.java b/core/java/android/net/INetworkStatsService.aidl
similarity index 64%
copy from test-runner/src/android/test/TestBrowserView.java
copy to core/java/android/net/INetworkStatsService.aidl
index 4799f196..6d57036 100644
--- a/test-runner/src/android/test/TestBrowserView.java
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 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.
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package android.test;
+package android.net;
 
-import java.util.List;
+import android.net.NetworkStatsHistory;
 
-/**
- * @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);
+/** {@hide} */
+interface INetworkStatsService {
+
+    NetworkStatsHistory[] getNetworkStatsSummary(int networkType);
+    NetworkStatsHistory getNetworkStatsUid(int uid);
+
 }
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index 5f5e11c..537750a 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -74,7 +74,9 @@
         /** IP traffic not available. */
         DISCONNECTED,
         /** Attempt to connect failed. */
-        FAILED
+        FAILED,
+        /** Access to this network is blocked. */
+        BLOCKED
     }
 
     /**
@@ -96,6 +98,7 @@
         stateMap.put(DetailedState.DISCONNECTING, State.DISCONNECTING);
         stateMap.put(DetailedState.DISCONNECTED, State.DISCONNECTED);
         stateMap.put(DetailedState.FAILED, State.DISCONNECTED);
+        stateMap.put(DetailedState.BLOCKED, State.DISCONNECTED);
     }
 
     private int mNetworkType;
@@ -138,6 +141,23 @@
         mIsRoaming = false;
     }
 
+    /** {@hide} */
+    public NetworkInfo(NetworkInfo source) {
+        if (source != null) {
+            mNetworkType = source.mNetworkType;
+            mSubtype = source.mSubtype;
+            mTypeName = source.mTypeName;
+            mSubtypeName = source.mSubtypeName;
+            mState = source.mState;
+            mDetailedState = source.mDetailedState;
+            mReason = source.mReason;
+            mExtraInfo = source.mExtraInfo;
+            mIsFailover = source.mIsFailover;
+            mIsRoaming = source.mIsRoaming;
+            mIsAvailable = source.mIsAvailable;
+        }
+    }
+
     /**
      * Reports the type of network (currently mobile or Wi-Fi) to which the
      * info in this object pertains.
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 1913aa7..dd7c1b0 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -19,6 +19,8 @@
 import android.content.Context;
 import android.os.RemoteException;
 
+import java.io.PrintWriter;
+
 /**
  * Manager for creating and modifying network policy rules.
  *
@@ -28,12 +30,13 @@
 
     /** No specific network policy, use system default. */
     public static final int POLICY_NONE = 0x0;
-    /** Reject network usage when application in background. */
-    public static final int POLICY_REJECT_BACKGROUND = 0x1;
-    /** Reject network usage on paid network connections. */
-    public static final int POLICY_REJECT_PAID = 0x2;
-    /** Application should conserve data. */
-    public static final int POLICY_CONSERVE_DATA = 0x4;
+    /** Reject network usage on paid networks when application in background. */
+    public static final int POLICY_REJECT_PAID_BACKGROUND = 0x1;
+
+    /** All network traffic should be allowed. */
+    public static final int RULE_ALLOW_ALL = 0x0;
+    /** Reject traffic on paid networks. */
+    public static final int RULE_REJECT_PAID = 0x1;
 
     private INetworkPolicyManager mService;
 
@@ -51,9 +54,8 @@
     /**
      * Set policy flags for specific UID.
      *
-     * @param policy {@link #POLICY_NONE} or combination of
-     *            {@link #POLICY_REJECT_BACKGROUND}, {@link #POLICY_REJECT_PAID},
-     *            or {@link #POLICY_CONSERVE_DATA}.
+     * @param policy {@link #POLICY_NONE} or combination of flags like
+     *            {@link #POLICY_REJECT_PAID_BACKGROUND}.
      */
     public void setUidPolicy(int uid, int policy) {
         try {
@@ -69,5 +71,23 @@
             return POLICY_NONE;
         }
     }
+    
+    /** {@hide} */
+    public static void dumpPolicy(PrintWriter fout, int policy) {
+        fout.write("[");
+        if ((policy & POLICY_REJECT_PAID_BACKGROUND) != 0) {
+            fout.write("REJECT_PAID_BACKGROUND");
+        }
+        fout.write("]");
+    }
+
+    /** {@hide} */
+    public static void dumpRules(PrintWriter fout, int rules) {
+        fout.write("[");
+        if ((rules & RULE_REJECT_PAID) != 0) {
+            fout.write("REJECT_PAID");
+        }
+        fout.write("]");
+    }
 
 }
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 0f207bc..588bf64 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -22,19 +22,22 @@
 
 import java.io.CharArrayWriter;
 import java.io.PrintWriter;
+import java.util.HashSet;
 
 /**
- * Collection of network statistics. Can contain summary details across all
- * interfaces, or details with per-UID granularity. Designed to parcel quickly
- * across process boundaries.
+ * Collection of active network statistics. Can contain summary details across
+ * all interfaces, or details with per-UID granularity. Internally stores data
+ * as a large table, closely matching {@code /proc/} data format. This structure
+ * optimizes for rapid in-memory comparison, but consider using
+ * {@link NetworkStatsHistory} when persisting.
  *
  * @hide
  */
 public class NetworkStats implements Parcelable {
-    /** {@link #iface} value when entry is summarized over all interfaces. */
+    /** {@link #iface} value when interface details unavailable. */
     public static final String IFACE_ALL = null;
-    /** {@link #uid} value when entry is summarized over all UIDs. */
-    public static final int UID_ALL = 0;
+    /** {@link #uid} value when UID details unavailable. */
+    public static final int UID_ALL = -1;
 
     // NOTE: data should only be accounted for once in this structure; if data
     // is broken out, the summarized version should not be included.
@@ -49,7 +52,7 @@
     public final long[] rx;
     public final long[] tx;
 
-    // TODO: add fg/bg stats and tag granularity
+    // TODO: add fg/bg stats once reported by kernel
 
     private NetworkStats(long elapsedRealtime, String[] iface, int[] uid, long[] rx, long[] tx) {
         this.elapsedRealtime = elapsedRealtime;
@@ -120,15 +123,35 @@
     }
 
     /**
+     * Return list of unique interfaces known by this data structure.
+     */
+    public String[] getKnownIfaces() {
+        final HashSet<String> ifaces = new HashSet<String>();
+        for (String iface : this.iface) {
+            if (iface != IFACE_ALL) {
+                ifaces.add(iface);
+            }
+        }
+        return ifaces.toArray(new String[ifaces.size()]);
+    }
+
+    /**
      * Subtract the given {@link NetworkStats}, effectively leaving the delta
      * between two snapshots in time. Assumes that statistics rows collect over
      * time, and that none of them have disappeared.
+     *
+     * @param enforceMonotonic Validate that incoming value is strictly
+     *            monotonic compared to this object.
      */
-    public NetworkStats subtract(NetworkStats value) {
-        // result will have our rows, but no meaningful timestamp
-        final int length = length();
-        final NetworkStats.Builder result = new NetworkStats.Builder(-1, length);
+    public NetworkStats subtract(NetworkStats value, boolean enforceMonotonic) {
+        final long deltaRealtime = this.elapsedRealtime - value.elapsedRealtime;
+        if (enforceMonotonic && deltaRealtime < 0) {
+            throw new IllegalArgumentException("found non-monotonic realtime");
+        }
 
+        // result will have our rows, and elapsed time between snapshots
+        final int length = length();
+        final NetworkStats.Builder result = new NetworkStats.Builder(deltaRealtime, length);
         for (int i = 0; i < length; i++) {
             final String iface = this.iface[i];
             final int uid = this.uid[i];
@@ -142,6 +165,9 @@
                 // existing row, subtract remote value
                 final long rx = this.rx[i] - value.rx[j];
                 final long tx = this.tx[i] - value.tx[j];
+                if (enforceMonotonic && (rx < 0 || tx < 0)) {
+                    throw new IllegalArgumentException("found non-monotonic values");
+                }
                 result.addEntry(iface, uid, rx, tx);
             }
         }
diff --git a/core/java/android/net/NetworkStatsHistory.aidl b/core/java/android/net/NetworkStatsHistory.aidl
new file mode 100644
index 0000000..8b9069f
--- /dev/null
+++ b/core/java/android/net/NetworkStatsHistory.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+parcelable NetworkStatsHistory;
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
new file mode 100644
index 0000000..b16101f
--- /dev/null
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.io.CharArrayWriter;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Arrays;
+
+/**
+ * Collection of historical network statistics, recorded into equally-sized
+ * "buckets" in time. Internally it stores data in {@code long} series for more
+ * efficient persistence.
+ * <p>
+ * Each bucket is defined by a {@link #bucketStart} timestamp, and lasts for
+ * {@link #bucketDuration}. Internally assumes that {@link #bucketStart} is
+ * sorted at all times.
+ *
+ * @hide
+ */
+public class NetworkStatsHistory implements Parcelable {
+    private static final int VERSION = 1;
+
+    /** {@link #uid} value when UID details unavailable. */
+    public static final int UID_ALL = -1;
+
+    // TODO: teach about zigzag encoding to use less disk space
+    // TODO: teach how to convert between bucket sizes
+
+    public final int networkType;
+    public final String identity;
+    public final int uid;
+    public final long bucketDuration;
+
+    int bucketCount;
+    long[] bucketStart;
+    long[] rx;
+    long[] tx;
+
+    public NetworkStatsHistory(int networkType, String identity, int uid, long bucketDuration) {
+        this.networkType = networkType;
+        this.identity = identity;
+        this.uid = uid;
+        this.bucketDuration = bucketDuration;
+        bucketStart = new long[0];
+        rx = new long[0];
+        tx = new long[0];
+        bucketCount = bucketStart.length;
+    }
+
+    public NetworkStatsHistory(Parcel in) {
+        networkType = in.readInt();
+        identity = in.readString();
+        uid = in.readInt();
+        bucketDuration = in.readLong();
+        bucketStart = readLongArray(in);
+        rx = in.createLongArray();
+        tx = in.createLongArray();
+        bucketCount = bucketStart.length;
+    }
+
+    /** {@inheritDoc} */
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(networkType);
+        out.writeString(identity);
+        out.writeInt(uid);
+        out.writeLong(bucketDuration);
+        writeLongArray(out, bucketStart, bucketCount);
+        writeLongArray(out, rx, bucketCount);
+        writeLongArray(out, tx, bucketCount);
+    }
+
+    public NetworkStatsHistory(DataInputStream in) throws IOException {
+        final int version = in.readInt();
+        networkType = in.readInt();
+        identity = in.readUTF();
+        uid = in.readInt();
+        bucketDuration = in.readLong();
+        bucketStart = readLongArray(in);
+        rx = readLongArray(in);
+        tx = readLongArray(in);
+        bucketCount = bucketStart.length;
+    }
+
+    public void writeToStream(DataOutputStream out) throws IOException {
+        out.writeInt(VERSION);
+        out.writeInt(networkType);
+        out.writeUTF(identity);
+        out.writeInt(uid);
+        out.writeLong(bucketDuration);
+        writeLongArray(out, bucketStart, bucketCount);
+        writeLongArray(out, rx, bucketCount);
+        writeLongArray(out, tx, bucketCount);
+    }
+
+    /** {@inheritDoc} */
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Record that data traffic occurred in the given time range. Will
+     * distribute across internal buckets, creating new buckets as needed.
+     */
+    public void recordData(long start, long end, long rx, long tx) {
+        // create any buckets needed by this range
+        ensureBuckets(start, end);
+
+        // distribute data usage into buckets
+        final long duration = end - start;
+        for (int i = bucketCount - 1; i >= 0; i--) {
+            final long curStart = bucketStart[i];
+            final long curEnd = curStart + bucketDuration;
+
+            // bucket is older than record; we're finished
+            if (curEnd < start) break;
+            // bucket is newer than record; keep looking
+            if (curStart > end) continue;
+
+            final long overlap = Math.min(curEnd, end) - Math.max(curStart, start);
+            if (overlap > 0) {
+                this.rx[i] += rx * overlap / duration;
+                this.tx[i] += tx * overlap / duration;
+            }
+        }
+    }
+
+    /**
+     * Ensure that buckets exist for given time range, creating as needed.
+     */
+    private void ensureBuckets(long start, long end) {
+        // normalize incoming range to bucket boundaries
+        start -= start % bucketDuration;
+        end += (bucketDuration - (end % bucketDuration)) % bucketDuration;
+
+        for (long now = start; now < end; now += bucketDuration) {
+            // try finding existing bucket
+            final int index = Arrays.binarySearch(bucketStart, 0, bucketCount, now);
+            if (index < 0) {
+                // bucket missing, create and insert
+                insertBucket(~index, now);
+            }
+        }
+    }
+
+    /**
+     * Insert new bucket at requested index and starting time.
+     */
+    private void insertBucket(int index, long start) {
+        // create more buckets when needed
+        if (bucketCount + 1 > bucketStart.length) {
+            final int newLength = bucketStart.length + 10;
+            bucketStart = Arrays.copyOf(bucketStart, newLength);
+            rx = Arrays.copyOf(rx, newLength);
+            tx = Arrays.copyOf(tx, newLength);
+        }
+
+        // create gap when inserting bucket in middle
+        if (index < bucketCount) {
+            final int dstPos = index + 1;
+            final int length = bucketCount - index;
+
+            System.arraycopy(bucketStart, index, bucketStart, dstPos, length);
+            System.arraycopy(rx, index, rx, dstPos, length);
+            System.arraycopy(tx, index, tx, dstPos, length);
+        }
+
+        bucketStart[index] = start;
+        rx[index] = 0;
+        tx[index] = 0;
+        bucketCount++;
+    }
+
+    /**
+     * Remove buckets older than requested cutoff.
+     */
+    public void removeBucketsBefore(long cutoff) {
+        int i;
+        for (i = 0; i < bucketCount; i++) {
+            final long curStart = bucketStart[i];
+            final long curEnd = curStart + bucketDuration;
+
+            // cutoff happens before or during this bucket; everything before
+            // this bucket should be removed.
+            if (curEnd > cutoff) break;
+        }
+
+        if (i > 0) {
+            final int length = bucketStart.length;
+            bucketStart = Arrays.copyOfRange(bucketStart, i, length);
+            rx = Arrays.copyOfRange(rx, i, length);
+            tx = Arrays.copyOfRange(tx, i, length);
+            bucketCount -= i;
+        }
+    }
+
+    public void dump(String prefix, PrintWriter pw) {
+        // TODO: consider stripping identity when dumping
+        pw.print(prefix);
+        pw.print("NetworkStatsHistory: networkType="); pw.print(networkType);
+        pw.print(" identity="); pw.print(identity);
+        pw.print(" uid="); pw.println(uid);
+        for (int i = 0; i < bucketCount; i++) {
+            pw.print(prefix);
+            pw.print("  timestamp="); pw.print(bucketStart[i]);
+            pw.print(" rx="); pw.print(rx[i]);
+            pw.print(" tx="); pw.println(tx[i]);
+        }
+    }
+
+    @Override
+    public String toString() {
+        final CharArrayWriter writer = new CharArrayWriter();
+        dump("", new PrintWriter(writer));
+        return writer.toString();
+    }
+
+    public static final Creator<NetworkStatsHistory> CREATOR = new Creator<NetworkStatsHistory>() {
+        public NetworkStatsHistory createFromParcel(Parcel in) {
+            return new NetworkStatsHistory(in);
+        }
+
+        public NetworkStatsHistory[] newArray(int size) {
+            return new NetworkStatsHistory[size];
+        }
+    };
+
+    private static long[] readLongArray(DataInputStream in) throws IOException {
+        final int size = in.readInt();
+        final long[] values = new long[size];
+        for (int i = 0; i < values.length; i++) {
+            values[i] = in.readLong();
+        }
+        return values;
+    }
+
+    private static void writeLongArray(DataOutputStream out, long[] values, int size) throws IOException {
+        if (size > values.length) {
+            throw new IllegalArgumentException("size larger than length");
+        }
+        out.writeInt(size);
+        for (int i = 0; i < size; i++) {
+            out.writeLong(values[i]);
+        }
+    }
+
+    private static long[] readLongArray(Parcel in) {
+        final int size = in.readInt();
+        final long[] values = new long[size];
+        for (int i = 0; i < values.length; i++) {
+            values[i] = in.readLong();
+        }
+        return values;
+    }
+
+    private static void writeLongArray(Parcel out, long[] values, int size) {
+        if (size > values.length) {
+            throw new IllegalArgumentException("size larger than length");
+        }
+        out.writeInt(size);
+        for (int i = 0; i < size; i++) {
+            out.writeLong(values[i]);
+        }
+    }
+
+}
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index c0ff734..8ab64fa 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -141,7 +141,8 @@
 
             // subtract starting values and return delta
             final NetworkStats profilingStop = getNetworkStatsForUid(context);
-            final NetworkStats profilingDelta = profilingStop.subtract(sActiveProfilingStart);
+            final NetworkStats profilingDelta = profilingStop.subtract(
+                    sActiveProfilingStart, false);
             sActiveProfilingStart = null;
             return profilingDelta;
         }
diff --git a/core/java/android/os/INetStatService.aidl b/core/java/android/os/INetStatService.aidl
deleted file mode 100644
index a8f3de0..0000000
--- a/core/java/android/os/INetStatService.aidl
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-/**
- * Retrieves packet and byte counts for the phone data interface,
- * and for all interfaces.
- * Used for the data activity icon and the phone status in Settings.
- *
- * {@hide}
- */
-interface INetStatService {
-    long getMobileTxPackets();
-    long getMobileRxPackets();
-    long getMobileTxBytes();
-    long getMobileRxBytes();
-    long getTotalTxPackets();
-    long getTotalRxPackets();
-    long getTotalTxBytes();
-    long getTotalRxBytes();
-}
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/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index 8018ff9..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;
@@ -105,10 +114,18 @@
      */
     public float ydpi;
 
-    /** @hide */
-    public int realWidthPixels;
-    /** @hide */
-    public int realHeightPixels;
+    /**
+     * The reported display width prior to any compatibility mode scaling
+     * being applied.
+     * @hide
+     */
+    public int unscaledWidthPixels;
+    /**
+     * The reported display height prior to any compatibility mode scaling
+     * being applied.
+     * @hide
+     */
+    public int unscaledHeightPixels;
 
     public DisplayMetrics() {
     }
@@ -121,8 +138,8 @@
         scaledDensity = o.scaledDensity;
         xdpi = o.xdpi;
         ydpi = o.ydpi;
-        realWidthPixels = o.realWidthPixels;
-        realHeightPixels = o.realHeightPixels;
+        unscaledWidthPixels = o.unscaledWidthPixels;
+        unscaledHeightPixels = o.unscaledHeightPixels;
     }
     
     public void setToDefaults() {
@@ -133,8 +150,8 @@
         scaledDensity = density;
         xdpi = DENSITY_DEVICE;
         ydpi = DENSITY_DEVICE;
-        realWidthPixels = 0;
-        realHeightPixels = 0;
+        unscaledWidthPixels = 0;
+        unscaledHeightPixels = 0;
     }
 
     @Override
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index b5d36d9..8032546 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -80,25 +80,37 @@
      * adjusted for you based on the current rotation of the display.
      */
     public void getSize(Point outSize) {
+        getSizeInternal(outSize, true);
+    }
+
+    /**
+     * Returns the raw size of the display, in pixels.  Note that this
+     * should <em>not</em> generally be used for computing layouts, since
+     * a device will typically have screen decoration (such as a status bar)
+     * along the edges of the display that reduce the amount of application
+     * space available from the raw size returned here.  This value is
+     * adjusted for you based on the current rotation of the display.
+     */
+    private void getSizeInternal(Point outSize, boolean doCompat) {
         try {
             IWindowManager wm = getWindowManager();
             if (wm != null) {
                 wm.getDisplaySize(outSize);
+                if (doCompat && mCompatibilityInfo != null) {
+                    synchronized (mTmpMetrics) {
+                        mTmpMetrics.unscaledWidthPixels = outSize.x;
+                        mTmpMetrics.unscaledHeightPixels = outSize.y;
+                        mTmpMetrics.density = mDensity;
+                        mCompatibilityInfo.applyToDisplayMetrics(mTmpMetrics);
+                        outSize.x = mTmpMetrics.widthPixels;
+                        outSize.y = mTmpMetrics.heightPixels;
+                    }
+                }
             } else {
                 // This is just for boot-strapping, initializing the
                 // system process before the window manager is up.
                 outSize.y = getRealHeight();
             }
-            if (mCompatibilityInfo != null) {
-                synchronized (mTmpMetrics) {
-                    mTmpMetrics.realWidthPixels = outSize.x;
-                    mTmpMetrics.realHeightPixels = outSize.y;
-                    mTmpMetrics.density = mDensity;
-                    mCompatibilityInfo.applyToDisplayMetrics(mTmpMetrics);
-                    outSize.x = mTmpMetrics.widthPixels;
-                    outSize.y = mTmpMetrics.heightPixels;
-                }
-            }
         } catch (RemoteException e) {
             Slog.w("Display", "Unable to get display size", e);
         }
@@ -109,7 +121,7 @@
      */
     public void getRectSize(Rect outSize) {
         synchronized (mTmpPoint) {
-            getSize(mTmpPoint);
+            getSizeInternal(mTmpPoint, true);
             outSize.set(0, 0, mTmpPoint.x, mTmpPoint.y);
         }
     }
@@ -137,7 +149,7 @@
         synchronized (mTmpPoint) {
             long now = SystemClock.uptimeMillis();
             if (now > (mLastGetTime+20)) {
-                getSize(mTmpPoint);
+                getSizeInternal(mTmpPoint, true);
                 mLastGetTime = now;
             }
             return mTmpPoint.x;
@@ -152,7 +164,7 @@
         synchronized (mTmpPoint) {
             long now = SystemClock.uptimeMillis();
             if (now > (mLastGetTime+20)) {
-                getSize(mTmpPoint);
+                getSizeInternal(mTmpPoint, true);
                 mLastGetTime = now;
             }
             return mTmpPoint.y;
@@ -218,7 +230,7 @@
      */
     public void getMetrics(DisplayMetrics outMetrics) {
         synchronized (mTmpPoint) {
-            getSize(mTmpPoint);
+            getSizeInternal(mTmpPoint, false);
             outMetrics.widthPixels = mTmpPoint.x;
             outMetrics.heightPixels = mTmpPoint.y;
         }
@@ -248,8 +260,8 @@
         outMetrics.xdpi         = mDpiX;
         outMetrics.ydpi         = mDpiY;
 
-        outMetrics.realWidthPixels  = outMetrics.widthPixels;
-        outMetrics.realHeightPixels = outMetrics.heightPixels;
+        outMetrics.unscaledWidthPixels  = outMetrics.widthPixels;
+        outMetrics.unscaledHeightPixels = outMetrics.heightPixels;
     }
 
     static IWindowManager getWindowManager() {
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/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index adafb59..bdf04ab0 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -59,6 +59,9 @@
     void setForcedDisplaySize(int longDimen, int shortDimen);
     void clearForcedDisplaySize();
 
+    // Is device configured with a hideable status bar or a tablet system bar?
+    boolean canStatusBarHide();
+
     // These can only be called when injecting events to your own window,
     // or by holding the INJECT_EVENTS permission.  These methods may block
     // until pending input events are finished being dispatched even when 'sync' is false.
diff --git a/core/java/android/view/MenuItem.java b/core/java/android/view/MenuItem.java
index 780c52e..dc68264 100644
--- a/core/java/android/view/MenuItem.java
+++ b/core/java/android/view/MenuItem.java
@@ -51,6 +51,13 @@
      * it also has an icon specified.
      */
     public static final int SHOW_AS_ACTION_WITH_TEXT = 4;
+
+    /**
+     * This item's action view collapses to a normal menu item.
+     * When expanded, the action view temporarily takes over
+     * a larger segment of its container.
+     */
+    public static final int SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW = 8;
     
     /**
      * Interface definition for a callback to be invoked when a menu item is
@@ -74,6 +81,34 @@
     }
 
     /**
+     * Interface definition for a callback to be invoked when a menu item
+     * marked with {@link MenuItem#SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW} is
+     * expanded or collapsed.
+     *
+     * @see MenuItem#expandActionView()
+     * @see MenuItem#collapseActionView()
+     * @see MenuItem#setShowAsActionFlags(int)
+     * @see MenuItem#
+     */
+    public interface OnActionExpandListener {
+        /**
+         * Called when a menu item with {@link MenuItem#SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW}
+         * is expanded.
+         * @param item Item that was expanded
+         * @return true if the item should expand, false if expansion should be suppressed.
+         */
+        public boolean onMenuItemActionExpand(MenuItem item);
+
+        /**
+         * Called when a menu item with {@link MenuItem#SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW}
+         * is collapsed.
+         * @param item Item that was collapsed
+         * @return true if the item should collapse, false if collapsing should be suppressed.
+         */
+        public boolean onMenuItemActionCollapse(MenuItem item);
+    }
+
+    /**
      * Return the identifier for this menu item.  The identifier can not
      * be changed after the menu is created.
      *
@@ -421,6 +456,27 @@
     public void setShowAsAction(int actionEnum);
 
     /**
+     * Sets how this item should display in the presence of an Action Bar.
+     * The parameter actionEnum is a flag set. One of {@link #SHOW_AS_ACTION_ALWAYS},
+     * {@link #SHOW_AS_ACTION_IF_ROOM}, or {@link #SHOW_AS_ACTION_NEVER} should
+     * be used, and you may optionally OR the value with {@link #SHOW_AS_ACTION_WITH_TEXT}.
+     * SHOW_AS_ACTION_WITH_TEXT requests that when the item is shown as an action,
+     * it should be shown with a text label.
+     *
+     * <p>Note: This method differs from {@link #setShowAsAction(int)} only in that it
+     * returns the current MenuItem instance for call chaining.
+     *
+     * @param actionEnum How the item should display. One of
+     * {@link #SHOW_AS_ACTION_ALWAYS}, {@link #SHOW_AS_ACTION_IF_ROOM}, or
+     * {@link #SHOW_AS_ACTION_NEVER}. SHOW_AS_ACTION_NEVER is the default.
+     *
+     * @see android.app.ActionBar
+     * @see #setActionView(View)
+     * @return This MenuItem instance for call chaining.
+     */
+    public MenuItem setShowAsActionFlags(int actionEnum);
+
+    /**
      * Set an action view for this menu item. An action view will be displayed in place
      * of an automatically generated menu item element in the UI when this item is shown
      * as an action within a parent.
@@ -453,4 +509,52 @@
      * @see #setShowAsAction(int)
      */
     public View getActionView();
+
+    /**
+     * Expand the action view associated with this menu item.
+     * The menu item must have an action view set, as well as
+     * the showAsAction flag {@link #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW}.
+     * If a listener has been set using {@link #setOnActionExpandListener(OnActionExpandListener)}
+     * it will have its {@link OnActionExpandListener#onMenuItemActionExpand(MenuItem)}
+     * method invoked. The listener may return false from this method to prevent expanding
+     * the action view.
+     *
+     * @return true if the action view was expanded, false otherwise.
+     */
+    public boolean expandActionView();
+
+    /**
+     * Collapse the action view associated with this menu item.
+     * The menu item must have an action view set, as well as the showAsAction flag
+     * {@link #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW}. If a listener has been set using
+     * {@link #setOnActionExpandListener(OnActionExpandListener)} it will have its
+     * {@link OnActionExpandListener#onMenuItemActionCollapse(MenuItem)} method invoked.
+     * The listener may return false from this method to prevent collapsing the action view.
+     *
+     * @return true if the action view was collapsed, false otherwise.
+     */
+    public boolean collapseActionView();
+
+    /**
+     * Returns true if this menu item's action view has been expanded.
+     *
+     * @return true if the item's action view is expanded, false otherwise.
+     *
+     * @see #expandActionView()
+     * @see #collapseActionView()
+     * @see #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW
+     * @see OnActionExpandListener
+     */
+    public boolean isActionViewExpanded();
+
+    /**
+     * Set an {@link OnActionExpandListener} on this menu item to be notified when
+     * the associated action view is expanded or collapsed. The menu item must
+     * be configured to expand or collapse its action view using the flag
+     * {@link #SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW}.
+     *
+     * @param listener Listener that will respond to expand/collapse events
+     * @return This menu item instance for call chaining
+     */
+    public MenuItem setOnActionExpandListener(OnActionExpandListener listener);
 }
\ No newline at end of file
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/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 64b1ac8..82a4d2d 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -466,6 +466,12 @@
     public int getMaxWallpaperLayer();
     
     /**
+     * Return true if the policy allows the status bar to hide.  Otherwise,
+     * it is a tablet-style system bar.
+     */
+    public boolean canStatusBarHide();
+
+    /**
      * Return the display width available after excluding any screen
      * decorations that can never be removed.  That is, system bar or
      * button bar.
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index 1f7441d..fee69e0 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -145,7 +145,9 @@
                             a.getString(com.android.internal.R.styleable
                                     .InputMethod_Subtype_imeSubtypeMode),
                             a.getString(com.android.internal.R.styleable
-                                    .InputMethod_Subtype_imeSubtypeExtraValue));
+                                    .InputMethod_Subtype_imeSubtypeExtraValue),
+                            a.getBoolean(com.android.internal.R.styleable
+                                    .InputMethod_Subtype_isAuxiliary, false));
                     mSubtypes.add(subtype);
                 }
             }
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/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index de38fbe..20cf93d 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -17,8 +17,10 @@
 package android.view.inputmethod;
 
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.TextUtils;
 import android.util.Slog;
 
 import java.util.ArrayList;
@@ -137,6 +139,31 @@
         return mIsAuxiliary;
     }
 
+    /**
+     * @param context Context will be used for getting Locale and PackageManager.
+     * @param packageName The package name of the IME
+     * @param appInfo The application info of the IME
+     * @return a display name for this subtype. The string resource of the label (mSubtypeNameResId)
+     * can have only one %s in it. If there is, the %s part will be replaced with the locale's
+     * display name by the formatter. If there is not, this method simply returns the string
+     * specified by mSubtypeNameResId. If mSubtypeNameResId is not specified (== 0), it's up to the
+     * framework to generate an appropriate display name.
+     */
+    public CharSequence getDisplayName(
+            Context context, String packageName, ApplicationInfo appInfo) {
+        final String locale = context.getResources().getConfiguration().locale.getDisplayName();
+        if (mSubtypeNameResId == 0) {
+            return locale;
+        }
+        final String subtypeName = context.getPackageManager().getText(
+                packageName, mSubtypeNameResId, appInfo).toString();
+        if (!TextUtils.isEmpty(subtypeName)) {
+            return String.format(subtypeName, locale);
+        } else {
+            return locale;
+        }
+    }
+
     private HashMap<String, String> getExtraValueHashMap() {
         if (mExtraValueHashMapCache == null) {
             mExtraValueHashMapCache = new HashMap<String, String>();
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/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index 2a1398d..4ee16e7 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -16,6 +16,8 @@
 
 package android.widget;
 
+import java.util.ArrayList;
+
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
@@ -23,14 +25,12 @@
 import android.graphics.Region;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
+import android.view.Gravity;
 import android.view.View;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
-import android.view.Gravity;
 import android.widget.RemoteViews.RemoteView;
 
-import java.util.ArrayList;
-
 
 /**
  * FrameLayout is designed to block out an area on the screen to display
@@ -364,10 +364,10 @@
                     gravity = DEFAULT_CHILD_GRAVITY;
                 }
 
-                final int horizontalGravity = Gravity.getAbsoluteGravity(gravity, isLayoutRtl());
+                final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, isLayoutRtl());
                 final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
 
-                switch (horizontalGravity) {
+                switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
                     case Gravity.LEFT:
                         childLeft = parentLeft + lp.leftMargin;
                         break;
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 8d449e0..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;
 
@@ -1430,8 +1446,8 @@
                 if (gravity < 0) {
                     gravity = minorGravity;
                 }
-                gravity = Gravity.getAbsoluteGravity(gravity, isLayoutRtl());
-                switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
+                final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, isLayoutRtl());
+                switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
                     case Gravity.CENTER_HORIZONTAL:
                         childLeft = paddingLeft + ((childSpace - childWidth) / 2)
                                 + lp.leftMargin - lp.rightMargin;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5886c64..9592d0c 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -2565,6 +2565,9 @@
                     sp.removeSpan(cw);
                 }
 
+                // hideControllers would do it, but it gets called after this method on rotation
+                sp.removeSpan(mSuggestionRangeSpan);
+
                 ss.text = sp;
             } else {
                 ss.text = mText.toString();
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 6cfeb87..dda3be6 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -362,8 +362,8 @@
         }
 
         mContextView.killMode();
-        ActionMode mode = new ActionModeImpl(callback);
-        if (callback.onCreateActionMode(mode, mode.getMenu())) {
+        ActionModeImpl mode = new ActionModeImpl(callback);
+        if (mode.dispatchOnCreate()) {
             mWasHiddenBeforeMode = !isShowing();
             mode.invalidate();
             mContextView.initForMode(mode);
@@ -633,8 +633,20 @@
 
         @Override
         public void invalidate() {
-            if (mCallback.onPrepareActionMode(this, mMenu)) {
-                // Refresh content in both context views
+            mMenu.stopDispatchingItemsChanged();
+            try {
+                mCallback.onPrepareActionMode(this, mMenu);
+            } finally {
+                mMenu.startDispatchingItemsChanged();
+            }
+        }
+
+        public boolean dispatchOnCreate() {
+            mMenu.stopDispatchingItemsChanged();
+            try {
+                return mCallback.onCreateActionMode(this, mMenu);
+            } finally {
+                mMenu.startDispatchingItemsChanged();
             }
         }
 
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/view/menu/ActionMenuItem.java b/core/java/com/android/internal/view/menu/ActionMenuItem.java
index 0ef4861..a4bcf60 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItem.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItem.java
@@ -236,4 +236,31 @@
     public MenuItem setActionView(int resId) {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public MenuItem setShowAsActionFlags(int actionEnum) {
+        setShowAsAction(actionEnum);
+        return this;
+    }
+
+    @Override
+    public boolean expandActionView() {
+        return false;
+    }
+
+    @Override
+    public boolean collapseActionView() {
+        return false;
+    }
+
+    @Override
+    public boolean isActionViewExpanded() {
+        return false;
+    }
+
+    @Override
+    public MenuItem setOnActionExpandListener(OnActionExpandListener listener) {
+        // No need to save the listener; ActionMenuItem does not support collapsing items.
+        return this;
+    }
 }
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index 0051ec3..91dd7e36 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -112,8 +112,11 @@
 
     @Override
     public View getItemView(MenuItemImpl item, View convertView, ViewGroup parent) {
-        final View actionView = item.getActionView();
-        return actionView != null ? actionView : super.getItemView(item, convertView, parent);
+        View actionView = item.getActionView();
+        actionView = actionView != null && !item.hasCollapsibleActionView() ?
+                actionView : super.getItemView(item, convertView, parent);
+        actionView.setVisibility(item.isActionViewExpanded() ? View.GONE : View.VISIBLE);
+        return actionView;
     }
 
     @Override
@@ -303,7 +306,7 @@
 
             if (item.requiresActionButton()) {
                 View v = item.getActionView();
-                if (v == null) {
+                if (v == null || item.hasCollapsibleActionView()) {
                     v = getItemView(item, mScrapActionButtonView, parent);
                     if (mScrapActionButtonView == null) {
                         mScrapActionButtonView = v;
@@ -329,7 +332,7 @@
 
                 if (isAction) {
                     View v = item.getActionView();
-                    if (v == null) {
+                    if (v == null || item.hasCollapsibleActionView()) {
                         v = getItemView(item, mScrapActionButtonView, parent);
                         if (mScrapActionButtonView == null) {
                             mScrapActionButtonView = v;
diff --git a/core/java/com/android/internal/view/menu/BaseMenuPresenter.java b/core/java/com/android/internal/view/menu/BaseMenuPresenter.java
index 16f51fd..ddbb08c 100644
--- a/core/java/com/android/internal/view/menu/BaseMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/BaseMenuPresenter.java
@@ -192,4 +192,12 @@
     public boolean flagActionItems() {
         return false;
     }
+
+    public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) {
+        return false;
+    }
+
+    public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
+        return false;
+    }
 }
diff --git a/core/java/com/android/internal/view/menu/ListMenuPresenter.java b/core/java/com/android/internal/view/menu/ListMenuPresenter.java
index 2cb2a10..f8d24a3 100644
--- a/core/java/com/android/internal/view/menu/ListMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ListMenuPresenter.java
@@ -159,6 +159,14 @@
         return false;
     }
 
+    public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) {
+        return false;
+    }
+
+    public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
+        return false;
+    }
+
     public void saveHierarchyState(Bundle outState) {
         SparseArray<Parcelable> viewStates = new SparseArray<Parcelable>();
         if (mMenuView != null) {
diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
index e9fcb23..fdfa954 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -744,11 +744,14 @@
         
         if (itemImpl == null || !itemImpl.isEnabled()) {
             return false;
-        }        
+        }
         
         boolean invoked = itemImpl.invoke();
 
-        if (item.hasSubMenu()) {
+        if (itemImpl.hasCollapsibleActionView()) {
+            invoked |= itemImpl.expandActionView();
+            if (invoked) close(true);
+        } else if (item.hasSubMenu()) {
             close(false);
 
             invoked |= dispatchSubMenuSelected((SubMenuBuilder) item.getSubMenu());
@@ -1081,4 +1084,42 @@
     boolean getOptionalIconsVisible() {
         return mOptionalIconsVisible;
     }
+
+    public boolean expandItemActionView(MenuItemImpl item) {
+        if (mPresenters.isEmpty()) return false;
+
+        boolean expanded = false;
+
+        stopDispatchingItemsChanged();
+        for (WeakReference<MenuPresenter> ref : mPresenters) {
+            final MenuPresenter presenter = ref.get();
+            if (presenter == null) {
+                mPresenters.remove(ref);
+            } else if ((expanded = presenter.expandItemActionView(this, item))) {
+                break;
+            }
+        }
+        startDispatchingItemsChanged();
+
+        return expanded;
+    }
+
+    public boolean collapseItemActionView(MenuItemImpl item) {
+        if (mPresenters.isEmpty()) return false;
+
+        boolean collapsed = false;
+
+        stopDispatchingItemsChanged();
+        for (WeakReference<MenuPresenter> ref : mPresenters) {
+            final MenuPresenter presenter = ref.get();
+            if (presenter == null) {
+                mPresenters.remove(ref);
+            } else if ((collapsed = presenter.collapseItemActionView(this, item))) {
+                break;
+            }
+        }
+        startDispatchingItemsChanged();
+
+        return collapsed;
+    }
 }
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index c6d386d..f2430e4 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -77,6 +77,8 @@
     private int mShowAsAction = SHOW_AS_ACTION_NEVER;
 
     private View mActionView;
+    private OnActionExpandListener mOnActionExpandListener;
+    private boolean mIsActionViewExpanded = false;
 
     /** Used for the icon resource ID if this item does not have an icon */
     static final int NO_ICON = 0;
@@ -561,4 +563,61 @@
     public View getActionView() {
         return mActionView;
     }
+
+    @Override
+    public MenuItem setShowAsActionFlags(int actionEnum) {
+        setShowAsAction(actionEnum);
+        return this;
+    }
+
+    @Override
+    public boolean expandActionView() {
+        if ((mShowAsAction & SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW) == 0 || mActionView == null) {
+            return false;
+        }
+
+        if (mOnActionExpandListener == null ||
+                mOnActionExpandListener.onMenuItemActionExpand(this)) {
+            return mMenu.expandItemActionView(this);
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean collapseActionView() {
+        if ((mShowAsAction & SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW) == 0) {
+            return false;
+        }
+        if (mActionView == null) {
+            // We're already collapsed if we have no action view.
+            return true;
+        }
+
+        if (mOnActionExpandListener == null ||
+                mOnActionExpandListener.onMenuItemActionCollapse(this)) {
+            return mMenu.collapseItemActionView(this);
+        }
+
+        return false;
+    }
+
+    @Override
+    public MenuItem setOnActionExpandListener(OnActionExpandListener listener) {
+        mOnActionExpandListener = listener;
+        return this;
+    }
+
+    public boolean hasCollapsibleActionView() {
+        return (mShowAsAction & SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW) != 0 && mActionView != null;
+    }
+
+    public void setActionViewExpanded(boolean isExpanded) {
+        mIsActionViewExpanded = isExpanded;
+        mMenu.onItemsChanged(false);
+    }
+
+    public boolean isActionViewExpanded() {
+        return mIsActionViewExpanded;
+    }
 }
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 38cec29..5767519 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -250,6 +250,14 @@
         return false;
     }
 
+    public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) {
+        return false;
+    }
+
+    public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
+        return false;
+    }
+
     private class MenuAdapter extends BaseAdapter {
         private MenuBuilder mAdapterMenu;
 
diff --git a/core/java/com/android/internal/view/menu/MenuPresenter.java b/core/java/com/android/internal/view/menu/MenuPresenter.java
index 5baf419..bd66448 100644
--- a/core/java/com/android/internal/view/menu/MenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/MenuPresenter.java
@@ -107,4 +107,22 @@
      * @return true if this presenter changed the action status of any items.
      */
     public boolean flagActionItems();
+
+    /**
+     * Called when a menu item with a collapsable action view should expand its action view.
+     *
+     * @param menu Menu containing the item to be expanded
+     * @param item Item to be expanded
+     * @return true if this presenter expanded the action view, false otherwise.
+     */
+    public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item);
+
+    /**
+     * Called when a menu item with a collapsable action view should collapse its action view.
+     *
+     * @param menu Menu containing the item to be collapsed
+     * @param item Item to be collapsed
+     * @return true if this presenter collapsed the action view, false otherwise.
+     */
+    public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item);
 }
diff --git a/core/java/com/android/internal/view/menu/SubMenuBuilder.java b/core/java/com/android/internal/view/menu/SubMenuBuilder.java
index 834041f..fb1cd5e 100644
--- a/core/java/com/android/internal/view/menu/SubMenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/SubMenuBuilder.java
@@ -111,4 +111,14 @@
     public SubMenu setHeaderView(View view) {
         return (SubMenu) super.setHeaderViewInt(view);
     }
+
+    @Override
+    public boolean expandItemActionView(MenuItemImpl item) {
+        return mParentMenu.expandItemActionView(item);
+    }
+
+    @Override
+    public boolean collapseItemActionView(MenuItemImpl item) {
+        return mParentMenu.collapseItemActionView(item);
+    }
 }
diff --git a/core/java/com/android/internal/widget/AbsActionBarView.java b/core/java/com/android/internal/widget/AbsActionBarView.java
index 788883b..ccbce3e 100644
--- a/core/java/com/android/internal/widget/AbsActionBarView.java
+++ b/core/java/com/android/internal/widget/AbsActionBarView.java
@@ -30,7 +30,7 @@
 
 public abstract class AbsActionBarView extends ViewGroup {
     protected ActionMenuView mMenuView;
-    protected ActionMenuPresenter mMenuPresenter;
+    protected ActionMenuPresenter mActionMenuPresenter;
     protected ActionBarContainer mSplitView;
 
     protected Animator mVisibilityAnim;
@@ -108,8 +108,8 @@
     }
 
     public boolean showOverflowMenu() {
-        if (mMenuPresenter != null) {
-            return mMenuPresenter.showOverflowMenu();
+        if (mActionMenuPresenter != null) {
+            return mActionMenuPresenter.showOverflowMenu();
         }
         return false;
     }
@@ -123,26 +123,26 @@
     }
 
     public boolean hideOverflowMenu() {
-        if (mMenuPresenter != null) {
-            return mMenuPresenter.hideOverflowMenu();
+        if (mActionMenuPresenter != null) {
+            return mActionMenuPresenter.hideOverflowMenu();
         }
         return false;
     }
 
     public boolean isOverflowMenuShowing() {
-        if (mMenuPresenter != null) {
-            return mMenuPresenter.isOverflowMenuShowing();
+        if (mActionMenuPresenter != null) {
+            return mActionMenuPresenter.isOverflowMenuShowing();
         }
         return false;
     }
 
     public boolean isOverflowReserved() {
-        return mMenuPresenter != null && mMenuPresenter.isOverflowReserved();
+        return mActionMenuPresenter != null && mActionMenuPresenter.isOverflowReserved();
     }
 
     public void dismissPopupMenus() {
-        if (mMenuPresenter != null) {
-            mMenuPresenter.dismissPopupMenus();
+        if (mActionMenuPresenter != null) {
+            mActionMenuPresenter.dismissPopupMenus();
         }
     }
 
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index deed1c5..e4c4989 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -167,9 +167,9 @@
         });
 
         final MenuBuilder menu = (MenuBuilder) mode.getMenu();
-        mMenuPresenter = new ActionMenuPresenter();
-        menu.addMenuPresenter(mMenuPresenter);
-        mMenuView = (ActionMenuView) mMenuPresenter.getMenuView(this);
+        mActionMenuPresenter = new ActionMenuPresenter();
+        menu.addMenuPresenter(mActionMenuPresenter);
+        mMenuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
 
         final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
                 LayoutParams.MATCH_PARENT);
@@ -178,10 +178,10 @@
             addView(mMenuView);
         } else {
             // Allow full screen width in split mode.
-            mMenuPresenter.setWidthLimit(
+            mActionMenuPresenter.setWidthLimit(
                     getContext().getResources().getDisplayMetrics().widthPixels, true);
             // No limit to the item count; use whatever will fit.
-            mMenuPresenter.setItemLimit(Integer.MAX_VALUE);
+            mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE);
             // Span the whole width
             layoutParams.width = LayoutParams.MATCH_PARENT;
             mSplitView.addView(mMenuView);
@@ -227,24 +227,24 @@
 
     @Override
     public boolean showOverflowMenu() {
-        if (mMenuPresenter != null) {
-            return mMenuPresenter.showOverflowMenu();
+        if (mActionMenuPresenter != null) {
+            return mActionMenuPresenter.showOverflowMenu();
         }
         return false;
     }
 
     @Override
     public boolean hideOverflowMenu() {
-        if (mMenuPresenter != null) {
-            return mMenuPresenter.hideOverflowMenu();
+        if (mActionMenuPresenter != null) {
+            return mActionMenuPresenter.hideOverflowMenu();
         }
         return false;
     }
 
     @Override
     public boolean isOverflowMenuShowing() {
-        if (mMenuPresenter != null) {
-            return mMenuPresenter.isOverflowMenuShowing();
+        if (mActionMenuPresenter != null) {
+            return mActionMenuPresenter.isOverflowMenuShowing();
         }
         return false;
     }
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index b7aac14..eb97ea8 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -21,7 +21,10 @@
 import com.android.internal.view.menu.ActionMenuPresenter;
 import com.android.internal.view.menu.ActionMenuView;
 import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.view.menu.MenuItemImpl;
 import com.android.internal.view.menu.MenuPresenter;
+import com.android.internal.view.menu.MenuView;
+import com.android.internal.view.menu.SubMenuBuilder;
 
 import android.app.ActionBar;
 import android.app.ActionBar.OnNavigationListener;
@@ -33,21 +36,22 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
+import android.os.Parcel;
+import android.os.Parcelable;
 import android.text.TextUtils;
-import android.text.TextUtils.TruncateAt;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.Menu;
+import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewParent;
 import android.view.Window;
 import android.widget.AdapterView;
 import android.widget.FrameLayout;
-import android.widget.HorizontalScrollView;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.ProgressBar;
@@ -87,9 +91,8 @@
     private Drawable mIcon;
     private Drawable mLogo;
 
-    private View mHomeLayout;
-    private View mHomeAsUpView;
-    private ImageView mIconView;
+    private HomeView mHomeLayout;
+    private HomeView mExpandedHomeLayout;
     private LinearLayout mTitleLayout;
     private TextView mTitleView;
     private TextView mSubtitleView;
@@ -124,6 +127,9 @@
 
     private Runnable mTabSelector;
 
+    private ExpandedActionViewMenuPresenter mExpandedMenuPresenter;
+    View mExpandedActionView;
+
     private final AdapterView.OnItemSelectedListener mNavItemSelectedListener =
             new AdapterView.OnItemSelectedListener() {
         public void onItemSelected(AdapterView parent, View view, int position, long id) {
@@ -136,7 +142,15 @@
         }
     };
 
-    private OnClickListener mTabClickListener = null;
+    private final OnClickListener mExpandedActionViewUpListener = new OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            final MenuItemImpl item = mExpandedMenuPresenter.mCurrentExpandedItem;
+            if (item != null) {
+                item.collapseActionView();
+            }
+        }
+    };
 
     public ActionBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -187,10 +201,11 @@
                 com.android.internal.R.styleable.ActionBar_homeLayout,
                 com.android.internal.R.layout.action_bar_home);
 
-        mHomeLayout = inflater.inflate(homeResId, this, false);
+        mHomeLayout = (HomeView) inflater.inflate(homeResId, this, false);
 
-        mHomeAsUpView = mHomeLayout.findViewById(com.android.internal.R.id.up);
-        mIconView = (ImageView) mHomeLayout.findViewById(com.android.internal.R.id.home);
+        mExpandedHomeLayout = (HomeView) inflater.inflate(homeResId, this, false);
+        mExpandedHomeLayout.setUp(true);
+        mExpandedHomeLayout.setOnClickListener(mExpandedActionViewUpListener);
         
         mTitleStyleRes = a.getResourceId(R.styleable.ActionBar_titleTextStyle, 0);
         mSubtitleStyleRes = a.getResourceId(R.styleable.ActionBar_subtitleTextStyle, 0);
@@ -285,7 +300,7 @@
     public void setEmbeddedTabView(ScrollingTabContainerView tabs) {
         mTabScrollView = tabs;
         mIncludeTabs = tabs != null;
-        if (mIncludeTabs) {
+        if (mIncludeTabs && mNavigationMode == ActionBar.NAVIGATION_MODE_TABS) {
             addView(mTabScrollView);
         }
     }
@@ -298,7 +313,8 @@
         if (menu == mOptionsMenu) return;
 
         if (mOptionsMenu != null) {
-            mOptionsMenu.removeMenuPresenter(mMenuPresenter);
+            mOptionsMenu.removeMenuPresenter(mActionMenuPresenter);
+            mOptionsMenu.removeMenuPresenter(mExpandedMenuPresenter);
         }
 
         MenuBuilder builder = (MenuBuilder) menu;
@@ -306,13 +322,15 @@
         if (mMenuView != null) {
             removeView(mMenuView);
         }
-        if (mMenuPresenter == null) {
-            mMenuPresenter = new ActionMenuPresenter();
-            mMenuPresenter.setCallback(cb);
+        if (mActionMenuPresenter == null) {
+            mActionMenuPresenter = new ActionMenuPresenter();
+            mActionMenuPresenter.setCallback(cb);
+            mExpandedMenuPresenter = new ExpandedActionViewMenuPresenter();
         }
-        builder.addMenuPresenter(mMenuPresenter);
+        builder.addMenuPresenter(mActionMenuPresenter);
+        builder.addMenuPresenter(mExpandedMenuPresenter);
 
-        final ActionMenuView menuView = (ActionMenuView) mMenuPresenter.getMenuView(this);
+        final ActionMenuView menuView = (ActionMenuView) mActionMenuPresenter.getMenuView(this);
         final LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT,
                 LayoutParams.MATCH_PARENT);
         menuView.setLayoutParams(layoutParams);
@@ -320,10 +338,10 @@
             addView(menuView);
         } else {
             // Allow full screen width in split mode.
-            mMenuPresenter.setWidthLimit(
+            mActionMenuPresenter.setWidthLimit(
                     getContext().getResources().getDisplayMetrics().widthPixels, true);
             // No limit to the item count; use whatever will fit.
-            mMenuPresenter.setItemLimit(Integer.MAX_VALUE);
+            mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE);
             // Span the whole width
             layoutParams.width = LayoutParams.MATCH_PARENT;
             if (mSplitView != null) {
@@ -411,13 +429,12 @@
             mHomeLayout.setVisibility(vis);
 
             if ((flagsChanged & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
-                final boolean isUp = (options & ActionBar.DISPLAY_HOME_AS_UP) != 0;
-                mHomeAsUpView.setVisibility(isUp ? VISIBLE : GONE);
+                mHomeLayout.setUp((options & ActionBar.DISPLAY_HOME_AS_UP) != 0);
             }
 
             if ((flagsChanged & ActionBar.DISPLAY_USE_LOGO) != 0) {
                 final boolean logoVis = mLogo != null && (options & ActionBar.DISPLAY_USE_LOGO) != 0;
-                mIconView.setImageDrawable(logoVis ? mLogo : mIcon);
+                mHomeLayout.setIcon(logoVis ? mLogo : mIcon);
             }
 
             if ((flagsChanged & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
@@ -457,7 +474,7 @@
         mIcon = icon;
         if (icon != null &&
                 ((mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) == 0 || mLogo == null)) {
-            mIconView.setImageDrawable(icon);
+            mHomeLayout.setIcon(icon);
         }
     }
 
@@ -468,7 +485,7 @@
     public void setLogo(Drawable logo) {
         mLogo = logo;
         if (logo != null && (mDisplayOptions & ActionBar.DISPLAY_USE_LOGO) != 0) {
-            mIconView.setImageDrawable(logo);
+            mHomeLayout.setIcon(logo);
         }
     }
 
@@ -482,7 +499,7 @@
     private int getPreferredIconDensity() {
         final Resources res = mContext.getResources();
         final int availableHeight = getLayoutParams().height -
-                mIconView.getPaddingTop() - mIconView.getPaddingBottom();
+                mHomeLayout.getVerticalIconPadding();
         int iconSize = res.getDimensionPixelSize(android.R.dimen.app_icon_size);
 
         if (iconSize * DisplayMetrics.DENSITY_LOW >= availableHeight) {
@@ -500,7 +517,7 @@
         if (mode != oldMode) {
             switch (oldMode) {
             case ActionBar.NAVIGATION_MODE_LIST:
-                if (mSpinner != null) {
+                if (mListNavLayout != null) {
                     removeView(mListNavLayout);
                 }
                 break;
@@ -685,10 +702,13 @@
         int leftOfCenter = availableWidth / 2;
         int rightOfCenter = leftOfCenter;
 
-        if (mHomeLayout.getVisibility() != GONE) {
-            mHomeLayout.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
+        View homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
+
+        if (homeLayout.getVisibility() != GONE) {
+            homeLayout.measure(
+                    MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
                     MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
-            final int homeWidth = mHomeLayout.getMeasuredWidth();
+            final int homeWidth = homeLayout.getMeasuredWidth();
             availableWidth = Math.max(0, availableWidth - homeWidth);
             leftOfCenter = Math.max(0, availableWidth - homeWidth);
         }
@@ -699,40 +719,42 @@
             rightOfCenter = Math.max(0, rightOfCenter - mMenuView.getMeasuredWidth());
         }
 
-        boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
-                (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
-        if (showTitle) {
-            availableWidth = measureChildView(mTitleLayout, availableWidth, childSpecHeight, 0);
-            leftOfCenter = Math.max(0, leftOfCenter - mTitleLayout.getMeasuredWidth());
-        }
+        if (mExpandedActionView == null) {
+            boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
+            (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
+            if (showTitle) {
+                availableWidth = measureChildView(mTitleLayout, availableWidth, childSpecHeight, 0);
+                leftOfCenter = Math.max(0, leftOfCenter - mTitleLayout.getMeasuredWidth());
+            }
 
-        switch (mNavigationMode) {
-        case ActionBar.NAVIGATION_MODE_LIST:
-            if (mListNavLayout != null) {
-                final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding;
-                availableWidth = Math.max(0, availableWidth - itemPaddingSize);
-                leftOfCenter = Math.max(0, leftOfCenter - itemPaddingSize);
-                mListNavLayout.measure(
-                        MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
-                        MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
-                final int listNavWidth = mListNavLayout.getMeasuredWidth();
-                availableWidth = Math.max(0, availableWidth - listNavWidth);
-                leftOfCenter = Math.max(0, leftOfCenter - listNavWidth);
+            switch (mNavigationMode) {
+                case ActionBar.NAVIGATION_MODE_LIST:
+                    if (mListNavLayout != null) {
+                        final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding;
+                        availableWidth = Math.max(0, availableWidth - itemPaddingSize);
+                        leftOfCenter = Math.max(0, leftOfCenter - itemPaddingSize);
+                        mListNavLayout.measure(
+                                MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
+                                MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+                        final int listNavWidth = mListNavLayout.getMeasuredWidth();
+                        availableWidth = Math.max(0, availableWidth - listNavWidth);
+                        leftOfCenter = Math.max(0, leftOfCenter - listNavWidth);
+                    }
+                    break;
+                case ActionBar.NAVIGATION_MODE_TABS:
+                    if (mTabScrollView != null) {
+                        final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding;
+                        availableWidth = Math.max(0, availableWidth - itemPaddingSize);
+                        leftOfCenter = Math.max(0, leftOfCenter - itemPaddingSize);
+                        mTabScrollView.measure(
+                                MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
+                                MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+                        final int tabWidth = mTabScrollView.getMeasuredWidth();
+                        availableWidth = Math.max(0, availableWidth - tabWidth);
+                        leftOfCenter = Math.max(0, leftOfCenter - tabWidth);
+                    }
+                    break;
             }
-            break;
-        case ActionBar.NAVIGATION_MODE_TABS:
-            if (mTabScrollView != null) {
-                final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding;
-                availableWidth = Math.max(0, availableWidth - itemPaddingSize);
-                leftOfCenter = Math.max(0, leftOfCenter - itemPaddingSize);
-                mTabScrollView.measure(
-                        MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST),
-                        MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
-                final int tabWidth = mTabScrollView.getMeasuredWidth();
-                availableWidth = Math.max(0, availableWidth - tabWidth);
-                leftOfCenter = Math.max(0, leftOfCenter - tabWidth);
-            }
-            break;
         }
 
         if (mIndeterminateProgressView != null &&
@@ -743,8 +765,16 @@
                     rightOfCenter - mIndeterminateProgressView.getMeasuredWidth());
         }
 
-        if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomNavView != null) {
-            final LayoutParams lp = generateLayoutParams(mCustomNavView.getLayoutParams());
+        View customView = null;
+        if (mExpandedActionView != null) {
+            customView = mExpandedActionView;
+        } else if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 &&
+                mCustomNavView != null) {
+            customView = mCustomNavView;
+        }
+
+        if (customView != null) {
+            final LayoutParams lp = generateLayoutParams(customView.getLayoutParams());
             final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ?
                     (ActionBar.LayoutParams) lp : null;
 
@@ -781,7 +811,7 @@
                 customNavWidth = Math.min(leftOfCenter, rightOfCenter) * 2;
             }
 
-            mCustomNavView.measure(
+            customView.measure(
                     MeasureSpec.makeMeasureSpec(customNavWidth, customNavWidthMode),
                     MeasureSpec.makeMeasureSpec(customNavHeight, customNavHeightMode));
         }
@@ -822,31 +852,34 @@
             return;
         }
 
-        if (mHomeLayout.getVisibility() != GONE) {
-            x += positionChild(mHomeLayout, x, y, contentHeight);
-        }
-        
-        final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
-                (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
-        if (showTitle) {
-            x += positionChild(mTitleLayout, x, y, contentHeight);
+        View homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
+        if (homeLayout.getVisibility() != GONE) {
+            x += positionChild(homeLayout, x, y, contentHeight);
         }
 
-        switch (mNavigationMode) {
-        case ActionBar.NAVIGATION_MODE_STANDARD:
-            break;
-        case ActionBar.NAVIGATION_MODE_LIST:
-            if (mListNavLayout != null) {
-                if (showTitle) x += mItemPadding;
-                x += positionChild(mListNavLayout, x, y, contentHeight) + mItemPadding;
+        if (mExpandedActionView == null) {
+            final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
+            (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
+            if (showTitle) {
+                x += positionChild(mTitleLayout, x, y, contentHeight);
             }
-            break;
-        case ActionBar.NAVIGATION_MODE_TABS:
-            if (mTabScrollView != null) {
-                if (showTitle) x += mItemPadding;
-                x += positionChild(mTabScrollView, x, y, contentHeight) + mItemPadding;
+
+            switch (mNavigationMode) {
+                case ActionBar.NAVIGATION_MODE_STANDARD:
+                    break;
+                case ActionBar.NAVIGATION_MODE_LIST:
+                    if (mListNavLayout != null) {
+                        if (showTitle) x += mItemPadding;
+                        x += positionChild(mListNavLayout, x, y, contentHeight) + mItemPadding;
+                    }
+                    break;
+                case ActionBar.NAVIGATION_MODE_TABS:
+                    if (mTabScrollView != null) {
+                        if (showTitle) x += mItemPadding;
+                        x += positionChild(mTabScrollView, x, y, contentHeight) + mItemPadding;
+                    }
+                    break;
             }
-            break;
         }
 
         int menuLeft = r - l - getPaddingRight();
@@ -861,13 +894,20 @@
             menuLeft -= mIndeterminateProgressView.getMeasuredWidth();
         }
 
-        if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
-            LayoutParams lp = mCustomNavView.getLayoutParams();
+        View customView = null;
+        if (mExpandedActionView != null) {
+            customView = mExpandedActionView;
+        } else if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 &&
+                mCustomNavView != null) {
+            customView = mCustomNavView;
+        }
+        if (customView != null) {
+            LayoutParams lp = customView.getLayoutParams();
             final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ?
                     (ActionBar.LayoutParams) lp : null;
 
             final int gravity = ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY;
-            final int navWidth = mCustomNavView.getMeasuredWidth();
+            final int navWidth = customView.getMeasuredWidth();
 
             int topMargin = 0;
             int bottomMargin = 0;
@@ -907,17 +947,17 @@
                 case Gravity.CENTER_VERTICAL:
                     final int paddedTop = mTop + getPaddingTop();
                     final int paddedBottom = mBottom - getPaddingBottom();
-                    ypos = ((paddedBottom - paddedTop) - mCustomNavView.getMeasuredHeight()) / 2;
+                    ypos = ((paddedBottom - paddedTop) - customView.getMeasuredHeight()) / 2;
                     break;
                 case Gravity.TOP:
                     ypos = getPaddingTop() + topMargin;
                     break;
                 case Gravity.BOTTOM:
-                    ypos = getHeight() - getPaddingBottom() - mCustomNavView.getMeasuredHeight()
+                    ypos = getHeight() - getPaddingBottom() - customView.getMeasuredHeight()
                             - bottomMargin;
                     break;
             }
-            x += positionChild(mCustomNavView, xpos, ypos, contentHeight);
+            x += positionChild(customView, xpos, ypos, contentHeight);
         }
 
         if (mProgressView != null) {
@@ -928,9 +968,83 @@
         }
     }
 
+    @Override
+    public LayoutParams generateLayoutParams(LayoutParams lp) {
+        if (lp == null) {
+            lp = generateDefaultLayoutParams();
+        }
+        return lp;
+    }
+
+    @Override
+    public Parcelable onSaveInstanceState() {
+        Parcelable superState = super.onSaveInstanceState();
+        SavedState state = new SavedState(superState);
+
+        if (mExpandedMenuPresenter != null && mExpandedMenuPresenter.mCurrentExpandedItem != null) {
+            state.expandedMenuItemId = mExpandedMenuPresenter.mCurrentExpandedItem.getItemId();
+        }
+
+        state.isOverflowOpen = isOverflowMenuShowing();
+
+        return state;
+    }
+
+    @Override
+    public void onRestoreInstanceState(Parcelable p) {
+        SavedState state = (SavedState) p;
+
+        super.onRestoreInstanceState(state.getSuperState());
+
+        if (state.expandedMenuItemId != 0 &&
+                mExpandedMenuPresenter != null && mOptionsMenu != null) {
+            final MenuItem item = mOptionsMenu.findItem(state.expandedMenuItemId);
+            if (item != null) {
+                item.expandActionView();
+            }
+        }
+
+        if (state.isOverflowOpen) {
+            postShowOverflowMenu();
+        }
+    }
+
+    static class SavedState extends BaseSavedState {
+        int expandedMenuItemId;
+        boolean isOverflowOpen;
+
+        SavedState(Parcelable superState) {
+            super(superState);
+        }
+
+        private SavedState(Parcel in) {
+            super(in);
+            expandedMenuItemId = in.readInt();
+            isOverflowOpen = in.readInt() != 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel out, int flags) {
+            super.writeToParcel(out, flags);
+            out.writeInt(expandedMenuItemId);
+            out.writeInt(isOverflowOpen ? 1 : 0);
+        }
+
+        public static final Parcelable.Creator<SavedState> CREATOR =
+                new Parcelable.Creator<SavedState>() {
+            public SavedState createFromParcel(Parcel in) {
+                return new SavedState(in);
+            }
+
+            public SavedState[] newArray(int size) {
+                return new SavedState[size];
+            }
+        };
+    }
+
     private static class HomeView extends FrameLayout {
         private View mUpView;
-        private View mIconView;
+        private ImageView mIconView;
 
         public HomeView(Context context) {
             this(context, null);
@@ -940,12 +1054,24 @@
             super(context, attrs);
         }
 
+        public void setUp(boolean isUp) {
+            mUpView.setVisibility(isUp ? VISIBLE : GONE);
+        }
+
+        public void setIcon(Drawable icon) {
+            mIconView.setImageDrawable(icon);
+        }
+
         @Override
         protected void onFinishInflate() {
             mUpView = findViewById(com.android.internal.R.id.up);
             mIconView = (ImageView) findViewById(com.android.internal.R.id.home);
         }
 
+        public int getVerticalIconPadding() {
+            return mIconView.getPaddingTop() + mIconView.getPaddingBottom();
+        }
+
         @Override
         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
             measureChildWithMargins(mUpView, widthMeasureSpec, 0, heightMeasureSpec, 0);
@@ -983,4 +1109,111 @@
             mIconView.layout(iconLeft, iconTop, iconLeft + iconWidth, iconTop + iconHeight);
         }
     }
+
+    private class ExpandedActionViewMenuPresenter implements MenuPresenter {
+        MenuBuilder mMenu;
+        MenuItemImpl mCurrentExpandedItem;
+
+        @Override
+        public void initForMenu(Context context, MenuBuilder menu) {
+            // Clear the expanded action view when menus change.
+            mExpandedActionView = null;
+            if (mCurrentExpandedItem != null) {
+                mCurrentExpandedItem.collapseActionView();
+            }
+            mMenu = menu;
+        }
+
+        @Override
+        public MenuView getMenuView(ViewGroup root) {
+            return null;
+        }
+
+        @Override
+        public void updateMenuView(boolean cleared) {
+            // Make sure the expanded item we have is still there.
+            if (mCurrentExpandedItem != null) {
+                boolean found = false;
+                final int count = mMenu.size();
+                for (int i = 0; i < count; i++) {
+                    final MenuItem item = mMenu.getItem(i);
+                    if (item == mCurrentExpandedItem) {
+                        found = true;
+                        break;
+                    }
+                }
+
+                if (!found) {
+                    // The item we had expanded disappeared. Collapse.
+                    collapseItemActionView(mMenu, mCurrentExpandedItem);
+                }
+            }
+        }
+
+        @Override
+        public void setCallback(Callback cb) {
+        }
+
+        @Override
+        public boolean onSubMenuSelected(SubMenuBuilder subMenu) {
+            return false;
+        }
+
+        @Override
+        public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
+        }
+
+        @Override
+        public boolean flagActionItems() {
+            return false;
+        }
+
+        @Override
+        public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) {
+            mExpandedActionView = item.getActionView();
+            mExpandedHomeLayout.setIcon(item.getIcon());
+            mCurrentExpandedItem = item;
+            if (mExpandedActionView.getParent() != ActionBarView.this) {
+                addView(mExpandedActionView);
+            }
+            if (mExpandedHomeLayout.getParent() != ActionBarView.this) {
+                addView(mExpandedHomeLayout);
+            }
+            mHomeLayout.setVisibility(GONE);
+            mTitleLayout.setVisibility(GONE);
+            if (mTabScrollView != null) mTabScrollView.setVisibility(GONE);
+            if (mSpinner != null) mSpinner.setVisibility(GONE);
+            if (mCustomNavView != null) mCustomNavView.setVisibility(GONE);
+            requestLayout();
+            item.setActionViewExpanded(true);
+            return true;
+        }
+
+        @Override
+        public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
+            removeView(mExpandedActionView);
+            removeView(mExpandedHomeLayout);
+            if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0) {
+                mHomeLayout.setVisibility(VISIBLE);
+            }
+            if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
+                mTitleLayout.setVisibility(VISIBLE);
+            }
+            if (mTabScrollView != null && mNavigationMode == ActionBar.NAVIGATION_MODE_TABS) {
+                mTabScrollView.setVisibility(VISIBLE);
+            }
+            if (mSpinner != null && mNavigationMode == ActionBar.NAVIGATION_MODE_LIST) {
+                mSpinner.setVisibility(VISIBLE);
+            }
+            if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
+                mCustomNavView.setVisibility(VISIBLE);
+            }
+            mExpandedActionView = null;
+            mExpandedHomeLayout.setIcon(null);
+            mCurrentExpandedItem = null;
+            requestLayout();
+            item.setActionViewExpanded(false);
+            return true;
+        }
+    }
 }
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_server_BluetoothService.cpp b/core/jni/android_server_BluetoothService.cpp
index 5c6958a..ac75634 100644
--- a/core/jni/android_server_BluetoothService.cpp
+++ b/core/jni/android_server_BluetoothService.cpp
@@ -250,15 +250,15 @@
 #endif
 }
 
-static void stopDiscoveryNative(JNIEnv *env, jobject object) {
-    LOGV("%s", __FUNCTION__);
+static jboolean stopDiscoveryNative(JNIEnv *env, jobject object) {
+    LOGV(__FUNCTION__);
 #ifdef HAVE_BLUETOOTH
     DBusMessage *msg = NULL;
     DBusMessage *reply = NULL;
     DBusError err;
     const char *name;
-    jstring ret;
     native_data_t *nat;
+    jboolean ret = JNI_FALSE;
 
     dbus_error_init(&err);
 
@@ -288,11 +288,16 @@
         } else {
             LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
         }
+        goto done;
     }
 
+    ret = JNI_TRUE;
 done:
     if (msg) dbus_message_unref(msg);
     if (reply) dbus_message_unref(reply);
+    return ret;
+#else
+    return JNI_FALSE;
 #endif
 }
 
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/layout/input_method_extract_view.xml b/core/res/res/layout/input_method_extract_view.xml
index 7d59d02..60bc24c 100644
--- a/core/res/res/layout/input_method_extract_view.xml
+++ b/core/res/res/layout/input_method_extract_view.xml
@@ -18,7 +18,7 @@
 */
 -->
 
-<LinearLayout
+<android.inputmethodservice.ExtractEditLayout
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:orientation="horizontal">
         
@@ -38,8 +38,8 @@
             android:id="@+id/inputExtractAccessories"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
-            android:paddingLeft="10dip"
-            android:paddingRight="10dip"
+            android:paddingLeft="8dip"
+            android:paddingRight="8dip"
             android:background="@android:drawable/keyboard_accessory_bg_landscape"
         >
         
@@ -48,7 +48,14 @@
             android:layout_height="wrap_content"
             android:layout_gravity="center"
             />
+        <android.inputmethodservice.ExtractButton android:id="@+id/inputExtractEditButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:text="@string/extract_edit_menu_button"
+            android:visibility="invisible"
+            />
             
     </FrameLayout>
     
-</LinearLayout>
+</android.inputmethodservice.ExtractEditLayout>
diff --git a/core/res/res/values-large/config.xml b/core/res/res/values-large/config.xml
index c94256e..9327200 100644
--- a/core/res/res/values-large/config.xml
+++ b/core/res/res/values-large/config.xml
@@ -23,8 +23,6 @@
     <!-- see comment in values/config.xml -->
     <dimen name="config_prefDialogWidth">440dp</dimen>
 
-    <bool name="config_statusBarCanHide">false</bool>
-
     <!-- see comment in values/config.xml -->
     <integer name="config_longPressOnPowerBehavior">2</integer>
 
diff --git a/core/res/res/values-sw600dp/config.xml b/core/res/res/values-sw600dp/config.xml
index 49ace34..d6a0cdd 100644
--- a/core/res/res/values-sw600dp/config.xml
+++ b/core/res/res/values-sw600dp/config.xml
@@ -20,8 +20,6 @@
 <!-- These resources are around just to allow their values to be customized
      for different hardware and product builds. -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <bool name="config_statusBarCanHide">false</bool>
-
     <!-- see comment in values/config.xml -->
     <integer name="config_longPressOnPowerBehavior">2</integer>
 
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index db76211..b3520da 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4482,6 +4482,10 @@
             <!-- When this item is shown as an action in the action bar, show a text
                  label with it even if it has an icon representation. -->
             <flag name="withText" value="4" />
+            <!-- This item's action view collapses to a normal menu
+                 item. When expanded, the action view takes over a
+                 larger segment of its container. -->
+            <flag name="collapseActionView" value="8" />
         </attr>
 
         <!-- An optional layout to be used as an action view.
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/config.xml b/core/res/res/values/config.xml
index af08d45..fc14a2a 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -20,8 +20,6 @@
 <!-- These resources are around just to allow their values to be customized
      for different hardware and product builds. -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <bool name="config_statusBarCanHide">true</bool>
-
     <!-- Do not translate. Defines the slots for the right-hand side icons.  That is to say, the
          icons in the status bar that are not notifications. -->
     <string-array name="config_statusBarIcons">
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index f5de1d2..724c528 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -32,10 +32,14 @@
     <dimen name="toast_y_offset">64dip</dimen>
     <!-- Height of the status bar -->
     <dimen name="status_bar_height">25dip</dimen>
-    <!-- Height of the status bar -->
+    <!-- Height of the system bar -->
+    <dimen name="system_bar_height">48dip</dimen>
+    <!-- Height of notification icons in the status bar -->
     <dimen name="status_bar_icon_size">25dip</dimen>
     <!-- Size of the giant number (unread count) in the notifications -->
     <dimen name="status_bar_content_number_size">48sp</dimen>
+    <!-- Height of notification icons in the system bar -->
+    <dimen name="system_bar_icon_size">32dip</dimen>
     <!-- Margin at the edge of the screen to ignore touch events for in the windowshade. -->
     <dimen name="status_bar_edge_ignore">5dp</dimen>
     <!-- Size of the fastscroll hint letter -->
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/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b8a4443..a277c74 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1852,7 +1852,7 @@
 
     <!-- Do not translate.  WebView User Agent string -->
     <string name="web_user_agent" translatable="false">Mozilla/5.0 (Linux; U; <xliff:g id="x">Android %s</xliff:g>)
-        AppleWebKit/534.20 (KHTML, like Gecko) Version/4.0 <xliff:g id="mobile">%s</xliff:g>Safari/534.20</string>
+        AppleWebKit/534.24 (KHTML, like Gecko) Version/4.0 <xliff:g id="mobile">%s</xliff:g>Safari/534.24</string>
     <!-- Do not translate.  WebView User Agent targeted content -->
     <string name="web_user_agent_target_content" translatable="false">"Mobile "</string>
 
@@ -2860,4 +2860,7 @@
 
     <!-- Storage description for USB storage. [CHAR LIMIT=NONE] -->
     <string name="storage_usb">USB storage</string>
+
+    <!-- Button text for the edit menu in input method extract mode. [CHAR LIMIT=16] -->
+    <string name="extract_edit_menu_button">Edit...</string>
 </resources>
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
index f1dd8fe..5f4c226 100644
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
@@ -678,8 +678,7 @@
         BluetoothReceiver receiver = getBluetoothReceiver(mask);
 
         long start = System.currentTimeMillis();
-        // TODO: put assertTrue() around cancelDiscovery() once it starts returning true.
-        adapter.cancelDiscovery();
+        assertTrue(adapter.cancelDiscovery());
 
         while (System.currentTimeMillis() - start < START_STOP_SCAN_TIMEOUT) {
             if (!adapter.isDiscovering() && ((receiver.getFiredFlags() & mask) == mask)) {
diff --git a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
new file mode 100644
index 0000000..eb63c0d
--- /dev/null
+++ b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.NetworkStatsHistory.UID_ALL;
+import static android.text.format.DateUtils.DAY_IN_MILLIS;
+import static android.text.format.DateUtils.HOUR_IN_MILLIS;
+import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+import static android.text.format.DateUtils.SECOND_IN_MILLIS;
+import static android.text.format.DateUtils.WEEK_IN_MILLIS;
+import static android.text.format.DateUtils.YEAR_IN_MILLIS;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.Suppress;
+import android.util.Log;
+
+import junit.framework.TestCase;
+
+import java.util.Random;
+
+@SmallTest
+public class NetworkStatsHistoryTest extends TestCase {
+    private static final String TAG = "NetworkStatsHistoryTest";
+
+    private static final long TEST_START = 1194220800000L;
+
+    private NetworkStatsHistory stats;
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        if (stats != null) {
+            assertConsistent(stats);
+        }
+    }
+
+    public void testRecordSingleBucket() throws Exception {
+        final long BUCKET_SIZE = HOUR_IN_MILLIS;
+        stats = buildStats(BUCKET_SIZE);
+
+        // record data into narrow window to get single bucket
+        stats.recordData(TEST_START, TEST_START + SECOND_IN_MILLIS, 1024L, 2048L);
+
+        assertEquals(1, stats.bucketCount);
+        assertBucket(stats, 0, 1024L, 2048L);
+    }
+
+    public void testRecordEqualBuckets() throws Exception {
+        final long bucketDuration = HOUR_IN_MILLIS;
+        stats = buildStats(bucketDuration);
+
+        // split equally across two buckets
+        final long recordStart = TEST_START + (bucketDuration / 2);
+        stats.recordData(recordStart, recordStart + bucketDuration, 1024L, 128L);
+
+        assertEquals(2, stats.bucketCount);
+        assertBucket(stats, 0, 512L, 64L);
+        assertBucket(stats, 1, 512L, 64L);
+    }
+
+    public void testRecordTouchingBuckets() throws Exception {
+        final long BUCKET_SIZE = 15 * MINUTE_IN_MILLIS;
+        stats = buildStats(BUCKET_SIZE);
+
+        // split almost completely into middle bucket, but with a few minutes
+        // overlap into neighboring buckets. total record is 20 minutes.
+        final long recordStart = (TEST_START + BUCKET_SIZE) - MINUTE_IN_MILLIS;
+        final long recordEnd = (TEST_START + (BUCKET_SIZE * 2)) + (MINUTE_IN_MILLIS * 4);
+        stats.recordData(recordStart, recordEnd, 1000L, 5000L);
+
+        assertEquals(3, stats.bucketCount);
+        // first bucket should have (1/20 of value)
+        assertBucket(stats, 0, 50L, 250L);
+        // second bucket should have (15/20 of value)
+        assertBucket(stats, 1, 750L, 3750L);
+        // final bucket should have (4/20 of value)
+        assertBucket(stats, 2, 200L, 1000L);
+    }
+
+    public void testRecordGapBuckets() throws Exception {
+        final long BUCKET_SIZE = HOUR_IN_MILLIS;
+        stats = buildStats(BUCKET_SIZE);
+
+        // record some data today and next week with large gap
+        final long firstStart = TEST_START;
+        final long lastStart = TEST_START + WEEK_IN_MILLIS;
+        stats.recordData(firstStart, firstStart + SECOND_IN_MILLIS, 128L, 256L);
+        stats.recordData(lastStart, lastStart + SECOND_IN_MILLIS, 64L, 512L);
+
+        // we should have two buckets, far apart from each other
+        assertEquals(2, stats.bucketCount);
+        assertBucket(stats, 0, 128L, 256L);
+        assertBucket(stats, 1, 64L, 512L);
+
+        // now record something in middle, spread across two buckets
+        final long middleStart = TEST_START + DAY_IN_MILLIS;
+        final long middleEnd = middleStart + (HOUR_IN_MILLIS * 2);
+        stats.recordData(middleStart, middleEnd, 2048L, 2048L);
+
+        // now should have four buckets, with new record in middle two buckets
+        assertEquals(4, stats.bucketCount);
+        assertBucket(stats, 0, 128L, 256L);
+        assertBucket(stats, 1, 1024L, 1024L);
+        assertBucket(stats, 2, 1024L, 1024L);
+        assertBucket(stats, 3, 64L, 512L);
+    }
+
+    public void testRecordOverlapBuckets() throws Exception {
+        final long BUCKET_SIZE = HOUR_IN_MILLIS;
+        stats = buildStats(BUCKET_SIZE);
+
+        // record some data in one bucket, and another overlapping buckets
+        stats.recordData(TEST_START, TEST_START + SECOND_IN_MILLIS, 256L, 256L);
+        final long midStart = TEST_START + (HOUR_IN_MILLIS / 2);
+        stats.recordData(midStart, midStart + HOUR_IN_MILLIS, 1024L, 1024L);
+
+        // should have two buckets, with some data mixed together
+        assertEquals(2, stats.bucketCount);
+        assertBucket(stats, 0, 768L, 768L);
+        assertBucket(stats, 1, 512L, 512L);
+    }
+
+    public void testRemove() throws Exception {
+        final long BUCKET_SIZE = HOUR_IN_MILLIS;
+        stats = buildStats(BUCKET_SIZE);
+
+        // record some data across 24 buckets
+        stats.recordData(TEST_START, TEST_START + DAY_IN_MILLIS, 24L, 24L);
+        assertEquals(24, stats.bucketCount);
+
+        // try removing far before buckets; should be no change
+        stats.removeBucketsBefore(TEST_START - YEAR_IN_MILLIS);
+        assertEquals(24, stats.bucketCount);
+
+        // try removing just moments into first bucket; should be no change
+        // since that bucket contains data beyond the cutoff
+        stats.removeBucketsBefore(TEST_START + SECOND_IN_MILLIS);
+        assertEquals(24, stats.bucketCount);
+
+        // try removing single bucket
+        stats.removeBucketsBefore(TEST_START + HOUR_IN_MILLIS);
+        assertEquals(23, stats.bucketCount);
+
+        // try removing multiple buckets
+        stats.removeBucketsBefore(TEST_START + (4 * HOUR_IN_MILLIS));
+        assertEquals(20, stats.bucketCount);
+
+        // try removing all buckets
+        stats.removeBucketsBefore(TEST_START + YEAR_IN_MILLIS);
+        assertEquals(0, stats.bucketCount);
+    }
+
+    @Suppress
+    public void testFuzzing() throws Exception {
+        try {
+            // fuzzing with random events, looking for crashes
+            final Random r = new Random();
+            for (int i = 0; i < 500; i++) {
+                stats = buildStats(r.nextLong());
+                for (int j = 0; j < 10000; j++) {
+                    if (r.nextBoolean()) {
+                        // add range
+                        final long start = r.nextLong();
+                        final long end = start + r.nextInt();
+                        stats.recordData(start, end, r.nextLong(), r.nextLong());
+                    } else {
+                        // trim something
+                        stats.removeBucketsBefore(r.nextLong());
+                    }
+                }
+                assertConsistent(stats);
+            }
+        } catch (Throwable e) {
+            Log.e(TAG, String.valueOf(stats));
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static NetworkStatsHistory buildStats(long bucketSize) {
+        return new NetworkStatsHistory(TYPE_MOBILE, null, UID_ALL, bucketSize);
+    }
+
+    private static void assertConsistent(NetworkStatsHistory stats) {
+        // verify timestamps are monotonic
+        for (int i = 1; i < stats.bucketCount; i++) {
+            assertTrue(stats.bucketStart[i - 1] < stats.bucketStart[i]);
+        }
+    }
+
+    private static void assertBucket(NetworkStatsHistory stats, int index, long rx, long tx) {
+        assertEquals("unexpected rx", rx, stats.rx[index]);
+        assertEquals("unexpected tx", tx, stats.tx[index]);
+    }
+
+}
diff --git a/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java
index 45719c2..23eb9cf 100644
--- a/core/tests/coretests/src/android/net/NetworkStatsTest.java
+++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java
@@ -47,8 +47,9 @@
                 .addEntry(TEST_IFACE, 100, 1024, 0)
                 .addEntry(TEST_IFACE, 101, 0, 1024).build();
 
-        final NetworkStats result = after.subtract(before);
+        final NetworkStats result = after.subtract(before, true);
 
+        // identical data should result in zero delta
         assertEquals(0, result.rx[0]);
         assertEquals(0, result.tx[0]);
         assertEquals(0, result.rx[1]);
@@ -64,7 +65,7 @@
                 .addEntry(TEST_IFACE, 100, 1025, 2)
                 .addEntry(TEST_IFACE, 101, 3, 1028).build();
 
-        final NetworkStats result = after.subtract(before);
+        final NetworkStats result = after.subtract(before, true);
 
         // expect delta between measurements
         assertEquals(1, result.rx[0]);
@@ -83,7 +84,7 @@
                 .addEntry(TEST_IFACE, 101, 0, 1024)
                 .addEntry(TEST_IFACE, 102, 1024, 1024).build();
 
-        final NetworkStats result = after.subtract(before);
+        final NetworkStats result = after.subtract(before, true);
 
         // its okay to have new rows
         assertEquals(0, result.rx[0]);
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/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index d51c202..17f0fa6 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -22,6 +22,7 @@
 import android.content.res.AssetManager;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
+import android.os.Process;
 import android.util.Log;
 import android.view.Surface;
 
@@ -683,9 +684,8 @@
      * processes.
      */
     public enum Priority {
-        // Remap these numbers to opaque...
-        LOW (5),     //ANDROID_PRIORITY_BACKGROUND + 5
-        NORMAL (-4);  //ANDROID_PRIORITY_DISPLAY
+        LOW (Process.THREAD_PRIORITY_BACKGROUND + (5 * Process.THREAD_PRIORITY_LESS_FAVORABLE)),
+        NORMAL (Process.THREAD_PRIORITY_DISPLAY);
 
         int mID;
         Priority(int id) {
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
index 6b6fcdf..48d1464 100644
--- a/include/media/stagefright/DataSource.h
+++ b/include/media/stagefright/DataSource.h
@@ -38,6 +38,7 @@
         kWantsPrefetching      = 1,
         kStreamedFromLocalHost = 2,
         kIsCachingDataSource   = 4,
+        kIsHTTPBasedSource     = 8,
     };
 
     static sp<DataSource> CreateFromURI(
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 072329d..20abd51 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -26,7 +26,6 @@
 
 // ----------------------------------------------------------------------------
 
-#define THREAD_PRIORITY_AUDIO_CLIENT (ANDROID_PRIORITY_AUDIO)
 // Maximum cumulated timeout milliseconds before restarting audioflinger thread
 #define MAX_STARTUP_TIMEOUT_MS  3000    // Longer timeout period at startup to cope with A2DP init time
 #define MAX_RUN_TIMEOUT_MS      1000
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/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index f6c4cc7..a41d7ab 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -315,9 +315,9 @@
             cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
             cblk->waitTimeMs = 0;
             if (t != 0) {
-               t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT);
+               t->run("ClientRecordThread", ANDROID_PRIORITY_AUDIO);
             } else {
-                setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
+                setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
             }
         } else {
             mActive = 0;
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index ea44f87..6b4391b 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -342,9 +342,9 @@
         cblk->waitTimeMs = 0;
         android_atomic_and(~CBLK_DISABLED_ON, &cblk->flags);
         if (t != 0) {
-           t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT);
+           t->run("AudioTrackThread", ANDROID_PRIORITY_AUDIO);
         } else {
-            setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
+            setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
         }
 
         LOGV("start %p before lock cblk %p", this, mCblk);
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 07a47e5..3a58d3f 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -715,7 +715,7 @@
 
 void AwesomePlayer::sendCacheStats() {
     sp<MediaPlayerBase> listener = mListener.promote();
-    if (listener != NULL) {
+    if (listener != NULL && mCachedSource != NULL) {
         int32_t kbps = 0;
         status_t err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
         if (err == OK) {
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index b2ed427..77a6602 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -203,13 +203,19 @@
 }
 
 status_t NuCachedSource2::getEstimatedBandwidthKbps(int32_t *kbps) {
-    HTTPBase* source = static_cast<HTTPBase *>(mSource.get());
-    return source->getEstimatedBandwidthKbps(kbps);
+    if (mSource->flags() & kIsHTTPBasedSource) {
+        HTTPBase* source = static_cast<HTTPBase *>(mSource.get());
+        return source->getEstimatedBandwidthKbps(kbps);
+    }
+    return ERROR_UNSUPPORTED;
 }
 
 status_t NuCachedSource2::setCacheStatCollectFreq(int32_t freqMs) {
-    HTTPBase *source = static_cast<HTTPBase *>(mSource.get());
-    return source->setBandwidthStatCollectFreq(freqMs);
+    if (mSource->flags() & kIsHTTPBasedSource) {
+        HTTPBase *source = static_cast<HTTPBase *>(mSource.get());
+        return source->setBandwidthStatCollectFreq(freqMs);
+    }
+    return ERROR_UNSUPPORTED;
 }
 
 status_t NuCachedSource2::initCheck() const {
@@ -221,7 +227,9 @@
 }
 
 uint32_t NuCachedSource2::flags() {
-    return (mSource->flags() & ~kWantsPrefetching) | kIsCachingDataSource;
+    // Remove HTTP related flags since NuCachedSource2 is not HTTP-based.
+    uint32_t flags = mSource->flags() & ~(kWantsPrefetching | kIsHTTPBasedSource);
+    return (flags | kIsCachingDataSource);
 }
 
 void NuCachedSource2::onMessageReceived(const sp<AMessage> &msg) {
diff --git a/media/libstagefright/NuHTTPDataSource.cpp b/media/libstagefright/NuHTTPDataSource.cpp
index c3b5e8f..dac2ee4 100644
--- a/media/libstagefright/NuHTTPDataSource.cpp
+++ b/media/libstagefright/NuHTTPDataSource.cpp
@@ -464,7 +464,7 @@
 }
 
 uint32_t NuHTTPDataSource::flags() {
-    return kWantsPrefetching;
+    return kWantsPrefetching | kIsHTTPBasedSource;
 }
 
 // static
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/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
index ad1f342..588a74d 100644
--- a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
+++ b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
@@ -218,7 +218,7 @@
 }
 
 uint32_t ChromiumHTTPDataSource::flags() {
-    return kWantsPrefetching;
+    return kWantsPrefetching | kIsHTTPBasedSource;
 }
 
 // static
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index 31fc0e5..2d6cb84 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -47,10 +47,14 @@
 
     size_t cachedSize();
     size_t approxDataRemaining(status_t *finalStatus);
-    status_t setCacheStatCollectFreq(int32_t freqMs);
 
     void resumeFetchingIfNecessary();
+
+    // The following methods are supported only if the
+    // data source is HTTP-based; otherwise, ERROR_UNSUPPORTED
+    // is returned.
     status_t getEstimatedBandwidthKbps(int32_t *kbps);
+    status_t setCacheStatCollectFreq(int32_t freqMs);
 
 protected:
     virtual ~NuCachedSource2();
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/VideoEditorPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/VideoEditorPerformance.java
index 4c66a2d..7eb6d22 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/VideoEditorPerformance.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/VideoEditorPerformance.java
@@ -112,12 +112,11 @@
 
     private final int NUM_OF_ITERATIONS=20;
 
-    private float calculateTimeTaken(long beginTime, int numIterations)
+    private int calculateTimeTaken(long beginTime, int numIterations)
         throws Exception {
         final long duration2 = SystemClock.uptimeMillis();
         final long durationToCreateMediaItem = (duration2 - beginTime);
-        final float timeTaken1 = (float)durationToCreateMediaItem *
-            1.0f/(float)numIterations;
+        final int timeTaken1 = (int)(durationToCreateMediaItem / numIterations);
         return (timeTaken1);
     }
 
@@ -208,7 +207,7 @@
         final String[] loggingInfo = new String[3];
         final MediaVideoItem[] mediaVideoItem =
             new MediaVideoItem[NUM_OF_ITERATIONS];
-        float timeTaken = 0.0f;
+        int timeTaken = 0;
         long startTime = 0;
 
         /** Time Take for creation of Media Video Item */
@@ -251,7 +250,7 @@
         final String[] loggingInfo = new String[3];
         final MediaImageItem[] mediaImageItem =
             new MediaImageItem[NUM_OF_ITERATIONS];
-        float timeTaken = 0.0f;
+        int timeTaken = 0;
 
         long beginTime = SystemClock.uptimeMillis();
         createImageItems(mediaImageItem, imageItemFileName, renderingMode,
@@ -296,7 +295,7 @@
         final int transitionDuration = 5000;
         final int transitionBehavior = Transition.BEHAVIOR_MIDDLE_FAST;
         final String[] loggingInfo = new String[3];
-        float timeTaken = 0.0f;
+        int timeTaken = 0;
 
         final MediaVideoItem[] mediaVideoItem =
             new MediaVideoItem[(NUM_OF_ITERATIONS *10) + 1];
@@ -514,7 +513,7 @@
         /** 18.Enable Looping for Audio Track.
          * */
         audioTrack.enableLoop();
-        float timeTaken = 0.0f;
+        int timeTaken = 0;
         final long beginTime = SystemClock.uptimeMillis();
             try {
                 mVideoEditor.export(outFilename, outHeight, outBitrate,
@@ -557,7 +556,7 @@
         mediaVideoItem.setExtractBoundaries(videoItemStartTime,
             videoItemEndTime);
 
-        float timeTaken = 0.0f;
+        int timeTaken = 0;
         long beginTime = SystemClock.uptimeMillis();
         for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
             mediaVideoItem.getThumbnail(mediaVideoItem.getWidth() / 2,
@@ -603,7 +602,7 @@
         final OverlayFrame overlayFrame[] = new OverlayFrame[NUM_OF_ITERATIONS];
         final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(overlayFilename,
             640, 480);
-        float timeTaken = 0.0f;
+        int timeTaken = 0;
         long beginTime = SystemClock.uptimeMillis();
         for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
             overlayFrame[i] = new OverlayFrame(mediaVideoItem, "overlay" + i,
@@ -647,7 +646,7 @@
         final int videoProfile = MediaProperties.H264_PROFILE_0_LEVEL_1_3;
         final int width = 1080;
         final int height = MediaProperties.HEIGHT_720;
-        float timeTaken = 0.0f;
+        int timeTaken = 0;
         final String[] loggingInfo = new String[1];
         final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
             "m0", videoItemFileName1, renderingMode);
@@ -1006,7 +1005,7 @@
         final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
         final int audioVolume = 50;
         final String[] loggingInfo = new String[2];
-        float timeTaken = 0.0f;
+        int timeTaken = 0;
 
         final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
             "mediaItem1", videoItemFileName1, renderingMode);
@@ -1057,7 +1056,7 @@
         final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
         final String[] loggingInfo = new String[3];
 
-        float timeTaken = 0.0f;
+        int timeTaken = 0;
 
         final MediaImageItem[] mediaImageItem =
             new MediaImageItem[NUM_OF_ITERATIONS];
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/BackupRestoreConfirmation/res/layout/confirm_backup.xml b/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml
index 109cfff..a4564e6 100644
--- a/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml
+++ b/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml
@@ -37,6 +37,7 @@
               android:layout_marginBottom="30dp" />
 
     <Button android:id="@+id/button_allow"
+            android:filterTouchesWhenObscured="true"
             android:text="@string/allow_backup_button_label"
             android:layout_below="@id/package_name"
             android:layout_height="wrap_content"
diff --git a/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml b/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml
index a1f9a4a..ca99ae1 100644
--- a/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml
+++ b/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml
@@ -37,6 +37,7 @@
               android:layout_marginBottom="30dp" />
 
     <Button android:id="@+id/button_allow"
+            android:filterTouchesWhenObscured="true"
             android:text="@string/allow_restore_button_label"
             android:layout_below="@id/package_name"
             android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/values-large/config.xml b/packages/SystemUI/res/values-large/config.xml
index 299ab97..4014f8d 100644
--- a/packages/SystemUI/res/values-large/config.xml
+++ b/packages/SystemUI/res/values-large/config.xml
@@ -20,14 +20,7 @@
 <!-- These resources are around just to allow their values to be customized
      for different hardware and product builds. -->
 <resources>
-    <integer name="config_status_bar_position">1</integer>
-
-    <!-- Component to be used as the status bar service.  Must implement the IStatusBar
-     interface.  This name is in the ComponentName flattened format (package/class)  -->
-    <string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.tablet.TabletStatusBar</string>
-
     <!-- Whether or not we show the number in the bar. -->
     <bool name="config_statusBarShowNumber">false</bool>
-
 </resources>
 
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 954a871..7a4ac5d 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -25,16 +25,14 @@
     data icon on devices -->
     <bool name="config_hspa_data_distinguishable">false</bool>
 
-    <!-- The location of the status bar.
-        0 - top
-        1 - bottom
-    -->
-    <integer name="config_status_bar_position">0</integer>
-
     <!-- Component to be used as the status bar service.  Must implement the IStatusBar
      interface.  This name is in the ComponentName flattened format (package/class)  -->
     <string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.PhoneStatusBar</string>
 
+    <!-- Component to be used as the system bar service.  Must implement the IStatusBar
+     interface.  This name is in the ComponentName flattened format (package/class)  -->
+    <string name="config_systemBarComponent" translatable="false">com.android.systemui.statusbar.tablet.TabletStatusBar</string>
+
     <!-- Whether or not we show the number in the bar. -->
     <bool name="config_statusBarShowNumber">true</bool>
 
@@ -42,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/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index 870acd3..d7a5056 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -27,7 +27,10 @@
 import android.content.res.Configuration;
 import android.os.Binder;
 import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.util.Slog;
+import android.view.IWindowManager;
 
 public class SystemUIService extends Service {
     static final String TAG = "SystemUIService";
@@ -36,7 +39,7 @@
      * The class names of the stuff to start.
      */
     final Object[] SERVICES = new Object[] {
-            R.string.config_statusBarComponent,
+            0, // system bar or status bar, filled in below.
             com.android.systemui.power.PowerUI.class,
         };
 
@@ -62,6 +65,17 @@
 
     @Override
     public void onCreate() {
+        // Pick status bar or system bar.
+        IWindowManager wm = IWindowManager.Stub.asInterface(
+                ServiceManager.getService(Context.WINDOW_SERVICE));
+        try {
+            SERVICES[0] = wm.canStatusBarHide()
+                    ? R.string.config_statusBarComponent
+                    : R.string.config_systemBarComponent;
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Failing checking whether status bar can hide", e);
+        }
+
         final int N = SERVICES.length;
         mServices = new SystemUI[N];
         for (int i=0; i<N; i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
index e9db998..339e3f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
@@ -422,9 +422,8 @@
             Log.d(TAG, "Get text from: " + imi.getPackageName() + subtype.getNameResId()
                     + imi.getServiceInfo().applicationInfo);
         }
-        // TODO: Change the language of subtype name according to subtype's locale.
-        return mPackageManager.getText(
-                imi.getPackageName(), subtype.getNameResId(), imi.getServiceInfo().applicationInfo);
+        return subtype.getDisplayName(
+                mContext, imi.getPackageName(), imi.getServiceInfo().applicationInfo);
     }
 
     private Drawable getSubtypeIcon(InputMethodInfo imi, InputMethodSubtype subtype) {
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 63bc9b7..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();
 
@@ -331,10 +329,10 @@
         final Resources res = mContext.getResources();
 
         mNaturalBarHeight = res.getDimensionPixelSize(
-                com.android.internal.R.dimen.status_bar_height);
+                com.android.internal.R.dimen.system_bar_height);
 
         int newIconSize = res.getDimensionPixelSize(
-            com.android.internal.R.dimen.status_bar_icon_size);
+            com.android.internal.R.dimen.system_bar_icon_size);
         int newIconHPadding = res.getDimensionPixelSize(
             R.dimen.status_bar_icon_padding);
 
@@ -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/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index d997109..75f466a 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -1446,7 +1446,9 @@
         }
 
         if (mActionBar != null) {
-            outState.putBoolean(ACTION_BAR_TAG, mActionBar.isOverflowMenuShowing());
+            SparseArray<Parcelable> actionBarStates = new SparseArray<Parcelable>();
+            mActionBar.saveHierarchyState(actionBarStates);
+            outState.putSparseParcelableArray(ACTION_BAR_TAG, actionBarStates);
         }
 
         return outState;
@@ -1484,8 +1486,10 @@
             restorePanelState(panelStates);
         }
 
-        if (mActionBar != null && savedInstanceState.getBoolean(ACTION_BAR_TAG)) {
-            mActionBar.postShowOverflowMenu();
+        if (mActionBar != null) {
+            SparseArray<Parcelable> actionBarStates =
+                    savedInstanceState.getSparseParcelableArray(ACTION_BAR_TAG);
+            mActionBar.restoreHierarchyState(actionBarStates);
         }
     }
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index e48dbe9..6eaba21 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -56,6 +56,7 @@
 import com.android.internal.view.BaseInputHandler;
 import com.android.internal.widget.PointerLocationView;
 
+import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
@@ -745,15 +746,14 @@
         mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
                 com.android.internal.R.array.config_safeModeEnabledVibePattern);
 
-        // Note: the Configuration is not stable here, so we cannot load mStatusBarCanHide from
-        // config_statusBarCanHide because the latter depends on the screen size
-
         // Controls rotation and the like.
         initializeHdmiState();
     }
 
     public void setInitialDisplaySize(int width, int height) {
+        int shortSize;
         if (width > height) {
+            shortSize = height;
             mLandscapeRotation = Surface.ROTATION_0;
             mSeascapeRotation = Surface.ROTATION_180;
             if (mContext.getResources().getBoolean(
@@ -765,6 +765,7 @@
                 mUpsideDownRotation = Surface.ROTATION_90;
             }
         } else {
+            shortSize = width;
             mPortraitRotation = Surface.ROTATION_0;
             mUpsideDownRotation = Surface.ROTATION_180;
             if (mContext.getResources().getBoolean(
@@ -776,6 +777,17 @@
                 mSeascapeRotation = Surface.ROTATION_270;
             }
         }
+
+        // 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;
+        mStatusBarCanHide = shortSizeDp < 600;
+        mStatusBarHeight = mContext.getResources().getDimensionPixelSize(
+                mStatusBarCanHide
+                ? com.android.internal.R.dimen.status_bar_height
+                : com.android.internal.R.dimen.system_bar_height);
     }
 
     public void updateSettings() {
@@ -1083,6 +1095,10 @@
         return STATUS_BAR_LAYER;
     }
 
+    public boolean canStatusBarHide() {
+        return mStatusBarCanHide;
+    }
+
     public int getNonDecorDisplayWidth(int rotation, int fullWidth) {
         return fullWidth;
     }
@@ -1244,13 +1260,6 @@
                     return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
                 }
                 mStatusBar = win;
-
-                // The Configuration will be stable by now, so we can load this
-                mStatusBarCanHide = mContext.getResources().getBoolean(
-                        com.android.internal.R.bool.config_statusBarCanHide);
-                mStatusBarHeight = mContext.getResources().getDimensionPixelSize(
-                        com.android.internal.R.dimen.status_bar_height);
-
                 break;
             case TYPE_NAVIGATION_BAR:
                 mContext.enforceCallingOrSelfPermission(
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/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index a564c2d..dd76eb8 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -16,6 +16,11 @@
 
 package com.android.server;
 
+import static android.Manifest.permission.UPDATE_DEVICE_STATS;
+import static android.net.ConnectivityManager.isNetworkTypeValid;
+import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
+import static android.net.NetworkPolicyManager.RULE_REJECT_PAID;
+
 import android.bluetooth.BluetoothTetheringDataTracker;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -26,11 +31,13 @@
 import android.net.DummyDataStateTracker;
 import android.net.EthernetDataTracker;
 import android.net.IConnectivityManager;
-import android.net.LinkAddress;
+import android.net.INetworkPolicyListener;
+import android.net.INetworkPolicyManager;
 import android.net.LinkProperties;
 import android.net.MobileDataStateTracker;
 import android.net.NetworkConfig;
 import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkStateTracker;
 import android.net.NetworkUtils;
 import android.net.Proxy;
@@ -54,6 +61,7 @@
 import android.text.TextUtils;
 import android.util.EventLog;
 import android.util.Slog;
+import android.util.SparseIntArray;
 
 import com.android.internal.telephony.Phone;
 import com.android.server.connectivity.Tethering;
@@ -62,13 +70,12 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.net.InetAddress;
-import java.net.Inet4Address;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.GregorianCalendar;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * @hide
@@ -78,6 +85,8 @@
     private static final boolean DBG = true;
     private static final String TAG = "ConnectivityService";
 
+    private static final boolean LOGD_RULES = false;
+
     // how long to wait before switching back to a radio's default network
     private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
     // system property that can override the above value
@@ -91,6 +100,9 @@
     private Tethering mTethering;
     private boolean mTetheringConfigValid = false;
 
+    /** Currently active network rules by UID. */
+    private SparseIntArray mUidRules = new SparseIntArray();
+
     /**
      * Sometimes we want to refer to the individual network state
      * trackers separately, and sometimes we just want to treat them
@@ -128,6 +140,7 @@
     private AtomicBoolean mBackgroundDataEnabled = new AtomicBoolean(true);
 
     private INetworkManagementService mNetd;
+    private INetworkPolicyManager mPolicyManager;
 
     private static final int ENABLED  = 1;
     private static final int DISABLED = 0;
@@ -250,14 +263,8 @@
     }
     RadioAttributes[] mRadioAttributes;
 
-    public static synchronized ConnectivityService getInstance(Context context) {
-        if (sServiceInstance == null) {
-            sServiceInstance = new ConnectivityService(context);
-        }
-        return sServiceInstance;
-    }
-
-    private ConnectivityService(Context context) {
+    public ConnectivityService(
+            Context context, INetworkManagementService netd, INetworkPolicyManager policyManager) {
         if (DBG) log("ConnectivityService starting up");
 
         HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread");
@@ -290,9 +297,19 @@
             loge("Error setting defaultDns using " + dns);
         }
 
-        mContext = context;
+        mContext = checkNotNull(context, "missing Context");
+        mNetd = checkNotNull(netd, "missing INetworkManagementService");
+        mPolicyManager = checkNotNull(policyManager, "missing INetworkPolicyManager");
 
-        PowerManager powerManager = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
+        try {
+            mPolicyManager.registerListener(mPolicyListener);
+        } catch (RemoteException e) {
+            // ouch, no rules updates means some processes may never get network
+            Slog.e(TAG, "unable to register INetworkPolicyListener", e);
+        }
+
+        final PowerManager powerManager = (PowerManager) context.getSystemService(
+                Context.POWER_SERVICE);
         mNetTransitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
         mNetTransitionWakeLockTimeout = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_networkTransitionTimeout);
@@ -536,32 +553,92 @@
     }
 
     /**
+     * Check if UID is blocked from using the given {@link NetworkInfo}.
+     */
+    private boolean isNetworkBlocked(NetworkInfo info, int uid) {
+        synchronized (mUidRules) {
+            return isNetworkBlockedLocked(info, uid);
+        }
+    }
+
+    /**
+     * Check if UID is blocked from using the given {@link NetworkInfo}.
+     */
+    private boolean isNetworkBlockedLocked(NetworkInfo info, int uid) {
+        // TODO: expand definition of "paid" network to cover tethered or paid
+        // hotspot use cases.
+        final boolean networkIsPaid = info.getType() != ConnectivityManager.TYPE_WIFI;
+        final int uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
+
+        if (networkIsPaid && (uidRules & RULE_REJECT_PAID) != 0) {
+            return true;
+        }
+
+        // no restrictive rules; network is visible
+        return false;
+    }
+
+    /**
      * Return NetworkInfo for the active (i.e., connected) network interface.
      * It is assumed that at most one network is active at a time. If more
      * than one is active, it is indeterminate which will be returned.
      * @return the info for the active network, or {@code null} if none is
      * active
      */
+    @Override
     public NetworkInfo getActiveNetworkInfo() {
-        return getNetworkInfo(mActiveDefaultNetwork);
+        enforceAccessPermission();
+        final int uid = Binder.getCallingUid();
+        return getNetworkInfo(mActiveDefaultNetwork, uid);
     }
 
+    @Override
+    public NetworkInfo getActiveNetworkInfoForUid(int uid) {
+        enforceConnectivityInternalPermission();
+        return getNetworkInfo(mActiveDefaultNetwork, uid);
+    }
+
+    @Override
     public NetworkInfo getNetworkInfo(int networkType) {
         enforceAccessPermission();
-        if (ConnectivityManager.isNetworkTypeValid(networkType)) {
-            NetworkStateTracker t = mNetTrackers[networkType];
-            if (t != null)
-                return t.getNetworkInfo();
-        }
-        return null;
+        final int uid = Binder.getCallingUid();
+        return getNetworkInfo(networkType, uid);
     }
 
+    private NetworkInfo getNetworkInfo(int networkType, int uid) {
+        NetworkInfo info = null;
+        if (isNetworkTypeValid(networkType)) {
+            final NetworkStateTracker tracker = mNetTrackers[networkType];
+            if (tracker != null) {
+                info = tracker.getNetworkInfo();
+                if (isNetworkBlocked(info, uid)) {
+                    // network is blocked; clone and override state
+                    info = new NetworkInfo(info);
+                    info.setDetailedState(DetailedState.BLOCKED, null, null);
+                }
+            }
+        }
+        return info;
+    }
+
+    @Override
     public NetworkInfo[] getAllNetworkInfo() {
         enforceAccessPermission();
-        NetworkInfo[] result = new NetworkInfo[mNetworksDefined];
+        final int uid = Binder.getCallingUid();
+        final NetworkInfo[] result = new NetworkInfo[mNetworksDefined];
         int i = 0;
-        for (NetworkStateTracker t : mNetTrackers) {
-            if(t != null) result[i++] = t.getNetworkInfo();
+        synchronized (mUidRules) {
+            for (NetworkStateTracker tracker : mNetTrackers) {
+                if (tracker != null) {
+                    NetworkInfo info = tracker.getNetworkInfo();
+                    if (isNetworkBlockedLocked(info, uid)) {
+                        // network is blocked; clone and override state
+                        info = new NetworkInfo(info);
+                        info.setDetailedState(DetailedState.BLOCKED, null, null);
+                    }
+                    result[i++] = info;
+                }
+            }
         }
         return result;
     }
@@ -574,15 +651,19 @@
      * @return the ip properties for the active network, or {@code null} if
      * none is active
      */
+    @Override
     public LinkProperties getActiveLinkProperties() {
         return getLinkProperties(mActiveDefaultNetwork);
     }
 
+    @Override
     public LinkProperties getLinkProperties(int networkType) {
         enforceAccessPermission();
-        if (ConnectivityManager.isNetworkTypeValid(networkType)) {
-            NetworkStateTracker t = mNetTrackers[networkType];
-            if (t != null) return t.getLinkProperties();
+        if (isNetworkTypeValid(networkType)) {
+            final NetworkStateTracker tracker = mNetTrackers[networkType];
+            if (tracker != null) {
+                return tracker.getLinkProperties();
+            }
         }
         return null;
     }
@@ -1027,6 +1108,30 @@
         }
     }
 
+    private INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
+        @Override
+        public void onRulesChanged(int uid, int uidRules) {
+            // only someone like NPMS should only be calling us
+            // TODO: create permission for modifying data policy
+            mContext.enforceCallingOrSelfPermission(UPDATE_DEVICE_STATS, TAG);
+
+            if (LOGD_RULES) {
+                Slog.d(TAG, "onRulesChanged(uid=" + uid + ", uidRules=" + uidRules + ")");
+            }
+
+            synchronized (mUidRules) {
+                // skip update when we've already applied rules
+                final int oldRules = mUidRules.get(uid, RULE_ALLOW_ALL);
+                if (oldRules == uidRules) return;
+
+                mUidRules.put(uid, uidRules);
+            }
+
+            // TODO: dispatch into NMS to push rules towards kernel module
+            // TODO: notify UID when it has requested targeted updates
+        }
+    };
+
     /**
      * @see ConnectivityManager#setMobileDataEnabled(boolean)
      */
@@ -1284,9 +1389,6 @@
     }
 
     void systemReady() {
-        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
-        mNetd = INetworkManagementService.Stub.asInterface(b);
-
         synchronized(this) {
             mSystemReady = true;
             if (mInitialBroadcast != null) {
@@ -2255,4 +2357,11 @@
         }
         return networkType;
     }
+
+    private static <T> T checkNotNull(T value, String message) {
+        if (value == null) {
+            throw new NullPointerException(message);
+        }
+        return value;
+    }
 }
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index 78636f3..3181a9d 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -148,7 +148,7 @@
         int minimumPasswordLowerCase = DEF_MINIMUM_PASSWORD_LOWER_CASE;
 
         static final int DEF_MINIMUM_PASSWORD_LETTERS = 1;
-        int minimumPasswordLetters = DEF_MINIMUM_PASSWORD_LOWER_CASE;
+        int minimumPasswordLetters = DEF_MINIMUM_PASSWORD_LETTERS;
 
         static final int DEF_MINIMUM_PASSWORD_NUMERIC = 1;
         int minimumPasswordNumeric = DEF_MINIMUM_PASSWORD_NUMERIC;
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index c96273b..f4308cd 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -1885,8 +1885,8 @@
                             int nameResId = subtype.getNameResId();
                             String mode = subtype.getMode();
                             if (nameResId != 0) {
-                                title = TextUtils.concat(pm.getText(imi.getPackageName(),
-                                        nameResId, imi.getServiceInfo().applicationInfo),
+                                title = TextUtils.concat(subtype.getDisplayName(context,
+                                        imi.getPackageName(), imi.getServiceInfo().applicationInfo),
                                         (TextUtils.isEmpty(label) ? "" : " (" + label + ")"));
                             } else {
                                 CharSequence language = subtype.getLocale();
diff --git a/services/java/com/android/server/NetStatService.java b/services/java/com/android/server/NetStatService.java
deleted file mode 100644
index 7fe6743..0000000
--- a/services/java/com/android/server/NetStatService.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server;
-
-import android.content.Context;
-import android.net.TrafficStats;
-import android.os.INetStatService;
-import android.os.SystemClock;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
-public class NetStatService extends INetStatService.Stub {
-    private final Context mContext;
-
-    public NetStatService(Context context) {
-        mContext = context;
-    }
-
-    public long getMobileTxPackets() {
-        return TrafficStats.getMobileTxPackets();
-    }
-
-    public long getMobileRxPackets() {
-        return TrafficStats.getMobileRxPackets();
-    }
-
-    public long getMobileTxBytes() {
-        return TrafficStats.getMobileTxBytes();
-    }
-
-    public long getMobileRxBytes() {
-        return TrafficStats.getMobileRxBytes();
-    }
-
-    public long getTotalTxPackets() {
-        return TrafficStats.getTotalTxPackets();
-    }
-
-    public long getTotalRxPackets() {
-        return TrafficStats.getTotalRxPackets();
-    }
-
-    public long getTotalTxBytes() {
-        return TrafficStats.getTotalTxBytes();
-    }
-
-    public long getTotalRxBytes() {
-        return TrafficStats.getTotalRxBytes();
-    }
-
-    @Override
-    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        // This data is accessible to any app -- no permission check needed.
-
-        pw.print("Elapsed: total=");
-        pw.print(SystemClock.elapsedRealtime());
-        pw.print("ms awake=");
-        pw.print(SystemClock.uptimeMillis());
-        pw.println("ms");
-
-        pw.print("Mobile: Tx=");
-        pw.print(getMobileTxBytes());
-        pw.print("B/");
-        pw.print(getMobileTxPackets());
-        pw.print("Pkts Rx=");
-        pw.print(getMobileRxBytes());
-        pw.print("B/");
-        pw.print(getMobileRxPackets());
-        pw.println("Pkts");
-
-        pw.print("Total: Tx=");
-        pw.print(getTotalTxBytes());
-        pw.print("B/");
-        pw.print(getTotalTxPackets());
-        pw.print("Pkts Rx=");
-        pw.print(getTotalRxBytes());
-        pw.print("B/");
-        pw.print(getTotalRxPackets());
-        pw.println("Pkts");
-    }
-}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 5355d44..596cbac 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -16,19 +16,6 @@
 
 package com.android.server;
 
-import com.android.server.accessibility.AccessibilityManagerService;
-import com.android.server.am.ActivityManagerService;
-import com.android.server.net.NetworkPolicyManagerService;
-import com.android.server.pm.PackageManagerService;
-import com.android.server.usb.UsbService;
-import com.android.server.wm.WindowManagerService;
-import com.android.internal.app.ShutdownThread;
-import com.android.internal.os.BinderInternal;
-import com.android.internal.os.SamplingProfilerIntegration;
-
-import dalvik.system.VMRuntime;
-import dalvik.system.Zygote;
-
 import android.accounts.AccountManagerService;
 import android.app.ActivityManagerNative;
 import android.bluetooth.BluetoothAdapter;
@@ -41,25 +28,35 @@
 import android.content.res.Configuration;
 import android.database.ContentObserver;
 import android.media.AudioService;
-import android.os.Build;
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.StrictMode;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.provider.Contacts.People;
 import android.provider.Settings;
 import android.server.BluetoothA2dpService;
 import android.server.BluetoothService;
 import android.server.search.SearchManagerService;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
-import android.util.Log;
 import android.util.Slog;
-import android.view.Display;
 import android.view.WindowManager;
 
+import com.android.internal.app.ShutdownThread;
+import com.android.internal.os.BinderInternal;
+import com.android.internal.os.SamplingProfilerIntegration;
+import com.android.server.accessibility.AccessibilityManagerService;
+import com.android.server.am.ActivityManagerService;
+import com.android.server.net.NetworkPolicyManagerService;
+import com.android.server.net.NetworkStatsService;
+import com.android.server.pm.PackageManagerService;
+import com.android.server.usb.UsbService;
+import com.android.server.wm.WindowManagerService;
+
+import dalvik.system.VMRuntime;
+import dalvik.system.Zygote;
+
 import java.io.File;
 import java.util.Timer;
 import java.util.TimerTask;
@@ -120,6 +117,9 @@
         LightsService lights = null;
         PowerManagerService power = null;
         BatteryService battery = null;
+        AlarmManagerService alarm = null;
+        NetworkManagementService networkManagement = null;
+        NetworkStatsService networkStats = null;
         NetworkPolicyManagerService networkPolicy = null;
         ConnectivityService connectivity = null;
         IPackageManager pm = null;
@@ -191,7 +191,7 @@
             power.init(context, lights, ActivityManagerService.getDefault(), battery);
 
             Slog.i(TAG, "Alarm Manager");
-            AlarmManagerService alarm = new AlarmManagerService(context);
+            alarm = new AlarmManagerService(context);
             ServiceManager.addService(Context.ALARM_SERVICE, alarm);
 
             Slog.i(TAG, "Init Watchdog");
@@ -277,33 +277,33 @@
             }
 
             try {
-                Slog.i(TAG, "NetStat Service");
-                ServiceManager.addService("netstat", new NetStatService(context));
-            } catch (Throwable e) {
-                Slog.e(TAG, "Failure starting NetStat Service", e);
-            }
-
-            try {
-                Slog.i(TAG, "NetworkPolicy Service");
-                networkPolicy = new NetworkPolicyManagerService(
-                        context, ActivityManagerService.self(), power);
-                ServiceManager.addService(Context.NETWORK_POLICY_SERVICE, networkPolicy);
-            } catch (Throwable e) {
-                Slog.e(TAG, "Failure starting Connectivity Service", e);
-            }
-
-            try {
                 Slog.i(TAG, "NetworkManagement Service");
-                ServiceManager.addService(
-                        Context.NETWORKMANAGEMENT_SERVICE,
-                        NetworkManagementService.create(context));
+                networkManagement = NetworkManagementService.create(context);
+                ServiceManager.addService(Context.NETWORKMANAGEMENT_SERVICE, networkManagement);
             } catch (Throwable e) {
                 Slog.e(TAG, "Failure starting NetworkManagement Service", e);
             }
 
             try {
+                Slog.i(TAG, "NetworkStats Service");
+                networkStats = new NetworkStatsService(context, networkManagement, alarm);
+                ServiceManager.addService(Context.NETWORK_STATS_SERVICE, networkStats);
+            } catch (Throwable e) {
+                Slog.e(TAG, "Failure starting NetworkStats Service", e);
+            }
+
+            try {
+                Slog.i(TAG, "NetworkPolicy Service");
+                networkPolicy = new NetworkPolicyManagerService(
+                        context, ActivityManagerService.self(), power, networkStats);
+                ServiceManager.addService(Context.NETWORK_POLICY_SERVICE, networkPolicy);
+            } catch (Throwable e) {
+                Slog.e(TAG, "Failure starting NetworkPolicy Service", e);
+            }
+
+            try {
                 Slog.i(TAG, "Connectivity Service");
-                connectivity = ConnectivityService.getInstance(context);
+                connectivity = new ConnectivityService(context, networkManagement, networkPolicy);
                 ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
             } catch (Throwable e) {
                 Slog.e(TAG, "Failure starting Connectivity Service", e);
@@ -539,6 +539,7 @@
         // These are needed to propagate to the runnable below.
         final Context contextF = context;
         final BatteryService batteryF = battery;
+        final NetworkStatsService networkStatsF = networkStats;
         final NetworkPolicyManagerService networkPolicyF = networkPolicy;
         final ConnectivityService connectivityF = connectivity;
         final DockObserver dockF = dock;
@@ -565,6 +566,7 @@
 
                 startSystemUi(contextF);
                 if (batteryF != null) batteryF.systemReady();
+                if (networkStatsF != null) networkStatsF.systemReady();
                 if (networkPolicyF != null) networkPolicyF.systemReady();
                 if (connectivityF != null) connectivityF.systemReady();
                 if (dockF != null) dockF.systemReady();
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index cc9e532..7801aec 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -41,7 +41,6 @@
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.Binder;
-import android.os.DeadObjectException;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -59,7 +58,6 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -107,16 +105,18 @@
 
     private final SimpleStringSplitter mStringColonSplitter = new SimpleStringSplitter(':');
 
-    private final SparseArray<List<AccessibilityServiceInfo>> mFeedbackTypeToEnabledServicesMap =
-        new SparseArray<List<AccessibilityServiceInfo>>();
-
     private PackageManager mPackageManager;
 
     private int mHandledFeedbackTypes = 0;
 
     private boolean mIsEnabled;
+
     private AccessibilityInputFilter mInputFilter;
 
+    private final List<AccessibilityServiceInfo> mEnabledServicesForFeedbackTempList = new ArrayList<AccessibilityServiceInfo>();
+
+    private boolean mHasInputFilter;
+
     /**
      * Handler for delayed event dispatch.
      */
@@ -259,6 +259,7 @@
                             unbindAllServicesLocked();
                         }
                         updateClientsLocked();
+                        updateInputFilterLocked();
                     }
                 }
             });
@@ -278,9 +279,19 @@
             });
     }
 
-    public boolean addClient(IAccessibilityManagerClient client) {
+    public boolean addClient(IAccessibilityManagerClient client) throws RemoteException {
         synchronized (mLock) {
-            mClients.add(client);
+            final IAccessibilityManagerClient addedClient = client;
+            mClients.add(addedClient);
+            // Clients are registered all the time until their process is
+            // killed, therefore we do not have a corresponding unlinkToDeath.
+            client.asBinder().linkToDeath(new DeathRecipient() {
+                public void binderDied() {
+                    synchronized (mLock) {
+                        mClients.remove(addedClient);
+                    }
+                }
+            }, 0);
             return mIsEnabled;
         }
     }
@@ -307,21 +318,22 @@
     }
 
     public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType) {
-        SparseArray<List<AccessibilityServiceInfo>> feedbackTypeToEnabledServicesMap =
-            mFeedbackTypeToEnabledServicesMap;
-        List<AccessibilityServiceInfo> enabledServices = new ArrayList<AccessibilityServiceInfo>();
+        List<AccessibilityServiceInfo> result = mEnabledServicesForFeedbackTempList;
+        List<Service> services = mServices;
         synchronized (mLock) {
             while (feedbackType != 0) {
                 final int feedbackTypeBit = (1 << Integer.numberOfTrailingZeros(feedbackType));
                 feedbackType &= ~feedbackTypeBit;
-                List<AccessibilityServiceInfo> perFeedbackType =
-                    feedbackTypeToEnabledServicesMap.get(feedbackTypeBit);
-                if (perFeedbackType != null) {
-                    enabledServices.addAll(perFeedbackType);
+                final int serviceCount = services.size();
+                for (int i = 0; i < serviceCount; i++) {
+                    Service service = services.get(i);
+                    if (service.mFeedbackType == feedbackType) {
+                        result.add(service.mAccessibilityServiceInfo);
+                    }
                 }
             }
         }
-        return enabledServices;
+        return result;
     }
 
     public void interrupt() {
@@ -331,16 +343,8 @@
                 try {
                     service.mServiceInterface.onInterrupt();
                 } catch (RemoteException re) {
-                    if (re instanceof DeadObjectException) {
-                        Slog.w(LOG_TAG, "Dead " + service.mService + ". Cleaning up.");
-                        if (removeDeadServiceLocked(service)) {
-                            count--;
-                            i--;
-                        }
-                    } else {
-                        Slog.e(LOG_TAG, "Error during sending interrupt request to "
-                                + service.mService, re);
-                    }
+                    Slog.e(LOG_TAG, "Error during sending interrupt request to "
+                        + service.mService, re);
                 }
             }
         }
@@ -364,8 +368,10 @@
                         service.setAccessibilityServiceInfo(oldInfo);
                     } else {
                         service.setAccessibilityServiceInfo(info);
+                        tryAddServiceLocked(service);
                     }
-                    updateStateOnEnabledService(service);
+
+                    updateInputFilterLocked();
                 }
                 return;
             default:
@@ -490,28 +496,45 @@
                 Slog.i(LOG_TAG, "Event " + event + " sent to " + listener);
             }
         } catch (RemoteException re) {
-            if (re instanceof DeadObjectException) {
-                Slog.w(LOG_TAG, "Dead " + service.mService + ". Cleaning up.");
-                removeDeadServiceLocked(service);
-            } else {
-                Slog.e(LOG_TAG, "Error during sending " + event + " to " + service.mService, re);
-            }
+            Slog.e(LOG_TAG, "Error during sending " + event + " to " + service.mService, re);
         }
     }
 
     /**
-     * Removes a dead service.
+     * Adds a service.
+     *
+     * @param service The service to add.
+     */
+    private void tryAddServiceLocked(Service service) {
+        try {
+            if (mServices.contains(service) || !service.isConfigured()) {
+                return;
+            }
+            service.linkToOwnDeath();
+            mServices.add(service);
+            mComponentNameToServiceMap.put(service.mComponentName, service);
+            updateInputFilterLocked();
+        } catch (RemoteException e) {
+            /* do nothing */
+        }
+    }
+
+    /**
+     * Removes a service.
      *
      * @param service The service.
      * @return True if the service was removed, false otherwise.
      */
-    private boolean removeDeadServiceLocked(Service service) {
-        if (DEBUG) {
-            Slog.i(LOG_TAG, "Dead service " + service.mService + " removed");
+    private boolean tryRemoveServiceLocked(Service service) {
+        final boolean removed = mServices.remove(service);
+        if (!removed) {
+            return false;
         }
+        mComponentNameToServiceMap.remove(service.mComponentName);
         mHandler.removeMessages(service.mId);
-        updateStateOnDisabledService(service);
-        return mServices.remove(service);
+        service.unlinkToOwnDeath();
+        updateInputFilterLocked();
+        return removed;
     }
 
     /**
@@ -534,11 +557,6 @@
             return false;
         }
 
-        if (!service.mService.isBinderAlive()) {
-            removeDeadServiceLocked(service);
-            return false;
-        }
-
         int eventType = event.getEventType();
         if ((service.mEventTypes & eventType) != eventType) {
             return false;
@@ -663,65 +681,36 @@
     }
 
     /**
-     * Sets the input filter state. If the filter is in enabled it is registered
-     * in the window manager, otherwise the filter is removed from the latter.
-     *
-     * @param enabled Whether the input filter is enabled.
+     * Updates the input filter state. The filter is enabled if accessibility
+     * is enabled and there is at least one accessibility service providing
+     * spoken feedback.
      */
-    private void setInputFilterEnabledLocked(boolean enabled) {
+    private void updateInputFilterLocked() {
         WindowManagerService wm = (WindowManagerService)ServiceManager.getService(
                 Context.WINDOW_SERVICE);
-        if (wm != null) {
-            if (enabled) {
+        if (mIsEnabled) {
+            final boolean hasSpokenFeedbackServices = !getEnabledAccessibilityServiceList(
+                    AccessibilityServiceInfo.FEEDBACK_SPOKEN).isEmpty();
+            if (hasSpokenFeedbackServices) {
+                if (mHasInputFilter) {
+                    return;
+                }
                 if (mInputFilter == null) {
                     mInputFilter = new AccessibilityInputFilter(mContext);
                 }
                 wm.setInputFilter(mInputFilter);
+                mHasInputFilter = true;
             } else {
-                wm.setInputFilter(null);
+                if (mHasInputFilter) {
+                    wm.setInputFilter(null);
+                    mHasInputFilter = false;
+                }
             }
-        }
-    }
-
-    /**
-     * Updates the set of enabled services for a given feedback type and
-     * if more than one of them provides spoken feedback enables touch
-     * exploration.
-     *
-     * @param service An enable service.
-     */
-    private void updateStateOnEnabledService(Service service) {
-        int feedbackType = service.mFeedbackType;
-        List<AccessibilityServiceInfo> enabledServices =
-            mFeedbackTypeToEnabledServicesMap.get(feedbackType);
-        if (enabledServices == null) {
-            enabledServices = new ArrayList<AccessibilityServiceInfo>();
-            mFeedbackTypeToEnabledServicesMap.put(feedbackType, enabledServices);
-        }
-        enabledServices.add(service.mAccessibilityServiceInfo);
-
-        // We enable touch exploration if at least one
-        // enabled service provides spoken feedback.
-        if (enabledServices.size() > 0
-                && service.mFeedbackType == AccessibilityServiceInfo.FEEDBACK_SPOKEN) {
-            updateClientsLocked();
-            setInputFilterEnabledLocked(true);
-        }
-    }
-
-    private void updateStateOnDisabledService(Service service) {
-        List<AccessibilityServiceInfo> enabledServices =
-            mFeedbackTypeToEnabledServicesMap.get(service.mFeedbackType);
-        if (enabledServices == null) {
-            return;
-        }
-        enabledServices.remove(service.mAccessibilityServiceInfo);
-        // We disable touch exploration if no
-        // enabled service provides spoken feedback.
-        if (enabledServices.isEmpty()
-                && service.mFeedbackType == AccessibilityServiceInfo.FEEDBACK_SPOKEN) {
-            updateClientsLocked();
-            setInputFilterEnabledLocked(false);
+        } else {
+            if (mHasInputFilter) {
+                wm.setInputFilter(null);
+                mHasInputFilter = false;
+            }
         }
     }
 
@@ -733,7 +722,8 @@
      * passed to the service it represents as soon it is bound. It also serves as the
      * connection for the service.
      */
-    class Service extends IAccessibilityServiceConnection.Stub implements ServiceConnection {
+    class Service extends IAccessibilityServiceConnection.Stub
+            implements ServiceConnection, DeathRecipient {
         int mId = 0;
 
         AccessibilityServiceInfo mAccessibilityServiceInfo;
@@ -752,8 +742,6 @@
 
         long mNotificationTimeout;
 
-        boolean mIsActive;
-
         ComponentName mComponentName;
 
         Intent mIntent;
@@ -806,11 +794,9 @@
          */
         public boolean unbind() {
             if (mService != null) {
-                mService = null;
+                tryRemoveServiceLocked(this);
                 mContext.unbindService(this);
-                mComponentNameToServiceMap.remove(mComponentName);
-                mServices.remove(this);
-                updateStateOnDisabledService(this);
+                mService = null;
                 return true;
             }
             return false;
@@ -833,17 +819,10 @@
         public void onServiceConnected(ComponentName componentName, IBinder service) {
             mService = service;
             mServiceInterface = IEventListener.Stub.asInterface(service);
-
             try {
                 mServiceInterface.setConnection(this);
                 synchronized (mLock) {
-                    if (!mServices.contains(this)) {
-                        mServices.add(this);
-                        mComponentNameToServiceMap.put(componentName, this);
-                        if (isConfigured()) {
-                            updateStateOnEnabledService(this);
-                        }
-                    }
+                    tryAddServiceLocked(this);
                 }
             } catch (RemoteException re) {
                 Slog.w(LOG_TAG, "Error while setting Controller for service: " + service, re);
@@ -851,9 +830,20 @@
         }
 
         public void onServiceDisconnected(ComponentName componentName) {
+            /* do nothing - #binderDied takes care */
+        }
+
+        public void linkToOwnDeath() throws RemoteException {
+            mService.linkToDeath(this, 0);
+        }
+
+        public void unlinkToOwnDeath() {
+            mService.unlinkToDeath(this, 0);
+        }
+
+        public void binderDied() {
             synchronized (mLock) {
-                Service service = mComponentNameToServiceMap.remove(componentName);
-                mServices.remove(service);
+                tryRemoveServiceLocked(this);
             }
         }
     }
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index b463e56..82e5e80 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -25,7 +25,6 @@
 import com.android.server.SystemServer;
 import com.android.server.Watchdog;
 import com.android.server.am.ActivityStack.ActivityState;
-import com.android.server.net.NetworkPolicyManagerService;
 import com.android.server.wm.WindowManagerService;
 
 import dalvik.system.Zygote;
@@ -1301,15 +1300,16 @@
                 break;
             }
             case DISPATCH_FOREGROUND_ACTIVITIES_CHANGED: {
-                final ProcessRecord app = (ProcessRecord) msg.obj;
-                final boolean foregroundActivities = msg.arg1 != 0;
-                dispatchForegroundActivitiesChanged(
-                        app.pid, app.info.uid, foregroundActivities);
+                final int pid = msg.arg1;
+                final int uid = msg.arg2;
+                final boolean foregroundActivities = (Boolean) msg.obj;
+                dispatchForegroundActivitiesChanged(pid, uid, foregroundActivities);
                 break;
             }
             case DISPATCH_PROCESS_DIED: {
-                final ProcessRecord app = (ProcessRecord) msg.obj;
-                dispatchProcessDied(app.pid, app.info.uid);
+                final int pid = msg.arg1;
+                final int uid = msg.arg2;
+                dispatchProcessDied(pid, uid);
                 break;
             }
             }
@@ -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();
@@ -9260,7 +9260,7 @@
             }
         }
 
-        mHandler.obtainMessage(DISPATCH_PROCESS_DIED, app).sendToTarget();
+        mHandler.obtainMessage(DISPATCH_PROCESS_DIED, app.pid, app.info.uid, null).sendToTarget();
 
         // If the caller is restarting this app, then leave it in its
         // current lists and let the caller take care of it.
@@ -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));
             }
         }
 
@@ -12821,8 +12819,8 @@
         app.curSchedGroup = schedGroup;
 
         if (hadForegroundActivities != app.foregroundActivities) {
-            mHandler.obtainMessage(DISPATCH_FOREGROUND_ACTIVITIES_CHANGED,
-                    app.foregroundActivities ? 1 : 0, 0, app).sendToTarget();
+            mHandler.obtainMessage(DISPATCH_FOREGROUND_ACTIVITIES_CHANGED, app.pid, app.info.uid,
+                    app.foregroundActivities).sendToTarget();
         }
 
         return adj;
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/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index d083d01..17c7161 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -16,11 +16,15 @@
 
 package com.android.server.net;
 
+import static android.Manifest.permission.DUMP;
 import static android.Manifest.permission.MANAGE_APP_TOKENS;
 import static android.Manifest.permission.UPDATE_DEVICE_STATS;
 import static android.net.NetworkPolicyManager.POLICY_NONE;
-import static android.net.NetworkPolicyManager.POLICY_REJECT_BACKGROUND;
-import static android.net.NetworkPolicyManager.POLICY_REJECT_PAID;
+import static android.net.NetworkPolicyManager.POLICY_REJECT_PAID_BACKGROUND;
+import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
+import static android.net.NetworkPolicyManager.RULE_REJECT_PAID;
+import static android.net.NetworkPolicyManager.dumpPolicy;
+import static android.net.NetworkPolicyManager.dumpRules;
 
 import android.app.IActivityManager;
 import android.app.IProcessObserver;
@@ -28,51 +32,73 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.INetworkPolicyListener;
 import android.net.INetworkPolicyManager;
+import android.net.INetworkStatsService;
 import android.os.IPowerManager;
+import android.os.RemoteCallbackList;
 import android.os.RemoteException;
-import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
 /**
  * Service that maintains low-level network policy rules and collects usage
  * statistics to drive those rules.
+ * <p>
+ * Derives active rules by combining a given policy with other system status,
+ * and delivers to listeners, such as {@link ConnectivityManager}, for
+ * enforcement.
  */
 public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
     private static final String TAG = "NetworkPolicy";
     private static final boolean LOGD = true;
 
-    private Context mContext;
-    private IActivityManager mActivityManager;
-    private IPowerManager mPowerManager;
+    private final Context mContext;
+    private final IActivityManager mActivityManager;
+    private final IPowerManager mPowerManager;
+    private final INetworkStatsService mNetworkStats;
 
-    private Object mRulesLock = new Object();
+    private final Object mRulesLock = new Object();
 
-    private boolean mScreenOn = false;
+    private boolean mScreenOn;
 
     /** Current network policy for each UID. */
     private SparseIntArray mUidPolicy = new SparseIntArray();
+    /** Current derived network rules for each UID. */
+    private SparseIntArray mUidRules = new SparseIntArray();
 
     /** Foreground at both UID and PID granularity. */
     private SparseBooleanArray mUidForeground = new SparseBooleanArray();
     private SparseArray<SparseBooleanArray> mUidPidForeground = new SparseArray<
             SparseBooleanArray>();
 
-    // TODO: periodically poll network stats and write to disk
+    private final RemoteCallbackList<INetworkPolicyListener> mListeners = new RemoteCallbackList<
+            INetworkPolicyListener>();
+
     // TODO: save/restore policy information from disk
 
-    public NetworkPolicyManagerService(
-            Context context, IActivityManager activityManager, IPowerManager powerManager) {
+    // TODO: keep whitelist of system-critical services that should never have
+    // rules enforced, such as system, phone, and radio UIDs.
+
+    // TODO: keep record of billing cycle details, and limit rules
+    // TODO: keep map of interfaces-to-billing-relationship
+
+    public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
+            IPowerManager powerManager, INetworkStatsService networkStats) {
         mContext = checkNotNull(context, "missing context");
         mActivityManager = checkNotNull(activityManager, "missing activityManager");
         mPowerManager = checkNotNull(powerManager, "missing powerManager");
+        mNetworkStats = checkNotNull(networkStats, "missing networkStats");
     }
 
     public void systemReady() {
-        // TODO: read current policy+stats from disk and generate NMS rules
+        // TODO: read current policy from disk
 
         updateScreenOn();
 
@@ -92,18 +118,13 @@
         screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
         mContext.registerReceiver(mScreenReceiver, screenFilter);
 
-        final IntentFilter shutdownFilter = new IntentFilter();
-        shutdownFilter.addAction(Intent.ACTION_SHUTDOWN);
-        mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
-
     }
 
     private IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
         @Override
         public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
             // only someone like AMS should only be calling us
-            mContext.enforceCallingOrSelfPermission(
-                    MANAGE_APP_TOKENS, "requires MANAGE_APP_TOKENS permission");
+            mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG);
 
             synchronized (mRulesLock) {
                 // because a uid can have multiple pids running inside, we need to
@@ -123,8 +144,7 @@
         @Override
         public void onProcessDied(int pid, int uid) {
             // only someone like AMS should only be calling us
-            mContext.enforceCallingOrSelfPermission(
-                    MANAGE_APP_TOKENS, "requires MANAGE_APP_TOKENS permission");
+            mContext.enforceCallingOrSelfPermission(MANAGE_APP_TOKENS, TAG);
 
             synchronized (mRulesLock) {
                 // clear records and recompute, when they exist
@@ -148,22 +168,19 @@
         }
     };
 
-    private BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            // TODO: persist any pending stats during clean shutdown
-            Log.d(TAG, "persisting stats");
-        }
-    };
-
     @Override
     public void setUidPolicy(int uid, int policy) {
-        mContext.enforceCallingOrSelfPermission(
-                UPDATE_DEVICE_STATS, "requires UPDATE_DEVICE_STATS permission");
+        // TODO: create permission for modifying data policy
+        mContext.enforceCallingOrSelfPermission(UPDATE_DEVICE_STATS, TAG);
 
+        final int oldPolicy;
         synchronized (mRulesLock) {
+            oldPolicy = getUidPolicy(uid);
             mUidPolicy.put(uid, policy);
+            updateRulesForUidL(uid);
         }
+
+        // TODO: consider dispatching BACKGROUND_DATA_SETTING broadcast
     }
 
     @Override
@@ -173,6 +190,86 @@
         }
     }
 
+    @Override
+    public void registerListener(INetworkPolicyListener listener) {
+        mListeners.register(listener);
+
+        synchronized (mRulesLock) {
+            // dispatch any existing rules to new listeners
+            final int size = mUidRules.size();
+            for (int i = 0; i < size; i++) {
+                final int uid = mUidRules.keyAt(i);
+                final int uidRules = mUidRules.valueAt(i);
+                if (uidRules != RULE_ALLOW_ALL) {
+                    try {
+                        listener.onRulesChanged(uid, uidRules);
+                    } catch (RemoteException e) {
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public void unregisterListener(INetworkPolicyListener listener) {
+        mListeners.unregister(listener);
+    }
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
+        mContext.enforceCallingOrSelfPermission(DUMP, TAG);
+
+        synchronized (mRulesLock) {
+            fout.println("Policy status for known UIDs:");
+
+            final SparseBooleanArray knownUids = new SparseBooleanArray();
+            collectKeys(mUidPolicy, knownUids);
+            collectKeys(mUidForeground, knownUids);
+            collectKeys(mUidRules, knownUids);
+
+            final int size = knownUids.size();
+            for (int i = 0; i < size; i++) {
+                final int uid = knownUids.keyAt(i);
+                fout.print("  UID=");
+                fout.print(uid);
+
+                fout.print(" policy=");
+                final int policyIndex = mUidPolicy.indexOfKey(uid);
+                if (policyIndex < 0) {
+                    fout.print("UNKNOWN");
+                } else {
+                    dumpPolicy(fout, mUidPolicy.valueAt(policyIndex));
+                }
+
+                fout.print(" foreground=");
+                final int foregroundIndex = mUidPidForeground.indexOfKey(uid);
+                if (foregroundIndex < 0) {
+                    fout.print("UNKNOWN");
+                } else {
+                    dumpSparseBooleanArray(fout, mUidPidForeground.valueAt(foregroundIndex));
+                }
+
+                fout.print(" rules=");
+                final int rulesIndex = mUidRules.indexOfKey(uid);
+                if (rulesIndex < 0) {
+                    fout.print("UNKNOWN");
+                } else {
+                    dumpRules(fout, mUidRules.valueAt(rulesIndex));
+                }
+
+                fout.println();
+            }
+        }
+    }
+
+    @Override
+    public boolean isUidForeground(int uid) {
+        synchronized (mRulesLock) {
+            // only really in foreground when screen is also on
+            return mUidForeground.get(uid, false) && mScreenOn;
+        }
+    }
+
     /**
      * Foreground for PID changed; recompute foreground at UID level. If
      * changed, will trigger {@link #updateRulesForUidL(int)}.
@@ -223,22 +320,33 @@
     }
 
     private void updateRulesForUidL(int uid) {
-        // only really in foreground when screen on
-        final boolean uidForeground = mUidForeground.get(uid, false) && mScreenOn;
         final int uidPolicy = getUidPolicy(uid);
+        final boolean uidForeground = isUidForeground(uid);
 
-        if (LOGD) {
-            Log.d(TAG, "updateRulesForUid(uid=" + uid + ") found foreground=" + uidForeground
-                    + " and policy=" + uidPolicy);
+        // derive active rules based on policy and active state
+        int uidRules = RULE_ALLOW_ALL;
+        if (!uidForeground && (uidPolicy & POLICY_REJECT_PAID_BACKGROUND) != 0) {
+            // uid in background, and policy says to block paid data
+            uidRules = RULE_REJECT_PAID;
         }
 
-        if (!uidForeground && (uidPolicy & POLICY_REJECT_BACKGROUND) != 0) {
-            // TODO: build updated rules and push to NMS
-        } else if ((uidPolicy & POLICY_REJECT_PAID) != 0) {
-            // TODO: build updated rules and push to NMS
-        } else {
-            // TODO: build updated rules and push to NMS
+        // TODO: only dispatch when rules actually change
+
+        // record rule locally to dispatch to new listeners
+        mUidRules.put(uid, uidRules);
+
+        // dispatch changed rule to existing listeners
+        final int length = mListeners.beginBroadcast();
+        for (int i = 0; i < length; i++) {
+            final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
+            if (listener != null) {
+                try {
+                    listener.onRulesChanged(uid, uidRules);
+                } catch (RemoteException e) {
+                }
+            }
         }
+        mListeners.finishBroadcast();
     }
 
     private static <T> T checkNotNull(T value, String message) {
@@ -247,4 +355,28 @@
         }
         return value;
     }
+
+    private static void collectKeys(SparseIntArray source, SparseBooleanArray target) {
+        final int size = source.size();
+        for (int i = 0; i < size; i++) {
+            target.put(source.keyAt(i), true);
+        }
+    }
+
+    private static void collectKeys(SparseBooleanArray source, SparseBooleanArray target) {
+        final int size = source.size();
+        for (int i = 0; i < size; i++) {
+            target.put(source.keyAt(i), true);
+        }
+    }
+
+    private static void dumpSparseBooleanArray(PrintWriter fout, SparseBooleanArray value) {
+        fout.print("[");
+        final int size = value.size();
+        for (int i = 0; i < size; i++) {
+            fout.print(value.keyAt(i) + "=" + value.valueAt(i));
+            if (i < size - 1) fout.print(",");
+        }
+        fout.print("]");
+    }
 }
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
new file mode 100644
index 0000000..d9c1f25
--- /dev/null
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -0,0 +1,403 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.net;
+
+import static android.Manifest.permission.DUMP;
+import static android.Manifest.permission.SHUTDOWN;
+import static android.Manifest.permission.UPDATE_DEVICE_STATS;
+import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.ConnectivityManager.TYPE_WIFI;
+import static android.net.NetworkStats.UID_ALL;
+
+import android.app.AlarmManager;
+import android.app.IAlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.INetworkStatsService;
+import android.net.LinkProperties;
+import android.net.NetworkStats;
+import android.net.NetworkStatsHistory;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.INetworkManagementService;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.telephony.TelephonyManager;
+import android.text.format.DateUtils;
+import android.util.NtpTrustedTime;
+import android.util.Slog;
+import android.util.TrustedTime;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.TelephonyIntents;
+import com.google.android.collect.Maps;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.HashMap;
+
+/**
+ * Collect and persist detailed network statistics, and provide this data to
+ * other system services.
+ */
+public class NetworkStatsService extends INetworkStatsService.Stub {
+    private static final String TAG = "NetworkStatsService";
+    private static final boolean LOGD = true;
+
+    private final Context mContext;
+    private final INetworkManagementService mNetworkManager;
+    private final IAlarmManager mAlarmManager;
+    private final TrustedTime mTime;
+
+    private static final String ACTION_NETWORK_STATS_POLL =
+            "com.android.server.action.NETWORK_STATS_POLL";
+
+    private PendingIntent mPollIntent;
+
+    // TODO: move tweakable params to Settings.Secure
+    // TODO: listen for kernel push events through netd instead of polling
+
+    private static final long KB_IN_BYTES = 1024;
+
+    private static final long POLL_INTERVAL = AlarmManager.INTERVAL_FIFTEEN_MINUTES;
+    private static final long SUMMARY_BUCKET_DURATION = 6 * DateUtils.HOUR_IN_MILLIS;
+    private static final long SUMMARY_MAX_HISTORY = 90 * DateUtils.DAY_IN_MILLIS;
+
+    // TODO: remove these high-frequency testing values
+//    private static final long POLL_INTERVAL = 5 * DateUtils.SECOND_IN_MILLIS;
+//    private static final long SUMMARY_BUCKET_DURATION = 10 * DateUtils.SECOND_IN_MILLIS;
+//    private static final long SUMMARY_MAX_HISTORY = 2 * DateUtils.MINUTE_IN_MILLIS;
+
+    /** Minimum delta required to persist to disk. */
+    private static final long SUMMARY_PERSIST_THRESHOLD = 64 * KB_IN_BYTES;
+
+    private static final long TIME_CACHE_MAX_AGE = DateUtils.DAY_IN_MILLIS;
+
+    private final Object mStatsLock = new Object();
+
+    /** Set of active ifaces during this boot. */
+    private HashMap<String, InterfaceInfo> mActiveIface = Maps.newHashMap();
+    /** Set of historical stats for known ifaces. */
+    private HashMap<InterfaceInfo, NetworkStatsHistory> mIfaceStats = Maps.newHashMap();
+
+    private NetworkStats mLastPollStats;
+    private NetworkStats mLastPersistStats;
+
+    private final HandlerThread mHandlerThread;
+    private final Handler mHandler;
+
+    // TODO: collect detailed uid stats, storing tag-granularity data until next
+    // dropbox, and uid summary for a specific bucket count.
+
+    // TODO: periodically compile statistics and send to dropbox.
+
+    public NetworkStatsService(
+            Context context, INetworkManagementService networkManager, IAlarmManager alarmManager) {
+        // TODO: move to using cached NtpTrustedTime
+        this(context, networkManager, alarmManager, new NtpTrustedTime());
+    }
+
+    public NetworkStatsService(Context context, INetworkManagementService networkManager,
+            IAlarmManager alarmManager, TrustedTime time) {
+        mContext = checkNotNull(context, "missing Context");
+        mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService");
+        mAlarmManager = checkNotNull(alarmManager, "missing IAlarmManager");
+        mTime = checkNotNull(time, "missing TrustedTime");
+
+        mHandlerThread = new HandlerThread(TAG);
+        mHandlerThread.start();
+        mHandler = new Handler(mHandlerThread.getLooper());
+    }
+
+    public void systemReady() {
+        // read historical stats from disk
+        readStatsLocked();
+
+        // watch other system services that claim interfaces
+        // TODO: protect incoming broadcast with permissions check.
+        // TODO: consider migrating this to ConnectivityService, but it might
+        // cause a circular dependency.
+        final IntentFilter interfaceFilter = new IntentFilter();
+        interfaceFilter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
+        interfaceFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+        mContext.registerReceiver(mInterfaceReceiver, interfaceFilter);
+
+        // listen for periodic polling events
+        final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
+        mContext.registerReceiver(mPollReceiver, pollFilter, UPDATE_DEVICE_STATS, mHandler);
+
+        // persist stats during clean shutdown
+        final IntentFilter shutdownFilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
+        mContext.registerReceiver(mShutdownReceiver, shutdownFilter, SHUTDOWN, null);
+
+        try {
+            registerPollAlarmLocked();
+        } catch (RemoteException e) {
+            Slog.w(TAG, "unable to register poll alarm");
+        }
+    }
+
+    /**
+     * Clear any existing {@link #ACTION_NETWORK_STATS_POLL} alarms, and
+     * reschedule based on current {@link #POLL_INTERVAL} value.
+     */
+    private void registerPollAlarmLocked() throws RemoteException {
+        if (mPollIntent != null) {
+            mAlarmManager.remove(mPollIntent);
+        }
+
+        mPollIntent = PendingIntent.getBroadcast(
+                mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0);
+
+        final long currentRealtime = SystemClock.elapsedRealtime();
+        mAlarmManager.setInexactRepeating(
+                AlarmManager.ELAPSED_REALTIME, currentRealtime, POLL_INTERVAL, mPollIntent);
+    }
+
+    @Override
+    public NetworkStatsHistory[] getNetworkStatsSummary(int networkType) {
+        // TODO: return history for requested types
+        return null;
+    }
+
+    @Override
+    public NetworkStatsHistory getNetworkStatsUid(int uid) {
+        // TODO: return history for requested uid
+        return null;
+    }
+
+    /**
+     * Receiver that watches for other system components that claim network
+     * interfaces. Used to associate {@link TelephonyManager#getSubscriberId()}
+     * with mobile interfaces.
+     */
+    private BroadcastReceiver mInterfaceReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            if (TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED.equals(action)) {
+                final LinkProperties prop = intent.getParcelableExtra(
+                        Phone.DATA_LINK_PROPERTIES_KEY);
+                final String iface = prop != null ? prop.getInterfaceName() : null;
+                if (iface != null) {
+                    final TelephonyManager teleManager = (TelephonyManager) context
+                            .getSystemService(Context.TELEPHONY_SERVICE);
+                    final InterfaceInfo info = new InterfaceInfo(
+                            iface, TYPE_MOBILE, teleManager.getSubscriberId());
+                    reportActiveInterface(info);
+                }
+            } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
+                final LinkProperties prop = intent.getParcelableExtra(
+                        WifiManager.EXTRA_LINK_PROPERTIES);
+                final String iface = prop != null ? prop.getInterfaceName() : null;
+                if (iface != null) {
+                    final InterfaceInfo info = new InterfaceInfo(iface, TYPE_WIFI, null);
+                    reportActiveInterface(info);
+                }
+            }
+        }
+    };
+
+    private BroadcastReceiver mPollReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            // already running on background handler, network/io is safe, and
+            // caller verified to have UPDATE_DEVICE_STATS permission above.
+            synchronized (mStatsLock) {
+                // TODO: acquire wakelock while performing poll
+                performPollLocked();
+            }
+        }
+    };
+
+    private BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            // persist stats during clean shutdown
+            synchronized (mStatsLock) {
+                writeStatsLocked();
+            }
+        }
+    };
+
+    private void performPollLocked() {
+        if (LOGD) Slog.v(TAG, "performPollLocked()");
+
+        // try refreshing time source when stale
+        if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
+            mTime.forceRefresh();
+        }
+
+        // TODO: consider marking "untrusted" times in historical stats
+        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
+                : System.currentTimeMillis();
+
+        final NetworkStats current;
+        try {
+            current = mNetworkManager.getNetworkStatsSummary();
+        } catch (RemoteException e) {
+            Slog.w(TAG, "problem reading network stats");
+            return;
+        }
+
+        // update historical usage with delta since last poll
+        final NetworkStats pollDelta = computeStatsDelta(mLastPollStats, current);
+        final long timeStart = currentTime - pollDelta.elapsedRealtime;
+        for (String iface : pollDelta.getKnownIfaces()) {
+            final InterfaceInfo info = mActiveIface.get(iface);
+            if (info == null) {
+                if (LOGD) Slog.w(TAG, "unknown interface " + iface + ", ignoring stats");
+                continue;
+            }
+
+            final int index = pollDelta.findIndex(iface, UID_ALL);
+            final long rx = pollDelta.rx[index];
+            final long tx = pollDelta.tx[index];
+
+            final NetworkStatsHistory history = findOrCreateHistoryLocked(info);
+            history.recordData(timeStart, currentTime, rx, tx);
+            history.removeBucketsBefore(currentTime - SUMMARY_MAX_HISTORY);
+        }
+
+        mLastPollStats = current;
+
+        // decide if enough has changed to trigger persist
+        final NetworkStats persistDelta = computeStatsDelta(mLastPersistStats, current);
+        for (String iface : persistDelta.getKnownIfaces()) {
+            final int index = persistDelta.findIndex(iface, UID_ALL);
+            if (persistDelta.rx[index] > SUMMARY_PERSIST_THRESHOLD
+                    || persistDelta.tx[index] > SUMMARY_PERSIST_THRESHOLD) {
+                writeStatsLocked();
+                mLastPersistStats = current;
+                break;
+            }
+        }
+    }
+
+    private NetworkStatsHistory findOrCreateHistoryLocked(InterfaceInfo info) {
+        NetworkStatsHistory stats = mIfaceStats.get(info);
+        if (stats == null) {
+            stats = new NetworkStatsHistory(
+                    info.networkType, info.identity, UID_ALL, SUMMARY_BUCKET_DURATION);
+            mIfaceStats.put(info, stats);
+        }
+        return stats;
+    }
+
+    private void readStatsLocked() {
+        if (LOGD) Slog.v(TAG, "readStatsLocked()");
+        // TODO: read historical stats from disk using AtomicFile
+    }
+
+    private void writeStatsLocked() {
+        if (LOGD) Slog.v(TAG, "writeStatsLocked()");
+        // TODO: persist historical stats to disk using AtomicFile
+    }
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        mContext.enforceCallingOrSelfPermission(DUMP, TAG);
+
+        pw.println("Active interfaces:");
+        for (InterfaceInfo info : mActiveIface.values()) {
+            info.dump("  ", pw);
+        }
+
+        pw.println("Known historical stats:");
+        for (NetworkStatsHistory stats : mIfaceStats.values()) {
+            stats.dump("  ", pw);
+        }
+    }
+
+    /**
+     * Details for a well-known network interface, including its name, network
+     * type, and billing relationship identity (such as IMSI).
+     */
+    private static class InterfaceInfo {
+        public final String iface;
+        public final int networkType;
+        public final String identity;
+
+        public InterfaceInfo(String iface, int networkType, String identity) {
+            this.iface = iface;
+            this.networkType = networkType;
+            this.identity = identity;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((identity == null) ? 0 : identity.hashCode());
+            result = prime * result + ((iface == null) ? 0 : iface.hashCode());
+            result = prime * result + networkType;
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof InterfaceInfo) {
+                final InterfaceInfo info = (InterfaceInfo) obj;
+                return equal(iface, info.iface) && networkType == info.networkType
+                        && equal(identity, info.identity);
+            }
+            return false;
+        }
+
+        public void dump(String prefix, PrintWriter pw) {
+            pw.print(prefix);
+            pw.print("InterfaceInfo: iface="); pw.print(iface);
+            pw.print(" networkType="); pw.print(networkType);
+            pw.print(" identity="); pw.println(identity);
+        }
+    }
+
+    private void reportActiveInterface(InterfaceInfo info) {
+        synchronized (mStatsLock) {
+            // TODO: when interface redefined, port over historical stats
+            mActiveIface.put(info.iface, info);
+        }
+    }
+
+    /**
+     * Return the delta between two {@link NetworkStats} snapshots, where {@code
+     * before} can be {@code null}.
+     */
+    private static NetworkStats computeStatsDelta(NetworkStats before, NetworkStats current) {
+        if (before != null) {
+            return current.subtract(before, false);
+        } else {
+            return current;
+        }
+    }
+
+    private static boolean equal(Object a, Object b) {
+        return a == b || (a != null && a.equals(b));
+    }
+
+    private static <T> T checkNotNull(T value, String message) {
+        if (value == null) {
+            throw new NullPointerException(message);
+        }
+        return value;
+    }
+
+}
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/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 08fea1b..2aa53ec 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -408,6 +408,8 @@
     int mBaseDisplayHeight = 0;
     int mCurDisplayWidth = 0;
     int mCurDisplayHeight = 0;
+    int mAppDisplayWidth = 0;
+    int mAppDisplayHeight = 0;
     int mRotation = 0;
     int mRequestedRotation = 0;
     int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -1433,8 +1435,8 @@
     int adjustWallpaperWindowsLocked() {
         int changed = 0;
 
-        final int dw = mCurDisplayWidth;
-        final int dh = mCurDisplayHeight;
+        final int dw = mAppDisplayWidth;
+        final int dh = mAppDisplayHeight;
 
         // First find top-most window that has asked to be on top of the
         // wallpaper; all wallpapers go behind it.
@@ -1852,8 +1854,8 @@
     }
 
     boolean updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
-        final int dw = mCurDisplayWidth;
-        final int dh = mCurDisplayHeight;
+        final int dw = mAppDisplayWidth;
+        final int dh = mAppDisplayHeight;
 
         boolean changed = false;
 
@@ -1893,8 +1895,8 @@
 
     void updateWallpaperVisibilityLocked() {
         final boolean visible = isWallpaperVisible(mWallpaperTarget);
-        final int dw = mCurDisplayWidth;
-        final int dh = mCurDisplayHeight;
+        final int dw = mAppDisplayWidth;
+        final int dh = mAppDisplayHeight;
 
         int curTokenIndex = mWallpaperTokens.size();
         while (curTokenIndex > 0) {
@@ -2701,7 +2703,7 @@
             configChanged = updateOrientationFromAppTokensLocked(false);
             performLayoutAndPlaceSurfacesLocked();
             if (displayed && win.mIsWallpaper) {
-                updateWallpaperOffsetLocked(win, mCurDisplayWidth, mCurDisplayHeight, false);
+                updateWallpaperOffsetLocked(win, mAppDisplayWidth, mAppDisplayHeight, false);
             }
             if (win.mAppToken != null) {
                 win.mAppToken.updateReportedVisibilityLocked();
@@ -4783,8 +4785,8 @@
         synchronized(mWindowMap) {
             long ident = Binder.clearCallingIdentity();
 
-            dw = mPolicy.getNonDecorDisplayWidth(mRotation, mCurDisplayWidth);
-            dh = mPolicy.getNonDecorDisplayHeight(mRotation, mCurDisplayHeight);
+            dw = mAppDisplayWidth;
+            dh = mAppDisplayHeight;
 
             int aboveAppLayer = mPolicy.windowTypeToLayerLw(
                     WindowManager.LayoutParams.TYPE_APPLICATION) * TYPE_LAYER_MULTIPLIER
@@ -5559,10 +5561,10 @@
 
         // Override display width and height with what we are computing,
         // to be sure they remain consistent.
-        dm.widthPixels = dm.realWidthPixels = mPolicy.getNonDecorDisplayWidth(
-                mRotation, dw);
-        dm.heightPixels = dm.realHeightPixels = mPolicy.getNonDecorDisplayHeight(
-                mRotation, dh);
+        dm.widthPixels = dm.unscaledWidthPixels = mAppDisplayWidth
+                = mPolicy.getNonDecorDisplayWidth(mRotation, dw);
+        dm.heightPixels = dm.unscaledHeightPixels = mAppDisplayHeight
+                = mPolicy.getNonDecorDisplayHeight(mRotation, dh);
 
         mCompatibleScreenScale = CompatibilityInfo.updateCompatibleScreenFrame(
                 dm, mCompatibleScreenFrame, null);
@@ -5990,8 +5992,8 @@
                 mInitialDisplayWidth = mInitialDisplayHeight;
                 mInitialDisplayHeight = tmp;
             }
-            mBaseDisplayWidth = mCurDisplayWidth = mInitialDisplayWidth;
-            mBaseDisplayHeight = mCurDisplayHeight = mInitialDisplayHeight;
+            mBaseDisplayWidth = mCurDisplayWidth = mAppDisplayWidth = mInitialDisplayWidth;
+            mBaseDisplayHeight = mCurDisplayHeight = mAppDisplayHeight = mInitialDisplayHeight;
             mInputManager.setDisplaySize(0, mDisplay.getRawWidth(), mDisplay.getRawHeight());
             mPolicy.setInitialDisplaySize(mInitialDisplayWidth, mInitialDisplayHeight);
         }
@@ -6493,8 +6495,8 @@
 
     public void getDisplaySize(Point size) {
         synchronized(mWindowMap) {
-            size.x = mCurDisplayWidth;
-            size.y = mCurDisplayHeight;
+            size.x = mAppDisplayWidth;
+            size.y = mAppDisplayHeight;
         }
     }
 
@@ -6626,6 +6628,10 @@
         }
     }
 
+    public boolean canStatusBarHide() {
+        return mPolicy.canStatusBarHide();
+    }
+
     // -------------------------------------------------------------
     // Internals
     // -------------------------------------------------------------
@@ -6990,9 +6996,8 @@
         final long currentTime = SystemClock.uptimeMillis();
         final int dw = mCurDisplayWidth;
         final int dh = mCurDisplayHeight;
-
-        final int innerDw = mPolicy.getNonDecorDisplayWidth(mRotation, dw);
-        final int innerDh = mPolicy.getNonDecorDisplayHeight(mRotation, dh);
+        final int innerDw = mAppDisplayWidth;
+        final int innerDh = mAppDisplayHeight;
 
         int i;
 
@@ -8965,6 +8970,8 @@
                         pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
                         pw.print(" cur=");
                         pw.print(mCurDisplayWidth); pw.print("x"); pw.print(mCurDisplayHeight);
+                        pw.print(" app=");
+                        pw.print(mAppDisplayWidth); pw.print("x"); pw.print(mAppDisplayHeight);
                         pw.print(" real="); pw.print(mDisplay.getRealWidth());
                         pw.print("x"); pw.print(mDisplay.getRealHeight());
                         pw.print(" raw="); pw.print(mDisplay.getRawWidth());
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index f8d1426..295d569 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -24,7 +24,9 @@
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.BROADCAST_STICKY" />
     <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
-    
+    <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" />
+    <uses-permission android:name="android.permission.MANAGE_APP_TOKENS" />
+
     <application>
         <uses-library android:name="android.test.runner" />
 
diff --git a/services/tests/servicestests/src/com/android/server/BroadcastInterceptingContext.java b/services/tests/servicestests/src/com/android/server/BroadcastInterceptingContext.java
new file mode 100644
index 0000000..fe88793
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/BroadcastInterceptingContext.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.AbstractFuture;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.Future;
+
+/**
+ * {@link ContextWrapper} that can attach listeners for upcoming
+ * {@link Context#sendBroadcast(Intent)}.
+ */
+public class BroadcastInterceptingContext extends ContextWrapper {
+    private static final String TAG = "WatchingContext";
+
+    private final List<BroadcastInterceptor> mInterceptors = Lists.newArrayList();
+
+    public class BroadcastInterceptor extends AbstractFuture<Intent> {
+        private final BroadcastReceiver mReceiver;
+        private final IntentFilter mFilter;
+
+        public BroadcastInterceptor(BroadcastReceiver receiver, IntentFilter filter) {
+            mReceiver = receiver;
+            mFilter = filter;
+        }
+
+        public boolean dispatchBroadcast(Intent intent) {
+            if (mFilter.match(getContentResolver(), intent, false, TAG) > 0) {
+                if (mReceiver != null) {
+                    final Context context = BroadcastInterceptingContext.this;
+                    mReceiver.onReceive(context, intent);
+                    return false;
+                } else {
+                    set(intent);
+                    return true;
+                }
+            } else {
+                return false;
+            }
+        }
+    }
+
+    public BroadcastInterceptingContext(Context base) {
+        super(base);
+    }
+
+    public Future<Intent> nextBroadcastIntent(String action) {
+        return nextBroadcastIntent(new IntentFilter(action));
+    }
+
+    public Future<Intent> nextBroadcastIntent(IntentFilter filter) {
+        final BroadcastInterceptor interceptor = new BroadcastInterceptor(null, filter);
+        synchronized (mInterceptors) {
+            mInterceptors.add(interceptor);
+        }
+        return interceptor;
+    }
+
+    @Override
+    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
+        synchronized (mInterceptors) {
+            mInterceptors.add(new BroadcastInterceptor(receiver, filter));
+        }
+        return null;
+    }
+
+    @Override
+    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
+            String broadcastPermission, Handler scheduler) {
+        return registerReceiver(receiver, filter);
+    }
+
+    @Override
+    public void unregisterReceiver(BroadcastReceiver receiver) {
+        synchronized (mInterceptors) {
+            final Iterator<BroadcastInterceptor> i = mInterceptors.iterator();
+            while (i.hasNext()) {
+                final BroadcastInterceptor interceptor = i.next();
+                if (receiver.equals(interceptor.mReceiver)) {
+                    i.remove();
+                }
+            }
+        }
+    }
+
+    @Override
+    public void sendBroadcast(Intent intent) {
+        synchronized (mInterceptors) {
+            final Iterator<BroadcastInterceptor> i = mInterceptors.iterator();
+            while (i.hasNext()) {
+                final BroadcastInterceptor interceptor = i.next();
+                if (interceptor.dispatchBroadcast(intent)) {
+                    i.remove();
+                }
+            }
+        }
+    }
+
+    @Override
+    public void sendStickyBroadcast(Intent intent) {
+        sendBroadcast(intent);
+    }
+
+    @Override
+    public void removeStickyBroadcast(Intent intent) {
+        // ignored
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
new file mode 100644
index 0000000..6552cdf
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import static android.net.NetworkPolicyManager.POLICY_NONE;
+import static android.net.NetworkPolicyManager.POLICY_REJECT_PAID_BACKGROUND;
+import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
+import static android.net.NetworkPolicyManager.RULE_REJECT_PAID;
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+
+import android.app.IActivityManager;
+import android.app.IProcessObserver;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.net.ConnectivityManager;
+import android.net.INetworkPolicyListener;
+import android.net.INetworkStatsService;
+import android.os.Binder;
+import android.os.IPowerManager;
+import android.test.AndroidTestCase;
+import android.test.mock.MockPackageManager;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.Suppress;
+
+import com.android.server.net.NetworkPolicyManagerService;
+
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+
+import java.util.concurrent.Future;
+
+/**
+ * Tests for {@link NetworkPolicyManagerService}.
+ */
+@LargeTest
+public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
+    private static final String TAG = "NetworkPolicyManagerServiceTest";
+
+    private BroadcastInterceptingContext mServiceContext;
+
+    private IActivityManager mActivityManager;
+    private IPowerManager mPowerManager;
+    private INetworkStatsService mStatsService;
+    private INetworkPolicyListener mPolicyListener;
+
+    private NetworkPolicyManagerService mService;
+    private IProcessObserver mProcessObserver;
+
+    private Binder mStubBinder = new Binder();
+
+    private static final int UID_A = 800;
+    private static final int UID_B = 801;
+
+    private static final int PID_1 = 400;
+    private static final int PID_2 = 401;
+    private static final int PID_3 = 402;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        // intercept various broadcasts, and pretend that uids have packages
+        mServiceContext = new BroadcastInterceptingContext(getContext()) {
+            @Override
+            public PackageManager getPackageManager() {
+                return new MockPackageManager() {
+                    @Override
+                    public String[] getPackagesForUid(int uid) {
+                        return new String[] { "com.example" };
+                    }
+                };
+            }
+        };
+
+        mActivityManager = createMock(IActivityManager.class);
+        mPowerManager = createMock(IPowerManager.class);
+        mStatsService = createMock(INetworkStatsService.class);
+        mPolicyListener = createMock(INetworkPolicyListener.class);
+
+        mService = new NetworkPolicyManagerService(
+                mServiceContext, mActivityManager, mPowerManager, mStatsService);
+
+        // RemoteCallbackList needs a binder to use as key
+        expect(mPolicyListener.asBinder()).andReturn(mStubBinder).atLeastOnce();
+        replay();
+        mService.registerListener(mPolicyListener);
+        verifyAndReset();
+
+        // catch the registered IProcessObserver during systemReady()
+        final Capture<IProcessObserver> processObserver = new Capture<IProcessObserver>();
+        mActivityManager.registerProcessObserver(capture(processObserver));
+        expectLastCall().atLeastOnce();
+
+        // expect to answer screen status during systemReady()
+        expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
+
+        replay();
+        mService.systemReady();
+        verifyAndReset();
+
+        mProcessObserver = processObserver.getValue();
+
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        mServiceContext = null;
+
+        mActivityManager = null;
+        mPowerManager = null;
+        mStatsService = null;
+        mPolicyListener = null;
+
+        mService = null;
+        mProcessObserver = null;
+
+        super.tearDown();
+    }
+
+    @Suppress
+    public void testPolicyChangeTriggersBroadcast() throws Exception {
+        mService.setUidPolicy(UID_A, POLICY_NONE);
+
+        // change background policy and expect broadcast
+        final Future<Intent> backgroundChanged = mServiceContext.nextBroadcastIntent(
+                ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
+
+        mService.setUidPolicy(UID_A, POLICY_REJECT_PAID_BACKGROUND);
+
+        backgroundChanged.get();
+    }
+
+    public void testPidForegroundCombined() throws Exception {
+        // push all uid into background
+        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
+        mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, false);
+        assertFalse(mService.isUidForeground(UID_A));
+        assertFalse(mService.isUidForeground(UID_B));
+
+        // push one of the shared pids into foreground
+        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
+        assertTrue(mService.isUidForeground(UID_A));
+        assertFalse(mService.isUidForeground(UID_B));
+
+        // and swap another uid into foreground
+        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
+        mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, true);
+        assertFalse(mService.isUidForeground(UID_A));
+        assertTrue(mService.isUidForeground(UID_B));
+
+        // push both pid into foreground
+        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
+        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
+        assertTrue(mService.isUidForeground(UID_A));
+
+        // pull one out, should still be foreground
+        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+        assertTrue(mService.isUidForeground(UID_A));
+
+        // pull final pid out, should now be background
+        mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
+        assertFalse(mService.isUidForeground(UID_A));
+    }
+
+    public void testScreenChangesRules() throws Exception {
+        // push strict policy for foreground uid, verify ALLOW rule
+        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        replay();
+        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
+        mService.setUidPolicy(UID_A, POLICY_REJECT_PAID_BACKGROUND);
+        verifyAndReset();
+
+        // now turn screen off and verify REJECT rule
+        expect(mPowerManager.isScreenOn()).andReturn(false).atLeastOnce();
+        expectRulesChanged(UID_A, RULE_REJECT_PAID);
+        replay();
+        mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_OFF));
+        verifyAndReset();
+
+        // and turn screen back on, verify ALLOW rule restored
+        expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
+        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        replay();
+        mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_ON));
+        verifyAndReset();
+    }
+
+    public void testPolicyNone() throws Exception {
+        // POLICY_NONE should RULE_ALLOW in foreground
+        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        replay();
+        mService.setUidPolicy(UID_A, POLICY_NONE);
+        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
+        verifyAndReset();
+
+        // POLICY_NONE should RULE_ALLOW in background
+        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        replay();
+        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+        verifyAndReset();
+    }
+
+    public void testPolicyReject() throws Exception {
+        // POLICY_REJECT should RULE_ALLOW in background
+        expectRulesChanged(UID_A, RULE_REJECT_PAID);
+        replay();
+        mService.setUidPolicy(UID_A, POLICY_REJECT_PAID_BACKGROUND);
+        verifyAndReset();
+
+        // POLICY_REJECT should RULE_ALLOW in foreground
+        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        replay();
+        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
+        verifyAndReset();
+
+        // POLICY_REJECT should RULE_REJECT in background
+        expectRulesChanged(UID_A, RULE_REJECT_PAID);
+        replay();
+        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+        verifyAndReset();
+    }
+
+    public void testPolicyRejectAddRemove() throws Exception {
+        // POLICY_NONE should have RULE_ALLOW in background
+        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        replay();
+        mService.setUidPolicy(UID_A, POLICY_NONE);
+        mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+        verifyAndReset();
+
+        // adding POLICY_REJECT should cause RULE_REJECT
+        expectRulesChanged(UID_A, RULE_REJECT_PAID);
+        replay();
+        mService.setUidPolicy(UID_A, POLICY_REJECT_PAID_BACKGROUND);
+        verifyAndReset();
+
+        // removing POLICY_REJECT should return us to RULE_ALLOW
+        expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+        replay();
+        mService.setUidPolicy(UID_A, POLICY_NONE);
+        verifyAndReset();
+    }
+
+    private void expectRulesChanged(int uid, int policy) throws Exception {
+        mPolicyListener.onRulesChanged(eq(uid), eq(policy));
+        expectLastCall().atLeastOnce();
+    }
+
+    private void replay() {
+        EasyMock.replay(mActivityManager, mPowerManager, mStatsService, mPolicyListener);
+    }
+
+    private void verifyAndReset() {
+        EasyMock.verify(mActivityManager, mPowerManager, mStatsService, mPolicyListener);
+        EasyMock.reset(mActivityManager, mPowerManager, mStatsService, mPolicyListener);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
index ca33d32..d1ee4f6 100644
--- a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java
@@ -25,14 +25,9 @@
 import static org.easymock.EasyMock.reset;
 import static org.easymock.EasyMock.verify;
 
-import com.google.common.collect.Lists;
-import com.google.common.util.concurrent.AbstractFuture;
-
 import android.content.ContentResolver;
 import android.content.Context;
-import android.content.ContextWrapper;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.net.INetworkManagementEventObserver;
 import android.net.NetworkStats;
 import android.net.ThrottleManager;
@@ -48,8 +43,6 @@
 import android.util.Log;
 import android.util.TrustedTime;
 
-import java.util.Iterator;
-import java.util.List;
 import java.util.concurrent.Future;
 
 /**
@@ -66,7 +59,7 @@
 
     private static final String TEST_IFACE = "test0";
 
-    private WatchingContext mWatchingContext;
+    private BroadcastInterceptingContext mWatchingContext;
     private INetworkManagementService mMockNMService;
     private TrustedTime mMockTime;
 
@@ -76,7 +69,7 @@
     public void setUp() throws Exception {
         super.setUp();
 
-        mWatchingContext = new WatchingContext(getContext());
+        mWatchingContext = new BroadcastInterceptingContext(getContext());
 
         mMockNMService = createMock(INetworkManagementService.class);
         mMockTime = createMock(TrustedTime.class);
@@ -354,69 +347,4 @@
 
         pollAction.get();
     }
-
-
-    /**
-     * {@link ContextWrapper} that can attach listeners for upcoming
-     * {@link Context#sendBroadcast(Intent)}.
-     */
-    private static class WatchingContext extends ContextWrapper {
-        private List<LocalBroadcastReceiver> mReceivers = Lists.newArrayList();
-
-        public class LocalBroadcastReceiver extends AbstractFuture<Intent> {
-            private IntentFilter mFilter;
-
-            public LocalBroadcastReceiver(IntentFilter filter) {
-                mFilter = filter;
-            }
-
-            public boolean dispatchBroadcast(Intent intent) {
-                if (mFilter.match(getContentResolver(), intent, false, TAG) > 0) {
-                    set(intent);
-                    return true;
-                } else {
-                    return false;
-                }
-            }
-        }
-
-        public WatchingContext(Context base) {
-            super(base);
-        }
-
-        public Future<Intent> nextBroadcastIntent(String action) {
-            return nextBroadcastIntent(new IntentFilter(action));
-        }
-
-        public Future<Intent> nextBroadcastIntent(IntentFilter filter) {
-            final LocalBroadcastReceiver receiver = new LocalBroadcastReceiver(filter);
-            synchronized (mReceivers) {
-                mReceivers.add(receiver);
-            }
-            return receiver;
-        }
-
-        @Override
-        public void sendBroadcast(Intent intent) {
-            synchronized (mReceivers) {
-                final Iterator<LocalBroadcastReceiver> i = mReceivers.iterator();
-                while (i.hasNext()) {
-                    final LocalBroadcastReceiver receiver = i.next();
-                    if (receiver.dispatchBroadcast(intent)) {
-                        i.remove();
-                    }
-                }
-            }
-        }
-
-        @Override
-        public void sendStickyBroadcast(Intent intent) {
-            sendBroadcast(intent);
-        }
-
-        @Override
-        public void removeStickyBroadcast(Intent intent) {
-            // ignored
-        }
-    }
 }
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/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/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/AndroidManifest.xml b/tests/BiDiTests/AndroidManifest.xml
index e54194c..ad27a62 100644
--- a/tests/BiDiTests/AndroidManifest.xml
+++ b/tests/BiDiTests/AndroidManifest.xml
@@ -57,6 +57,62 @@
             </intent-filter>
         </activity>
 
+        <activity android:name=".BiDiTestFrameLayoutLtrActivity"
+                  android:windowSoftInputMode="stateAlwaysHidden">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".BiDiTestFrameLayoutRtlActivity"
+                  android:windowSoftInputMode="stateAlwaysHidden">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".BiDiTestRelativeLayoutLtrActivity"
+                  android:windowSoftInputMode="stateAlwaysHidden">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".BiDiTestRelativeLayoutRtlActivity"
+                  android:windowSoftInputMode="stateAlwaysHidden">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".BiDiTestRelativeLayoutLtrActivity2"
+                  android:windowSoftInputMode="stateAlwaysHidden">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".BiDiTestRelativeLayoutRtlActivity2"
+                  android:windowSoftInputMode="stateAlwaysHidden">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".BiDiTestTableLayoutLtrActivity"
+                  android:windowSoftInputMode="stateAlwaysHidden">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".BiDiTestTableLayoutRtlActivity"
+                  android:windowSoftInputMode="stateAlwaysHidden">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
+
     </application>
 
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/tests/BiDiTests/res/layout/frame_layout_ltr.xml b/tests/BiDiTests/res/layout/frame_layout_ltr.xml
new file mode 100644
index 0000000..bd324e3
--- /dev/null
+++ b/tests/BiDiTests/res/layout/frame_layout_ltr.xml
@@ -0,0 +1,88 @@
+<?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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/frame_layout_ltr"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:horizontalDirection="ltr"
+    android:background="#FF000000">
+
+        <FrameLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="right|center_vertical"
+            android:background="#FFFF0000">
+        </FrameLayout>
+
+        <FrameLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="left|center_vertical"
+            android:background="#FF00FF00">
+        </FrameLayout>
+
+        <FrameLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="top|center_horizontal"
+            android:background="#FF0000FF">
+        </FrameLayout>
+
+        <FrameLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="bottom|center_horizontal"
+            android:background="#FF00FFFF">
+        </FrameLayout>
+
+        <FrameLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="top|before"
+            android:background="#FFFFFFFF">
+        </FrameLayout>
+
+        <FrameLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="top|after"
+            android:background="#FFFFFF00">
+        </FrameLayout>
+
+        <FrameLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="bottom|before"
+            android:background="#FFFFFFFF">
+        </FrameLayout>
+
+        <FrameLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="bottom|after"
+            android:background="#FFFFFF00">
+        </FrameLayout>
+
+        <FrameLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="center_horizontal|center_vertical"
+            android:background="#FF888888">
+        </FrameLayout>
+
+</FrameLayout>
+
diff --git a/tests/BiDiTests/res/layout/frame_layout_rtl.xml b/tests/BiDiTests/res/layout/frame_layout_rtl.xml
new file mode 100644
index 0000000..814f5e1
--- /dev/null
+++ b/tests/BiDiTests/res/layout/frame_layout_rtl.xml
@@ -0,0 +1,88 @@
+<?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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/frame_layout_ltr"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:horizontalDirection="rtl"
+    android:background="#FF000000">
+
+        <FrameLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="right|center_vertical"
+            android:background="#FFFF0000">
+        </FrameLayout>
+
+        <FrameLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="left|center_vertical"
+            android:background="#FF00FF00">
+        </FrameLayout>
+
+        <FrameLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="top|center_horizontal"
+            android:background="#FF0000FF">
+        </FrameLayout>
+
+        <FrameLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="bottom|center_horizontal"
+            android:background="#FF00FFFF">
+        </FrameLayout>
+
+        <FrameLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="top|before"
+            android:background="#FFFFFFFF">
+        </FrameLayout>
+
+        <FrameLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="top|after"
+            android:background="#FFFFFF00">
+        </FrameLayout>
+
+        <FrameLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="bottom|before"
+            android:background="#FFFFFFFF">
+        </FrameLayout>
+
+        <FrameLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="bottom|after"
+            android:background="#FFFFFF00">
+        </FrameLayout>
+
+        <FrameLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="center_horizontal|center_vertical"
+            android:background="#FF888888">
+        </FrameLayout>
+
+</FrameLayout>
+
diff --git a/tests/BiDiTests/res/layout/linear_layout_ltr.xml b/tests/BiDiTests/res/layout/linear_layout_ltr.xml
index a95fb0e..c5a8d47 100644
--- a/tests/BiDiTests/res/layout/linear_layout_ltr.xml
+++ b/tests/BiDiTests/res/layout/linear_layout_ltr.xml
@@ -15,7 +15,7 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/layouttest"
+    android:id="@+id/linear_layout_ltr"
     android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
@@ -24,26 +24,52 @@
     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:orientation="horizontal"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:horizontalDirection="inherit">
+        android:layout_height="wrap_content">
 
        <Button android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:text="@string/button1_text"
-               android:textSize="32dip"
+               android:textSize="24dip"
         />
 
         <TextView android:id="@+id/textview"
                   android:layout_height="wrap_content"
                   android:layout_width="wrap_content"
-                  android:textSize="32dip"
+                  android:textSize="24dip"
                   android:text="@string/textview_text"
         />
 
         <Button android:layout_height="wrap_content"
                 android:layout_width="wrap_content"
                 android:text="@string/button2_text"
-                android:textSize="32dip"
+                android:textSize="24dip"
+         />
+
+    </LinearLayout>
+
+    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:horizontalDirection="inherit">
+
+       <Button android:layout_height="wrap_content"
+               android:layout_width="wrap_content"
+               android:text="@string/button1_text"
+               android:textSize="24dip"
+        />
+
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_text"
+        />
+
+        <Button android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:text="@string/button2_text"
+                android:textSize="24dip"
          />
 
     </LinearLayout>
@@ -57,20 +83,20 @@
        <Button android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:text="@string/button1_text"
-               android:textSize="32dip"
+               android:textSize="24dip"
         />
 
         <TextView android:id="@+id/textview"
                   android:layout_height="wrap_content"
                   android:layout_width="wrap_content"
-                  android:textSize="32dip"
+                  android:textSize="24dip"
                   android:text="@string/textview_text"
         />
 
         <Button android:layout_height="wrap_content"
                 android:layout_width="wrap_content"
                 android:text="@string/button2_text"
-                android:textSize="32dip"
+                android:textSize="24dip"
          />
 
     </LinearLayout>
@@ -84,20 +110,20 @@
        <Button android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:text="@string/button1_text"
-               android:textSize="32dip"
+               android:textSize="24dip"
         />
 
         <TextView android:id="@+id/textview"
                   android:layout_height="wrap_content"
                   android:layout_width="wrap_content"
-                  android:textSize="32dip"
+                  android:textSize="24dip"
                   android:text="@string/textview_text"
         />
 
         <Button android:layout_height="wrap_content"
                 android:layout_width="wrap_content"
                 android:text="@string/button2_text"
-                android:textSize="32dip"
+                android:textSize="24dip"
          />
 
     </LinearLayout>
@@ -111,20 +137,20 @@
        <Button android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:text="@string/button1_text"
-               android:textSize="32dip"
+               android:textSize="24dip"
         />
 
         <TextView android:id="@+id/textview"
                   android:layout_height="wrap_content"
                   android:layout_width="wrap_content"
-                  android:textSize="32dip"
+                  android:textSize="24dip"
                   android:text="@string/textview_text"
         />
 
         <Button android:layout_height="wrap_content"
                 android:layout_width="wrap_content"
                 android:text="@string/button2_text"
-                android:textSize="32dip"
+                android:textSize="24dip"
          />
 
     </LinearLayout>
@@ -138,20 +164,20 @@
        <Button android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:text="@string/button1_text"
-               android:textSize="32dip"
+               android:textSize="24dip"
         />
 
         <TextView android:id="@+id/textview"
                   android:layout_height="wrap_content"
                   android:layout_width="wrap_content"
-                  android:textSize="32dip"
+                  android:textSize="24dip"
                   android:text="@string/textview_text"
         />
 
         <Button android:layout_height="wrap_content"
                 android:layout_width="wrap_content"
                 android:text="@string/button2_text"
-                android:textSize="32dip"
+                android:textSize="24dip"
          />
 
     </LinearLayout>
@@ -165,20 +191,20 @@
        <Button android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:text="@string/button1_text"
-               android:textSize="32dip"
+               android:textSize="24dip"
         />
 
         <TextView android:id="@+id/textview"
                   android:layout_height="wrap_content"
                   android:layout_width="wrap_content"
-                  android:textSize="32dip"
+                  android:textSize="24dip"
                   android:text="@string/textview_text"
         />
 
         <Button android:layout_height="wrap_content"
                 android:layout_width="wrap_content"
                 android:text="@string/button2_text"
-                android:textSize="32dip"
+                android:textSize="24dip"
          />
 
     </LinearLayout>
diff --git a/tests/BiDiTests/res/layout/linear_layout_rtl.xml b/tests/BiDiTests/res/layout/linear_layout_rtl.xml
index 0d60950..1494fec 100644
--- a/tests/BiDiTests/res/layout/linear_layout_rtl.xml
+++ b/tests/BiDiTests/res/layout/linear_layout_rtl.xml
@@ -15,7 +15,7 @@
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/layouttest"
+    android:id="@+id/linear_layout_rtl"
     android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
@@ -24,26 +24,52 @@
     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:orientation="horizontal"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:horizontalDirection="inherit">
+        android:layout_height="wrap_content">
 
        <Button android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:text="@string/button1_text"
-               android:textSize="32dip"
+               android:textSize="24dip"
         />
 
         <TextView android:id="@+id/textview"
                   android:layout_height="wrap_content"
                   android:layout_width="wrap_content"
-                  android:textSize="32dip"
+                  android:textSize="24dip"
                   android:text="@string/textview_text"
         />
 
         <Button android:layout_height="wrap_content"
                 android:layout_width="wrap_content"
                 android:text="@string/button2_text"
-                android:textSize="32dip"
+                android:textSize="24dip"
+         />
+
+    </LinearLayout>
+
+    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:horizontalDirection="inherit">
+
+       <Button android:layout_height="wrap_content"
+               android:layout_width="wrap_content"
+               android:text="@string/button1_text"
+               android:textSize="24dip"
+        />
+
+        <TextView android:id="@+id/textview"
+                  android:layout_height="wrap_content"
+                  android:layout_width="wrap_content"
+                  android:textSize="24dip"
+                  android:text="@string/textview_text"
+        />
+
+        <Button android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:text="@string/button2_text"
+                android:textSize="24dip"
          />
 
     </LinearLayout>
@@ -57,20 +83,20 @@
        <Button android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:text="@string/button1_text"
-               android:textSize="32dip"
+               android:textSize="24dip"
         />
 
         <TextView android:id="@+id/textview"
                   android:layout_height="wrap_content"
                   android:layout_width="wrap_content"
-                  android:textSize="32dip"
+                  android:textSize="24dip"
                   android:text="@string/textview_text"
         />
 
         <Button android:layout_height="wrap_content"
                 android:layout_width="wrap_content"
                 android:text="@string/button2_text"
-                android:textSize="32dip"
+                android:textSize="24dip"
          />
 
     </LinearLayout>
@@ -84,20 +110,20 @@
        <Button android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:text="@string/button1_text"
-               android:textSize="32dip"
+               android:textSize="24dip"
         />
 
         <TextView android:id="@+id/textview"
                   android:layout_height="wrap_content"
                   android:layout_width="wrap_content"
-                  android:textSize="32dip"
+                  android:textSize="24dip"
                   android:text="@string/textview_text"
         />
 
         <Button android:layout_height="wrap_content"
                 android:layout_width="wrap_content"
                 android:text="@string/button2_text"
-                android:textSize="32dip"
+                android:textSize="24dip"
          />
 
     </LinearLayout>
@@ -111,20 +137,20 @@
        <Button android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:text="@string/button1_text"
-               android:textSize="32dip"
+               android:textSize="24dip"
         />
 
         <TextView android:id="@+id/textview"
                   android:layout_height="wrap_content"
                   android:layout_width="wrap_content"
-                  android:textSize="32dip"
+                  android:textSize="24dip"
                   android:text="@string/textview_text"
         />
 
         <Button android:layout_height="wrap_content"
                 android:layout_width="wrap_content"
                 android:text="@string/button2_text"
-                android:textSize="32dip"
+                android:textSize="24dip"
          />
 
     </LinearLayout>
@@ -138,20 +164,20 @@
        <Button android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:text="@string/button1_text"
-               android:textSize="32dip"
+               android:textSize="24dip"
         />
 
         <TextView android:id="@+id/textview"
                   android:layout_height="wrap_content"
                   android:layout_width="wrap_content"
-                  android:textSize="32dip"
+                  android:textSize="24dip"
                   android:text="@string/textview_text"
         />
 
         <Button android:layout_height="wrap_content"
                 android:layout_width="wrap_content"
                 android:text="@string/button2_text"
-                android:textSize="32dip"
+                android:textSize="24dip"
          />
 
     </LinearLayout>
@@ -165,20 +191,20 @@
        <Button android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:text="@string/button1_text"
-               android:textSize="32dip"
+               android:textSize="24dip"
         />
 
         <TextView android:id="@+id/textview"
                   android:layout_height="wrap_content"
                   android:layout_width="wrap_content"
-                  android:textSize="32dip"
+                  android:textSize="24dip"
                   android:text="@string/textview_text"
         />
 
         <Button android:layout_height="wrap_content"
                 android:layout_width="wrap_content"
                 android:text="@string/button2_text"
-                android:textSize="32dip"
+                android:textSize="24dip"
          />
 
     </LinearLayout>
diff --git a/tests/BiDiTests/res/layout/relative_layout_ltr.xml b/tests/BiDiTests/res/layout/relative_layout_ltr.xml
new file mode 100644
index 0000000..53ae7c3
--- /dev/null
+++ b/tests/BiDiTests/res/layout/relative_layout_ltr.xml
@@ -0,0 +1,88 @@
+<?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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/frame_layout_ltr"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:horizontalDirection="ltr"
+    android:background="#FF000000">
+
+        <RelativeLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="right|center_vertical"
+            android:background="#FFFF0000">
+        </RelativeLayout>
+
+        <RelativeLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="left|center_vertical"
+            android:background="#FF00FF00">
+        </RelativeLayout>
+
+        <RelativeLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="top|center_horizontal"
+            android:background="#FF0000FF">
+        </RelativeLayout>
+
+        <RelativeLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="bottom|center_horizontal"
+            android:background="#FF00FFFF">
+        </RelativeLayout>
+
+        <RelativeLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="top|before"
+            android:background="#FFFFFFFF">
+        </RelativeLayout>
+
+        <RelativeLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="top|after"
+            android:background="#FFFFFF00">
+        </RelativeLayout>
+
+        <RelativeLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="bottom|before"
+            android:background="#FFFFFFFF">
+        </RelativeLayout>
+
+        <RelativeLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="bottom|after"
+            android:background="#FFFFFF00">
+        </RelativeLayout>
+
+        <RelativeLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="center_horizontal|center_vertical"
+            android:background="#FF888888">
+        </RelativeLayout>
+
+</FrameLayout>
+
diff --git a/tests/BiDiTests/res/layout/relative_layout_ltr_2.xml b/tests/BiDiTests/res/layout/relative_layout_ltr_2.xml
new file mode 100644
index 0000000..93d1b4b
--- /dev/null
+++ b/tests/BiDiTests/res/layout/relative_layout_ltr_2.xml
@@ -0,0 +1,155 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/relative_layout_ltr"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:horizontalDirection="ltr">
+
+    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:background="#FF000000"
+            android:padding="10px">
+
+        <TextView android:id="@+id/label_1"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:text="Type here:" />
+
+        <EditText android:id="@+id/entry_1"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/label_1" />
+
+        <Button android:id="@+id/ok_1"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/entry_1"
+                android:layout_alignParentRight="true"
+                android:layout_marginLeft="10px"
+                android:text="OK" />
+
+        <Button android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toLeftOf="@id/ok_1"
+                android:layout_alignTop="@id/ok_1"
+                android:text="Cancel" />
+
+    </RelativeLayout>
+
+    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:background="#FF000000"
+            android:padding="10px"
+            android:horizontalDirection="ltr">
+
+        <TextView android:id="@+id/label_2"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:text="Type here:" />
+
+        <EditText android:id="@+id/entry_2"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/label_2" />
+
+        <Button android:id="@+id/ok_2"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/entry_2"
+                android:layout_alignParentRight="true"
+                android:layout_marginLeft="10px"
+                android:text="OK" />
+
+        <Button android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toLeftOf="@id/ok_2"
+                android:layout_alignTop="@id/ok_2"
+                android:text="Cancel" />
+
+    </RelativeLayout>
+
+    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:background="#FF000000"
+            android:padding="10px"
+            android:horizontalDirection="inherit">
+
+        <TextView android:id="@+id/label_3"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:text="Type here:" />
+
+        <EditText android:id="@+id/entry_3"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/label_3" />
+
+        <Button android:id="@+id/ok_3"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/entry_3"
+                android:layout_alignParentRight="true"
+                android:layout_marginLeft="10px"
+                android:text="OK" />
+
+        <Button android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toLeftOf="@id/ok_3"
+                android:layout_alignTop="@id/ok_3"
+                android:text="Cancel" />
+
+    </RelativeLayout>
+
+    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:background="#FF000000"
+            android:padding="10px"
+            android:horizontalDirection="rtl">
+
+        <TextView android:id="@+id/label_4"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:text="Type here:" />
+
+        <EditText android:id="@+id/entry_4"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/label_4" />
+
+        <Button android:id="@+id/ok_4"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/entry_4"
+                android:layout_alignParentRight="true"
+                android:layout_marginLeft="10px"
+                android:text="OK" />
+
+        <Button android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toLeftOf="@id/ok_4"
+                android:layout_alignTop="@id/ok_4"
+                android:text="Cancel" />
+
+    </RelativeLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/BiDiTests/res/layout/relative_layout_rtl.xml b/tests/BiDiTests/res/layout/relative_layout_rtl.xml
new file mode 100644
index 0000000..4b87752
--- /dev/null
+++ b/tests/BiDiTests/res/layout/relative_layout_rtl.xml
@@ -0,0 +1,88 @@
+<?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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/frame_layout_rtl"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:horizontalDirection="rtl"
+    android:background="#FF000000">
+
+        <RelativeLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="right|center_vertical"
+            android:background="#FFFF0000">
+        </RelativeLayout>
+
+        <RelativeLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="left|center_vertical"
+            android:background="#FF00FF00">
+        </RelativeLayout>
+
+        <RelativeLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="top|center_horizontal"
+            android:background="#FF0000FF">
+        </RelativeLayout>
+
+        <RelativeLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="bottom|center_horizontal"
+            android:background="#FF00FFFF">
+        </RelativeLayout>
+
+        <RelativeLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="top|before"
+            android:background="#FFFFFFFF">
+        </RelativeLayout>
+
+        <RelativeLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="top|after"
+            android:background="#FFFFFF00">
+        </RelativeLayout>
+
+        <RelativeLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="bottom|before"
+            android:background="#FFFFFFFF">
+        </RelativeLayout>
+
+        <RelativeLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="bottom|after"
+            android:background="#FFFFFF00">
+        </RelativeLayout>
+
+        <RelativeLayout
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:layout_gravity="center_horizontal|center_vertical"
+            android:background="#FF888888">
+        </RelativeLayout>
+
+</FrameLayout>
+
diff --git a/tests/BiDiTests/res/layout/relative_layout_rtl_2.xml b/tests/BiDiTests/res/layout/relative_layout_rtl_2.xml
new file mode 100644
index 0000000..8418e72
--- /dev/null
+++ b/tests/BiDiTests/res/layout/relative_layout_rtl_2.xml
@@ -0,0 +1,155 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/relative_layout_ltr"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:horizontalDirection="rtl">
+
+    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:background="#FF000000"
+            android:padding="10px">
+
+        <TextView android:id="@+id/label_1"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:text="Type here:" />
+
+        <EditText android:id="@+id/entry_1"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/label_1" />
+
+        <Button android:id="@+id/ok_1"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/entry_1"
+                android:layout_alignParentRight="true"
+                android:layout_marginLeft="10px"
+                android:text="OK" />
+
+        <Button android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toLeftOf="@id/ok_1"
+                android:layout_alignTop="@id/ok_1"
+                android:text="Cancel" />
+
+    </RelativeLayout>
+
+    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:background="#FF000000"
+            android:padding="10px"
+            android:horizontalDirection="ltr">
+
+        <TextView android:id="@+id/label_2"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:text="Type here:" />
+
+        <EditText android:id="@+id/entry_2"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/label_2" />
+
+        <Button android:id="@+id/ok_2"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/entry_2"
+                android:layout_alignParentRight="true"
+                android:layout_marginLeft="10px"
+                android:text="OK" />
+
+        <Button android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toLeftOf="@id/ok_2"
+                android:layout_alignTop="@id/ok_2"
+                android:text="Cancel" />
+
+    </RelativeLayout>
+
+    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:background="#FF000000"
+            android:padding="10px"
+            android:horizontalDirection="inherit">
+
+        <TextView android:id="@+id/label_3"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:text="Type here:" />
+
+        <EditText android:id="@+id/entry_3"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/label_3" />
+
+        <Button android:id="@+id/ok_3"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/entry_3"
+                android:layout_alignParentRight="true"
+                android:layout_marginLeft="10px"
+                android:text="OK" />
+
+        <Button android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toLeftOf="@id/ok_3"
+                android:layout_alignTop="@id/ok_3"
+                android:text="Cancel" />
+
+    </RelativeLayout>
+
+    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:background="#FF000000"
+            android:padding="10px"
+            android:horizontalDirection="rtl">
+
+        <TextView android:id="@+id/label_4"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:text="Type here:" />
+
+        <EditText android:id="@+id/entry_4"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/label_4" />
+
+        <Button android:id="@+id/ok_4"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/entry_4"
+                android:layout_alignParentRight="true"
+                android:layout_marginLeft="10px"
+                android:text="OK" />
+
+        <Button android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toLeftOf="@id/ok_4"
+                android:layout_alignTop="@id/ok_4"
+                android:text="Cancel" />
+
+    </RelativeLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/BiDiTests/res/layout/table_layout_ltr.xml b/tests/BiDiTests/res/layout/table_layout_ltr.xml
new file mode 100644
index 0000000..f44de8e
--- /dev/null
+++ b/tests/BiDiTests/res/layout/table_layout_ltr.xml
@@ -0,0 +1,215 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/linear_layout_ltr"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:horizontalDirection="ltr">
+
+    <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:stretchColumns="1,2">
+
+        <TableRow>
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:text="@string/button1_text"
+                    android:textSize="24dip"
+             />
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    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/button_after_text"
+                    android:textSize="24dip"
+                    android:gravity="after"
+             />
+        </TableRow>
+
+        <TableRow>
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:text="@string/button2_text"
+                    android:textSize="24dip"
+             />
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    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/button_before_text"
+                    android:textSize="24dip"
+                    android:gravity="before"
+             />
+        </TableRow>
+
+    </TableLayout>
+
+    <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:stretchColumns="1,2"
+        android:horizontalDirection="inherit">
+
+        <TableRow>
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:text="@string/button1_text"
+                    android:textSize="24dip"
+             />
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    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/button_after_text"
+                    android:textSize="24dip"
+                    android:gravity="after"
+             />
+        </TableRow>
+
+        <TableRow>
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:text="@string/button2_text"
+                    android:textSize="24dip"
+             />
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    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/button_before_text"
+                    android:textSize="24dip"
+                    android:gravity="before"
+             />
+        </TableRow>
+
+    </TableLayout>
+
+    <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:stretchColumns="1,2"
+        android:horizontalDirection="ltr">
+
+        <TableRow>
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:text="@string/button1_text"
+                    android:textSize="24dip"
+             />
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    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/button_after_text"
+                    android:textSize="24dip"
+                    android:gravity="after"
+             />
+        </TableRow>
+
+        <TableRow>
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:text="@string/button2_text"
+                    android:textSize="24dip"
+             />
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    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/button_before_text"
+                    android:textSize="24dip"
+                    android:gravity="before"
+             />
+        </TableRow>
+
+    </TableLayout>
+
+    <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:stretchColumns="1,2"
+        android:horizontalDirection="rtl">
+
+        <TableRow>
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:text="@string/button1_text"
+                    android:textSize="24dip"
+             />
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    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/button_after_text"
+                    android:textSize="24dip"
+                    android:gravity="after"
+             />
+        </TableRow>
+
+        <TableRow>
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:text="@string/button2_text"
+                    android:textSize="24dip"
+             />
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    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/button_before_text"
+                    android:textSize="24dip"
+                    android:gravity="before"
+             />
+        </TableRow>
+
+    </TableLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/BiDiTests/res/layout/table_layout_rtl.xml b/tests/BiDiTests/res/layout/table_layout_rtl.xml
new file mode 100644
index 0000000..84270ba
--- /dev/null
+++ b/tests/BiDiTests/res/layout/table_layout_rtl.xml
@@ -0,0 +1,215 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/linear_layout_ltr"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:horizontalDirection="rtl">
+
+    <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:stretchColumns="1,2">
+
+        <TableRow>
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:text="@string/button1_text"
+                    android:textSize="24dip"
+             />
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    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/button_after_text"
+                    android:textSize="24dip"
+                    android:gravity="after"
+             />
+        </TableRow>
+
+        <TableRow>
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:text="@string/button2_text"
+                    android:textSize="24dip"
+             />
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    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/button_before_text"
+                    android:textSize="24dip"
+                    android:gravity="before"
+             />
+        </TableRow>
+
+    </TableLayout>
+
+    <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:stretchColumns="1,2"
+        android:horizontalDirection="inherit">
+
+        <TableRow>
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:text="@string/button1_text"
+                    android:textSize="24dip"
+             />
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    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/button_after_text"
+                    android:textSize="24dip"
+                    android:gravity="after"
+             />
+        </TableRow>
+
+        <TableRow>
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:text="@string/button2_text"
+                    android:textSize="24dip"
+             />
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    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/button_before_text"
+                    android:textSize="24dip"
+                    android:gravity="before"
+             />
+        </TableRow>
+
+    </TableLayout>
+
+    <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:stretchColumns="1,2"
+        android:horizontalDirection="ltr">
+
+        <TableRow>
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:text="@string/button1_text"
+                    android:textSize="24dip"
+             />
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    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/button_after_text"
+                    android:textSize="24dip"
+                    android:gravity="after"
+             />
+        </TableRow>
+
+        <TableRow>
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:text="@string/button2_text"
+                    android:textSize="24dip"
+             />
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    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/button_before_text"
+                    android:textSize="24dip"
+                    android:gravity="before"
+             />
+        </TableRow>
+
+    </TableLayout>
+
+    <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:stretchColumns="1,2"
+        android:horizontalDirection="rtl">
+
+        <TableRow>
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:text="@string/button1_text"
+                    android:textSize="24dip"
+             />
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    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/button_after_text"
+                    android:textSize="24dip"
+                    android:gravity="after"
+             />
+        </TableRow>
+
+        <TableRow>
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    android:text="@string/button2_text"
+                    android:textSize="24dip"
+             />
+            <Button android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"
+                    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/button_before_text"
+                    android:textSize="24dip"
+                    android:gravity="before"
+             />
+        </TableRow>
+
+    </TableLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/BiDiTests/res/values/strings.xml b/tests/BiDiTests/res/values/strings.xml
index 3795d4b..2aeb9e1 100644
--- a/tests/BiDiTests/res/values/strings.xml
+++ b/tests/BiDiTests/res/values/strings.xml
@@ -16,6 +16,12 @@
     <string name="button_text">Button</string>
     <string name="button1_text">Button1</string>
     <string name="button2_text">Button2</string>
+    <string name="button3_text">Button3</string>
+    <string name="button4_text">Button4</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/BiDiTests/src/com/android/bidi/BiDiTestActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
index 0d9b4f7..2662683 100644
--- a/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestActivity.java
@@ -37,20 +37,64 @@
         intent = new Intent().setClass(this, BiDiTestBasicActivity.class);
 
         // Initialize a TabSpec for each tab and add it to the TabHost
-        spec = tabHost.newTabSpec("basic").setIndicator("Basic").setContent(intent);
+        spec = tabHost.newTabSpec("basic").setIndicator("Basic").
+            setContent(intent);
         tabHost.addTab(spec);
 
         // Do the same for the other tabs
         intent = new Intent().setClass(this, BiDiTestCanvasActivity.class);
-        spec = tabHost.newTabSpec("canvas").setIndicator("Canvas").setContent(intent);
+        spec = tabHost.newTabSpec("canvas").setIndicator("Canvas").
+            setContent(intent);
         tabHost.addTab(spec);
 
         intent = new Intent().setClass(this, BiDiTestLinearLayoutLtrActivity.class);
-        spec = tabHost.newTabSpec("layout-ltr").setIndicator("LinearLayout LTR").setContent(intent);
+        spec = tabHost.newTabSpec("linear-layout-ltr").setIndicator("Linear LTR").
+            setContent(intent);
         tabHost.addTab(spec);
 
         intent = new Intent().setClass(this, BiDiTestLinearLayoutRtlActivity.class);
-        spec = tabHost.newTabSpec("layout-rtl").setIndicator("LinearLayout RTL").setContent(intent);
+        spec = tabHost.newTabSpec("linear-layout-rtl").setIndicator("Linear RTL").
+            setContent(intent);
+        tabHost.addTab(spec);
+
+        intent = new Intent().setClass(this, BiDiTestFrameLayoutLtrActivity.class);
+        spec = tabHost.newTabSpec("frame-layout-ltr").setIndicator("Frame LTR").
+            setContent(intent);
+        tabHost.addTab(spec);
+
+        intent = new Intent().setClass(this, BiDiTestFrameLayoutRtlActivity.class);
+        spec = tabHost.newTabSpec("frame-layout-rtl").setIndicator("Frame RTL").
+            setContent(intent);
+        tabHost.addTab(spec);
+
+        intent = new Intent().setClass(this, BiDiTestRelativeLayoutLtrActivity.class);
+        spec = tabHost.newTabSpec("relative-layout-ltr").setIndicator("Relative LTR").
+            setContent(intent);
+        tabHost.addTab(spec);
+
+        intent = new Intent().setClass(this, BiDiTestRelativeLayoutRtlActivity.class);
+        spec = tabHost.newTabSpec("relative-layout-rtl").setIndicator("Relative RTL").
+            setContent(intent);
+        tabHost.addTab(spec);
+
+        intent = new Intent().setClass(this, BiDiTestRelativeLayoutLtrActivity2.class);
+        spec = tabHost.newTabSpec("relative-layout-ltr-2").setIndicator("Relative2 LTR").
+            setContent(intent);
+        tabHost.addTab(spec);
+
+        intent = new Intent().setClass(this, BiDiTestRelativeLayoutRtlActivity2.class);
+        spec = tabHost.newTabSpec("relative-layout-rtl-2").setIndicator("Relative2 RTL").
+            setContent(intent);
+        tabHost.addTab(spec);
+
+        intent = new Intent().setClass(this, BiDiTestTableLayoutLtrActivity.class);
+        spec = tabHost.newTabSpec("table-layout-ltr").setIndicator("Table LTR").
+            setContent(intent);
+        tabHost.addTab(spec);
+
+        intent = new Intent().setClass(this, BiDiTestTableLayoutRtlActivity.class);
+        spec = tabHost.newTabSpec("table-layout-rtl").setIndicator("Table RTL").
+            setContent(intent);
         tabHost.addTab(spec);
 
         tabHost.setCurrentTab(0);
diff --git a/test-runner/tests/src/android/test/StubTestBrowserActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestFrameLayoutLtrActivity.java
similarity index 60%
copy from test-runner/tests/src/android/test/StubTestBrowserActivity.java
copy to tests/BiDiTests/src/com/android/bidi/BiDiTestFrameLayoutLtrActivity.java
index 97ed3ce..6ce4fe4 100644
--- a/test-runner/tests/src/android/test/StubTestBrowserActivity.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestFrameLayoutLtrActivity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 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.
@@ -14,20 +14,18 @@
  * limitations under the License.
  */
 
-package android.test;
+package com.android.bidi;
 
-import junit.framework.TestSuite;
+import android.app.Activity;
+import android.os.Bundle;
 
-public class StubTestBrowserActivity extends TestBrowserActivity {
-
-    private static TestSuite mTestSuite;
-
-    static void setTopTestSuite(TestSuite testSuite) {
-        mTestSuite = testSuite;
-    }
+public class BiDiTestFrameLayoutLtrActivity extends Activity {
 
     @Override
-    public TestSuite getTopTestSuite() {
-        return mTestSuite;
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.frame_layout_ltr);
     }
 }
+
diff --git a/test-runner/tests/src/android/test/StubTestBrowserActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestFrameLayoutRtlActivity.java
similarity index 60%
copy from test-runner/tests/src/android/test/StubTestBrowserActivity.java
copy to tests/BiDiTests/src/com/android/bidi/BiDiTestFrameLayoutRtlActivity.java
index 97ed3ce..6012a5c 100644
--- a/test-runner/tests/src/android/test/StubTestBrowserActivity.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestFrameLayoutRtlActivity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 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.
@@ -14,20 +14,18 @@
  * limitations under the License.
  */
 
-package android.test;
+package com.android.bidi;
 
-import junit.framework.TestSuite;
+import android.app.Activity;
+import android.os.Bundle;
 
-public class StubTestBrowserActivity extends TestBrowserActivity {
-
-    private static TestSuite mTestSuite;
-
-    static void setTopTestSuite(TestSuite testSuite) {
-        mTestSuite = testSuite;
-    }
+public class BiDiTestFrameLayoutRtlActivity extends Activity {
 
     @Override
-    public TestSuite getTopTestSuite() {
-        return mTestSuite;
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.frame_layout_rtl);
     }
 }
+
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestLinearLayoutLtrActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestLinearLayoutLtrActivity.java
index 6d8f11d..280af6a 100644
--- a/tests/BiDiTests/src/com/android/bidi/BiDiTestLinearLayoutLtrActivity.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestLinearLayoutLtrActivity.java
@@ -18,18 +18,13 @@
 
 import android.app.Activity;
 import android.os.Bundle;
-import android.widget.LinearLayout;
 
 public class BiDiTestLinearLayoutLtrActivity extends Activity {
 
-    private LinearLayout layout;
-
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
         setContentView(R.layout.linear_layout_ltr);
-
-        layout = (LinearLayout) findViewById(R.id.layouttest);
     }
 }
diff --git a/tests/BiDiTests/src/com/android/bidi/BiDiTestLinearLayoutRtlActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestLinearLayoutRtlActivity.java
index 0130793..7121a62 100644
--- a/tests/BiDiTests/src/com/android/bidi/BiDiTestLinearLayoutRtlActivity.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestLinearLayoutRtlActivity.java
@@ -18,18 +18,13 @@
 
 import android.app.Activity;
 import android.os.Bundle;
-import android.widget.LinearLayout;
 
 public class BiDiTestLinearLayoutRtlActivity extends Activity {
 
-    private LinearLayout layout;
-
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
         setContentView(R.layout.linear_layout_rtl);
-
-        layout = (LinearLayout) findViewById(R.id.layouttest);
     }
 }
diff --git a/test-runner/tests/src/android/test/StubTestBrowserActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestRelativeLayoutLtrActivity.java
similarity index 60%
copy from test-runner/tests/src/android/test/StubTestBrowserActivity.java
copy to tests/BiDiTests/src/com/android/bidi/BiDiTestRelativeLayoutLtrActivity.java
index 97ed3ce..d6b8d02 100644
--- a/test-runner/tests/src/android/test/StubTestBrowserActivity.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestRelativeLayoutLtrActivity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 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.
@@ -14,20 +14,18 @@
  * limitations under the License.
  */
 
-package android.test;
+package com.android.bidi;
 
-import junit.framework.TestSuite;
+import android.app.Activity;
+import android.os.Bundle;
 
-public class StubTestBrowserActivity extends TestBrowserActivity {
-
-    private static TestSuite mTestSuite;
-
-    static void setTopTestSuite(TestSuite testSuite) {
-        mTestSuite = testSuite;
-    }
+public class BiDiTestRelativeLayoutLtrActivity extends Activity {
 
     @Override
-    public TestSuite getTopTestSuite() {
-        return mTestSuite;
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.relative_layout_ltr);
     }
 }
+
diff --git a/test-runner/tests/src/android/test/StubTestBrowserActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestRelativeLayoutLtrActivity2.java
similarity index 60%
copy from test-runner/tests/src/android/test/StubTestBrowserActivity.java
copy to tests/BiDiTests/src/com/android/bidi/BiDiTestRelativeLayoutLtrActivity2.java
index 97ed3ce..476375c 100644
--- a/test-runner/tests/src/android/test/StubTestBrowserActivity.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestRelativeLayoutLtrActivity2.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 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.
@@ -14,20 +14,18 @@
  * limitations under the License.
  */
 
-package android.test;
+package com.android.bidi;
 
-import junit.framework.TestSuite;
+import android.app.Activity;
+import android.os.Bundle;
 
-public class StubTestBrowserActivity extends TestBrowserActivity {
-
-    private static TestSuite mTestSuite;
-
-    static void setTopTestSuite(TestSuite testSuite) {
-        mTestSuite = testSuite;
-    }
+public class BiDiTestRelativeLayoutLtrActivity2 extends Activity {
 
     @Override
-    public TestSuite getTopTestSuite() {
-        return mTestSuite;
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.relative_layout_ltr_2);
     }
 }
+
diff --git a/test-runner/tests/src/android/test/StubTestBrowserActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestRelativeLayoutRtlActivity.java
similarity index 60%
rename from test-runner/tests/src/android/test/StubTestBrowserActivity.java
rename to tests/BiDiTests/src/com/android/bidi/BiDiTestRelativeLayoutRtlActivity.java
index 97ed3ce..683b7a3 100644
--- a/test-runner/tests/src/android/test/StubTestBrowserActivity.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestRelativeLayoutRtlActivity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 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.
@@ -14,20 +14,18 @@
  * limitations under the License.
  */
 
-package android.test;
+package com.android.bidi;
 
-import junit.framework.TestSuite;
+import android.app.Activity;
+import android.os.Bundle;
 
-public class StubTestBrowserActivity extends TestBrowserActivity {
-
-    private static TestSuite mTestSuite;
-
-    static void setTopTestSuite(TestSuite testSuite) {
-        mTestSuite = testSuite;
-    }
+public class BiDiTestRelativeLayoutRtlActivity extends Activity {
 
     @Override
-    public TestSuite getTopTestSuite() {
-        return mTestSuite;
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.relative_layout_rtl);
     }
 }
+
diff --git a/test-runner/tests/src/android/test/StubTestBrowserActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestRelativeLayoutRtlActivity2.java
similarity index 60%
copy from test-runner/tests/src/android/test/StubTestBrowserActivity.java
copy to tests/BiDiTests/src/com/android/bidi/BiDiTestRelativeLayoutRtlActivity2.java
index 97ed3ce..db2af7f 100644
--- a/test-runner/tests/src/android/test/StubTestBrowserActivity.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestRelativeLayoutRtlActivity2.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 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.
@@ -14,20 +14,18 @@
  * limitations under the License.
  */
 
-package android.test;
+package com.android.bidi;
 
-import junit.framework.TestSuite;
+import android.app.Activity;
+import android.os.Bundle;
 
-public class StubTestBrowserActivity extends TestBrowserActivity {
-
-    private static TestSuite mTestSuite;
-
-    static void setTopTestSuite(TestSuite testSuite) {
-        mTestSuite = testSuite;
-    }
+public class BiDiTestRelativeLayoutRtlActivity2 extends Activity {
 
     @Override
-    public TestSuite getTopTestSuite() {
-        return mTestSuite;
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.relative_layout_rtl_2);
     }
 }
+
diff --git a/test-runner/tests/src/android/test/StubTestBrowserActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestTableLayoutLtrActivity.java
similarity index 60%
copy from test-runner/tests/src/android/test/StubTestBrowserActivity.java
copy to tests/BiDiTests/src/com/android/bidi/BiDiTestTableLayoutLtrActivity.java
index 97ed3ce..0719dae 100644
--- a/test-runner/tests/src/android/test/StubTestBrowserActivity.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestTableLayoutLtrActivity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 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.
@@ -14,20 +14,18 @@
  * limitations under the License.
  */
 
-package android.test;
+package com.android.bidi;
 
-import junit.framework.TestSuite;
+import android.app.Activity;
+import android.os.Bundle;
 
-public class StubTestBrowserActivity extends TestBrowserActivity {
-
-    private static TestSuite mTestSuite;
-
-    static void setTopTestSuite(TestSuite testSuite) {
-        mTestSuite = testSuite;
-    }
+public class BiDiTestTableLayoutLtrActivity extends Activity {
 
     @Override
-    public TestSuite getTopTestSuite() {
-        return mTestSuite;
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.table_layout_ltr);
     }
 }
+
diff --git a/test-runner/tests/src/android/test/StubTestBrowserActivity.java b/tests/BiDiTests/src/com/android/bidi/BiDiTestTableLayoutRtlActivity.java
similarity index 60%
copy from test-runner/tests/src/android/test/StubTestBrowserActivity.java
copy to tests/BiDiTests/src/com/android/bidi/BiDiTestTableLayoutRtlActivity.java
index 97ed3ce..3553ed8 100644
--- a/test-runner/tests/src/android/test/StubTestBrowserActivity.java
+++ b/tests/BiDiTests/src/com/android/bidi/BiDiTestTableLayoutRtlActivity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 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.
@@ -14,20 +14,18 @@
  * limitations under the License.
  */
 
-package android.test;
+package com.android.bidi;
 
-import junit.framework.TestSuite;
+import android.app.Activity;
+import android.os.Bundle;
 
-public class StubTestBrowserActivity extends TestBrowserActivity {
-
-    private static TestSuite mTestSuite;
-
-    static void setTopTestSuite(TestSuite testSuite) {
-        mTestSuite = testSuite;
-    }
+public class BiDiTestTableLayoutRtlActivity extends Activity {
 
     @Override
-    public TestSuite getTopTestSuite() {
-        return mTestSuite;
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.table_layout_rtl);
     }
 }
+
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);