Merge "Import translations. DO NOT MERGE" into jb-mr1-dev
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 1b71b43..5d306d2 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -829,7 +829,6 @@
 
 static void android_view_GLES20Canvas_setTextureLayerTransform(JNIEnv* env, jobject clazz,
         Layer* layer, SkMatrix* matrix) {
-
     layer->getTransform().load(*matrix);
 }
 
diff --git a/core/res/res/drawable-hdpi/ic_notify_wifidisplay.png b/core/res/res/drawable-hdpi/ic_notify_wifidisplay.png
new file mode 100644
index 0000000..35f27df
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_notify_wifidisplay.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_notify_wifidisplay.png b/core/res/res/drawable-mdpi/ic_notify_wifidisplay.png
new file mode 100644
index 0000000..f9c8678
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_notify_wifidisplay.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_notify_wifidisplay.png b/core/res/res/drawable-xhdpi/ic_notify_wifidisplay.png
new file mode 100644
index 0000000..4cc0ee8
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_notify_wifidisplay.png
Binary files differ
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 72de22c..f8dbd84 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3821,6 +3821,13 @@
     <!-- Title text to show within the overlay.  [CHAR LIMIT=50] -->
     <string name="display_manager_overlay_display_title"><xliff:g id="name">%1$s</xliff:g>: <xliff:g id="width">%2$d</xliff:g>x<xliff:g id="height">%3$d</xliff:g>, <xliff:g id="dpi">%4$d</xliff:g> dpi</string>
 
+    <!-- Title of the notification to indicate an active wifi display connection.  [CHAR LIMIT=50] -->
+    <string name="wifi_display_notification_title">Wireless display is connected</string>
+    <!-- Message of the notification to indicate an active wifi display connection.  [CHAR LIMIT=80] -->
+    <string name="wifi_display_notification_message">This screen is showing on another device</string>
+    <!-- Label of a button to disconnect an active wifi display connection.  [CHAR LIMIT=25] -->
+    <string name="wifi_display_notification_disconnect">Disconnect</string>
+
     <!-- Keyguard strings -->
     <!-- Label shown on emergency call button in keyguard -->
     <string name="kg_emergency_call_label">Emergency call</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e76b67b..b3af161 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1486,6 +1486,7 @@
   <java-symbol type="bool" name="show_ongoing_ime_switcher" />
   <java-symbol type="color" name="config_defaultNotificationColor" />
   <java-symbol type="drawable" name="ic_notification_ime_default" />
+  <java-symbol type="drawable" name="ic_notify_wifidisplay" />
   <java-symbol type="drawable" name="stat_notify_car_mode" />
   <java-symbol type="drawable" name="stat_notify_disabled" />
   <java-symbol type="drawable" name="stat_notify_disk_full" />
@@ -1621,6 +1622,9 @@
   <java-symbol type="string" name="vpn_lockdown_error" />
   <java-symbol type="string" name="vpn_lockdown_reset" />
   <java-symbol type="string" name="wallpaper_binding_label" />
+  <java-symbol type="string" name="wifi_display_notification_title" />
+  <java-symbol type="string" name="wifi_display_notification_message" />
+  <java-symbol type="string" name="wifi_display_notification_disconnect" />
   <java-symbol type="style" name="Theme.Dialog.AppError" />
   <java-symbol type="style" name="Theme.Toast" />
   <java-symbol type="xml" name="storage_list" />
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 69be317..448e3da 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -209,6 +209,9 @@
     }
 
     inline void allocateTexture(GLenum format, GLenum storage) {
+#if DEBUG_LAYERS
+        ALOGD("  Allocate layer: %dx%d", getWidth(), getHeight());
+#endif
         glTexImage2D(renderTarget, 0, format, getWidth(), getHeight(), 0, format, storage, NULL);
     }
 
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 406d5e9..b6be5b3 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -895,12 +895,6 @@
 void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) {
     float alpha = layer->getAlpha() / 255.0f;
 
-    mat4& transform = layer->getTransform();
-    if (!transform.isIdentity()) {
-        save(0);
-        mSnapshot->transform->multiply(transform);
-    }
-
     setupDraw();
     if (layer->getRenderTarget() == GL_TEXTURE_2D) {
         setupDrawWithTexture();
@@ -937,10 +931,6 @@
     glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
 
     finishDrawTexture();
-
-    if (!transform.isIdentity()) {
-        restore();
-    }
 }
 
 void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) {
@@ -2792,12 +2782,24 @@
         return DrawGlInfo::kStatusDone;
     }
 
+    mat4* transform = NULL;
+    if (layer->isTextureLayer()) {
+        transform = &layer->getTransform();
+        if (!transform->isIdentity()) {
+            save(0);
+            mSnapshot->transform->multiply(*transform);
+        }
+    }
+
     Rect transformed;
     Rect clip;
     const bool rejected = quickRejectNoScissor(x, y,
             x + layer->layer.getWidth(), y + layer->layer.getHeight(), transformed, clip);
 
     if (rejected) {
+        if (transform && !transform->isIdentity()) {
+            restore();
+        }
         return DrawGlInfo::kStatusDone;
     }
 
@@ -2858,6 +2860,10 @@
         }
     }
 
+    if (transform && !transform->isIdentity()) {
+        restore();
+    }
+
     return DrawGlInfo::kStatusDrew;
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index a857eba..248a516 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -35,7 +35,7 @@
     View mHandleView;
     int mFingers;
     PhoneStatusBar mStatusBar;
-    private boolean mFlipped;
+    boolean mOkToFlip;
 
     public NotificationPanelView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -94,10 +94,10 @@
         if (PhoneStatusBar.SETTINGS_DRAG_SHORTCUT && mStatusBar.mHasFlipSettings) {
             switch (event.getActionMasked()) {
                 case MotionEvent.ACTION_DOWN:
-                    mFlipped = false;
+                    mOkToFlip = getExpandedHeight() == 0;
                     break;
                 case MotionEvent.ACTION_POINTER_DOWN:
-                    if (!mFlipped) {
+                    if (mOkToFlip) {
                         float miny = event.getY(0);
                         float maxy = miny;
                         for (int i=1; i<event.getPointerCount(); i++) {
@@ -111,7 +111,7 @@
                             } else {
                                 mStatusBar.flipToSettings();
                             }
-                            mFlipped = true;
+                            mOkToFlip = false;
                         }
                     }
                     break;
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
index 0ad2404..b66c883 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
@@ -43,7 +43,7 @@
 
 /**
  * Manages creating, showing, hiding and resetting the keyguard.  Calls back
- * via {@link com.android.internal.policy.impl.KeyguardViewCallback} to poke
+ * via {@link KeyguardViewMediator.ViewMediatorCallback} to poke
  * the wake lock and report that the keyguard is done, which is in turn,
  * reported to this class by the current {@link KeyguardViewBase}.
  */
@@ -233,6 +233,7 @@
 
         if (mScreenOn) {
             mKeyguardView.show();
+            mKeyguardView.requestFocus();
         }
     }
 
@@ -314,22 +315,25 @@
 
             // Caller should wait for this window to be shown before turning
             // on the screen.
-            if (mKeyguardHost.getVisibility() == View.VISIBLE) {
-                // Keyguard may be in the process of being shown, but not yet
-                // updated with the window manager...  give it a chance to do so.
-                mKeyguardHost.post(new Runnable() {
-                    public void run() {
-                        if (mKeyguardHost.getVisibility() == View.VISIBLE) {
-                            showListener.onShown(mKeyguardHost.getWindowToken());
-                        } else {
-                            showListener.onShown(null);
+            if (showListener != null) {
+                if (mKeyguardHost.getVisibility() == View.VISIBLE) {
+                    // Keyguard may be in the process of being shown, but not yet
+                    // updated with the window manager...  give it a chance to do so.
+                    mKeyguardHost.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            if (mKeyguardHost.getVisibility() == View.VISIBLE) {
+                                showListener.onShown(mKeyguardHost.getWindowToken());
+                            } else {
+                                showListener.onShown(null);
+                            }
                         }
-                    }
-                });
-            } else {
-                showListener.onShown(null);
+                    });
+                } else {
+                    showListener.onShown(null);
+                }
             }
-        } else {
+        } else if (showListener != null) {
             showListener.onShown(null);
         }
     }
@@ -356,10 +360,9 @@
         if (mKeyguardView != null) {
             mKeyguardView.wakeWhenReadyTq(keyCode);
             return true;
-        } else {
-            Log.w(TAG, "mKeyguardView is null in wakeWhenReadyTq");
-            return false;
         }
+        Log.w(TAG, "mKeyguardView is null in wakeWhenReadyTq");
+        return false;
     }
 
     /**
@@ -382,6 +385,7 @@
                 final KeyguardViewBase lastView = mKeyguardView;
                 mKeyguardView = null;
                 mKeyguardHost.postDelayed(new Runnable() {
+                    @Override
                     public void run() {
                         synchronized (KeyguardViewManager.this) {
                             lastView.cleanUp();
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
index 92f9dfd..ceb0325 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
@@ -629,9 +629,7 @@
             mScreenOn = true;
             cancelDoKeyguardLaterLocked();
             if (DEBUG) Log.d(TAG, "onScreenTurnedOn, seq = " + mDelayedShowingSequence);
-            if (showListener != null) {
-                notifyScreenOnLocked(showListener);
-            }
+            notifyScreenOnLocked(showListener);
         }
         maybeSendUserPresentBroadcast();
     }
@@ -1365,7 +1363,7 @@
 
     /**
      * Handle message sent by {@link #verifyUnlock}
-     * @see #RESET
+     * @see #VERIFY_UNLOCK
      */
     private void handleVerifyUnlock() {
         synchronized (KeyguardViewMediator.this) {
diff --git a/services/java/com/android/server/display/WifiDisplayAdapter.java b/services/java/com/android/server/display/WifiDisplayAdapter.java
index c441b02..66eac88 100644
--- a/services/java/com/android/server/display/WifiDisplayAdapter.java
+++ b/services/java/com/android/server/display/WifiDisplayAdapter.java
@@ -16,17 +16,28 @@
 
 package com.android.server.display;
 
+import com.android.internal.R;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.WifiDisplay;
 import android.hardware.display.WifiDisplayStatus;
 import android.media.RemoteDisplay;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.UserHandle;
+import android.provider.Settings;
 import android.util.Slog;
 import android.view.Surface;
 
@@ -52,8 +63,18 @@
 
     private static final boolean DEBUG = false;
 
+    private static final int MSG_SEND_STATUS_CHANGE_BROADCAST = 1;
+    private static final int MSG_UPDATE_NOTIFICATION = 2;
+
+    private static final String ACTION_DISCONNECT = "android.server.display.wfd.DISCONNECT";
+
+    private final WifiDisplayHandler mHandler;
     private final PersistentDataStore mPersistentDataStore;
     private final boolean mSupportsProtectedBuffers;
+    private final NotificationManager mNotificationManager;
+
+    private final PendingIntent mSettingsPendingIntent;
+    private final PendingIntent mDisconnectPendingIntent;
 
     private WifiDisplayController mDisplayController;
     private WifiDisplayDevice mDisplayDevice;
@@ -67,14 +88,32 @@
     private WifiDisplay[] mRememberedDisplays = WifiDisplay.EMPTY_ARRAY;
 
     private boolean mPendingStatusChangeBroadcast;
+    private boolean mPendingNotificationUpdate;
 
     public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
             Context context, Handler handler, Listener listener,
             PersistentDataStore persistentDataStore) {
         super(syncRoot, context, handler, listener, TAG);
+        mHandler = new WifiDisplayHandler(handler.getLooper());
         mPersistentDataStore = persistentDataStore;
         mSupportsProtectedBuffers = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_wifiDisplaySupportsProtectedBuffers);
+        mNotificationManager = (NotificationManager)context.getSystemService(
+                Context.NOTIFICATION_SERVICE);
+
+        Intent settingsIntent = new Intent(Settings.ACTION_WIFI_DISPLAY_SETTINGS);
+        settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        mSettingsPendingIntent = PendingIntent.getActivityAsUser(
+                context, 0, settingsIntent, 0, null, UserHandle.CURRENT);
+
+        Intent disconnectIntent = new Intent(ACTION_DISCONNECT);
+        mDisconnectPendingIntent = PendingIntent.getBroadcastAsUser(
+                context, 0, disconnectIntent, 0, UserHandle.CURRENT);
+
+        context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
+                new IntentFilter(ACTION_DISCONNECT), null, mHandler);
     }
 
     @Override
@@ -89,6 +128,7 @@
         pw.println("mAvailableDisplays=" + Arrays.toString(mAvailableDisplays));
         pw.println("mRememberedDisplays=" + Arrays.toString(mRememberedDisplays));
         pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast);
+        pw.println("mPendingNotificationUpdate=" + mPendingNotificationUpdate);
         pw.println("mSupportsProtectedBuffers=" + mSupportsProtectedBuffers);
 
         // Try to dump the controller state.
@@ -266,6 +306,8 @@
         mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height,
                 refreshRate, deviceFlags, surface);
         sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED);
+
+        scheduleUpdateNotificationLocked();
     }
 
     private void handleDisconnectLocked() {
@@ -273,6 +315,8 @@
             mDisplayDevice.clearSurfaceLocked();
             sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED);
             mDisplayDevice = null;
+
+            scheduleUpdateNotificationLocked();
         }
     }
 
@@ -280,28 +324,81 @@
         mCurrentStatus = null;
         if (!mPendingStatusChangeBroadcast) {
             mPendingStatusChangeBroadcast = true;
-            getHandler().post(mStatusChangeBroadcast);
+            mHandler.sendEmptyMessage(MSG_SEND_STATUS_CHANGE_BROADCAST);
         }
     }
 
-    private final Runnable mStatusChangeBroadcast = new Runnable() {
-        @Override
-        public void run() {
-            final Intent intent;
-            synchronized (getSyncRoot()) {
-                if (!mPendingStatusChangeBroadcast) {
-                    return;
-                }
+    private void scheduleUpdateNotificationLocked() {
+        if (!mPendingNotificationUpdate) {
+            mPendingNotificationUpdate = true;
+            mHandler.sendEmptyMessage(MSG_UPDATE_NOTIFICATION);
+        }
+    }
 
-                mPendingStatusChangeBroadcast = false;
-                intent = new Intent(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED);
-                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
-                intent.putExtra(DisplayManager.EXTRA_WIFI_DISPLAY_STATUS,
-                        getWifiDisplayStatusLocked());
+    // Runs on the handler.
+    private void handleSendStatusChangeBroadcast() {
+        final Intent intent;
+        synchronized (getSyncRoot()) {
+            if (!mPendingStatusChangeBroadcast) {
+                return;
             }
 
-            // Send protected broadcast about wifi display status to registered receivers.
-            getContext().sendBroadcast(intent);
+            mPendingStatusChangeBroadcast = false;
+            intent = new Intent(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED);
+            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+            intent.putExtra(DisplayManager.EXTRA_WIFI_DISPLAY_STATUS,
+                    getWifiDisplayStatusLocked());
+        }
+
+        // Send protected broadcast about wifi display status to registered receivers.
+        getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
+    }
+
+    // Runs on the handler.
+    private void handleUpdateNotification() {
+        final boolean isConnected;
+        synchronized (getSyncRoot()) {
+            if (!mPendingNotificationUpdate) {
+                return;
+            }
+
+            mPendingNotificationUpdate = false;
+            isConnected = (mDisplayDevice != null);
+        }
+
+        mNotificationManager.cancelAsUser(null,
+                R.string.wifi_display_notification_title, UserHandle.ALL);
+
+        if (isConnected) {
+            Context context = getContext();
+
+            Resources r = context.getResources();
+            Notification notification = new Notification.Builder(context)
+                    .setContentTitle(r.getString(
+                            R.string.wifi_display_notification_title))
+                    .setContentText(r.getString(
+                            R.string.wifi_display_notification_message))
+                    .setContentIntent(mSettingsPendingIntent)
+                    .setSmallIcon(R.drawable.ic_notify_wifidisplay)
+                    .setOngoing(true)
+                    .addAction(android.R.drawable.ic_menu_close_clear_cancel,
+                            r.getString(R.string.wifi_display_notification_disconnect),
+                            mDisconnectPendingIntent)
+                    .build();
+            mNotificationManager.notifyAsUser(null,
+                    R.string.wifi_display_notification_title,
+                    notification, UserHandle.ALL);
+        }
+    }
+
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent.getAction().equals(ACTION_DISCONNECT)) {
+                synchronized (getSyncRoot()) {
+                    requestDisconnectLocked();
+                }
+            }
         }
     };
 
@@ -454,4 +551,23 @@
             return mInfo;
         }
     }
+
+    private final class WifiDisplayHandler extends Handler {
+        public WifiDisplayHandler(Looper looper) {
+            super(looper, null, true /*async*/);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_SEND_STATUS_CHANGE_BROADCAST:
+                    handleSendStatusChangeBroadcast();
+                    break;
+
+                case MSG_UPDATE_NOTIFICATION:
+                    handleUpdateNotification();
+                    break;
+            }
+        }
+    }
 }
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back.png
new file mode 100644
index 0000000..84e6bc8
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back_default.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back_default.png
deleted file mode 100644
index ac5a97b..0000000
--- a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back_default.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home.png
new file mode 100644
index 0000000..38e4f45
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home_default.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home_default.png
deleted file mode 100644
index a90dc9b..0000000
--- a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home_default.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent.png
new file mode 100644
index 0000000..bf9f300
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent_default.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent_default.png
deleted file mode 100644
index cb3c433..0000000
--- a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent_default.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back.png
new file mode 100644
index 0000000..a00bc5b
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png
deleted file mode 100644
index 5ab09f0..0000000
--- a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back_default.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home.png
new file mode 100644
index 0000000..dc3183b
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png
deleted file mode 100644
index 62ca427..0000000
--- a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home_default.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent.png
new file mode 100644
index 0000000..b07f611
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png
deleted file mode 100644
index ff698fb..0000000
--- a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent_default.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml b/tools/layoutlib/bridge/resources/bars/navigation_bar.xml
similarity index 76%
rename from tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml
rename to tools/layoutlib/bridge/resources/bars/navigation_bar.xml
index c5acddb..599ca08 100644
--- a/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml
+++ b/tools/layoutlib/bridge/resources/bars/navigation_bar.xml
@@ -1,5 +1,9 @@
 <?xml version="1.0" encoding="utf-8"?>
 <merge xmlns:android="http://schemas.android.com/apk/res/android">
+	<TextView
+			android:layout_width="wrap_content"
+			android:layout_height="wrap_content"
+			android:layout_weight="1"/>
 	<ImageView
 			android:layout_height="wrap_content"
 			android:layout_width="wrap_content"/>
@@ -13,12 +17,4 @@
 			android:layout_width="wrap_content"
 			android:layout_height="wrap_content"
 			android:layout_weight="1"/>
-	<ImageView
-			android:layout_height="wrap_content"
-			android:layout_width="wrap_content"/>
-	<ImageView
-			android:layout_height="wrap_content"
-			android:layout_width="wrap_content"
-			android:layout_marginLeft="3dip"
-			android:layout_marginRight="15dip"/>
 </merge>
diff --git a/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml b/tools/layoutlib/bridge/resources/bars/status_bar.xml
similarity index 100%
rename from tools/layoutlib/bridge/resources/bars/phone_system_bar.xml
rename to tools/layoutlib/bridge/resources/bars/status_bar.xml
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back.png
new file mode 100644
index 0000000..bd60cd6
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back_default.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back_default.png
deleted file mode 100644
index 4cb305d..0000000
--- a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back_default.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home.png
new file mode 100644
index 0000000..c5bc5c9
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home_default.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home_default.png
deleted file mode 100644
index 31d35c8..0000000
--- a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home_default.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent.png
new file mode 100644
index 0000000..f621d9c
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent_default.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent_default.png
deleted file mode 100644
index f0cc341d..0000000
--- a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent_default.png
+++ /dev/null
Binary files differ
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index daf520b..bf8658e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -210,7 +210,8 @@
                 Capability.PLAY_ANIMATION,
                 Capability.ANIMATED_VIEW_MANIPULATION,
                 Capability.ADAPTER_BINDING,
-                Capability.EXTENDED_VIEWINFO);
+                Capability.EXTENDED_VIEWINFO,
+                Capability.FIXED_SCALABLE_NINE_PATCH);
 
 
         BridgeAssetManager.initSystem();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
index 62c886b..ea9d8d9 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
@@ -60,11 +60,15 @@
 
     protected abstract TextView getStyleableTextView();
 
-    protected CustomBar(Context context, Density density, String layoutPath, String name)
-            throws XmlPullParserException {
+    protected CustomBar(Context context, Density density, int orientation, String layoutPath,
+            String name) throws XmlPullParserException {
         super(context);
-        setOrientation(LinearLayout.HORIZONTAL);
-        setGravity(Gravity.CENTER_VERTICAL);
+        setOrientation(orientation);
+        if (orientation == LinearLayout.HORIZONTAL) {
+            setGravity(Gravity.CENTER_VERTICAL);
+        } else {
+            setGravity(Gravity.CENTER_HORIZONTAL);
+        }
 
         LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
                 Context.LAYOUT_INFLATER_SERVICE);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java
index 68f5aba..226649d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java
@@ -21,6 +21,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.content.Context;
+import android.widget.LinearLayout;
 import android.widget.TextView;
 
 public class FakeActionBar extends CustomBar {
@@ -29,7 +30,7 @@
 
     public FakeActionBar(Context context, Density density, String label, String icon)
             throws XmlPullParserException {
-        super(context, density, "/bars/action_bar.xml", "action_bar.xml");
+        super(context, density, LinearLayout.HORIZONTAL, "/bars/action_bar.xml", "action_bar.xml");
 
         // Cannot access the inside items through id because no R.id values have been
         // created for them.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
new file mode 100644
index 0000000..cc90d6b
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
@@ -0,0 +1,54 @@
+/*
+ * 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.layoutlib.bridge.bars;
+
+import com.android.resources.Density;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.content.Context;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+public class NavigationBar extends CustomBar {
+
+    public NavigationBar(Context context, Density density, int orientation) throws XmlPullParserException {
+        super(context, density, orientation, "/bars/navigation_bar.xml", "navigation_bar.xml");
+
+        setBackgroundColor(0xFF000000);
+
+        // Cannot access the inside items through id because no R.id values have been
+        // created for them.
+        // We do know the order though.
+        // 0 is a spacer.
+        int back = 1;
+        int recent = 3;
+        if (orientation == LinearLayout.VERTICAL) {
+            back = 3;
+            recent = 1;
+        }
+
+        loadIcon(back,   "ic_sysbar_back.png", density);
+        loadIcon(2,      "ic_sysbar_home.png", density);
+        loadIcon(recent, "ic_sysbar_recent.png", density);
+    }
+
+    @Override
+    protected TextView getStyleableTextView() {
+        return null;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
similarity index 86%
rename from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java
rename to tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
index 7521011..5c08412 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
@@ -25,12 +25,13 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LevelListDrawable;
 import android.view.Gravity;
+import android.widget.LinearLayout;
 import android.widget.TextView;
 
-public class PhoneSystemBar extends CustomBar {
+public class StatusBar extends CustomBar {
 
-    public PhoneSystemBar(Context context, Density density) throws XmlPullParserException {
-        super(context, density, "/bars/phone_system_bar.xml", "phone_system_bar.xml");
+    public StatusBar(Context context, Density density) throws XmlPullParserException {
+        super(context, density, LinearLayout.HORIZONTAL, "/bars/status_bar.xml", "status_bar.xml");
 
         // FIXME: use FILL_H?
         setGravity(Gravity.START | Gravity.TOP | Gravity.RIGHT);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java
deleted file mode 100644
index 456ddb4..0000000
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.layoutlib.bridge.bars;
-
-import com.android.resources.Density;
-import com.android.resources.ResourceType;
-
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LevelListDrawable;
-import android.widget.TextView;
-
-public class TabletSystemBar extends CustomBar {
-
-    public TabletSystemBar(Context context, Density density) throws XmlPullParserException {
-        super(context, density, "/bars/tablet_system_bar.xml", "tablet_system_bar.xml");
-
-        setBackgroundColor(0xFF000000);
-
-        // Cannot access the inside items through id because no R.id values have been
-        // created for them.
-        // We do know the order though.
-        loadIcon(0, "ic_sysbar_back_default.png", density);
-        loadIcon(1, "ic_sysbar_home_default.png", density);
-        loadIcon(2, "ic_sysbar_recent_default.png", density);
-        // 3 is the spacer
-        loadIcon(4, "stat_sys_wifi_signal_4_fully.png", density);
-        Drawable drawable = loadIcon(5, ResourceType.DRAWABLE, "stat_sys_battery_charge");
-        if (drawable instanceof LevelListDrawable) {
-            ((LevelListDrawable) drawable).setLevel(100);
-        }
-    }
-
-    @Override
-    protected TextView getStyleableTextView() {
-        return null;
-    }
-}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
index 5f5ebc4..c27859f 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
@@ -21,6 +21,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.content.Context;
+import android.widget.LinearLayout;
 import android.widget.TextView;
 
 public class TitleBar extends CustomBar {
@@ -29,7 +30,7 @@
 
     public TitleBar(Context context, Density density, String label)
             throws XmlPullParserException {
-        super(context, density, "/bars/title_bar.xml", "title_bar.xml");
+        super(context, density, LinearLayout.HORIZONTAL, "/bars/title_bar.xml", "title_bar.xml");
 
         // Cannot access the inside items through id because no R.id values have been
         // created for them.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
index de65fd4..f109e39 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
@@ -20,11 +20,12 @@
 import static com.android.ide.common.rendering.api.Result.Status.ERROR_TIMEOUT;
 import static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
 
+import com.android.ide.common.rendering.api.HardwareConfig;
 import com.android.ide.common.rendering.api.LayoutLog;
 import com.android.ide.common.rendering.api.RenderParams;
 import com.android.ide.common.rendering.api.RenderResources;
-import com.android.ide.common.rendering.api.Result;
 import com.android.ide.common.rendering.api.RenderResources.FrameworkResourceIdProvider;
+import com.android.ide.common.rendering.api.Result;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.android.BridgeContext;
 import com.android.resources.Density;
@@ -98,19 +99,22 @@
             return result;
         }
 
+        HardwareConfig hardwareConfig = mParams.getHardwareConfig();
+
         // setup the display Metrics.
         DisplayMetrics metrics = new DisplayMetrics();
-        metrics.densityDpi = metrics.noncompatDensityDpi = mParams.getDensity().getDpiValue();
+        metrics.densityDpi = metrics.noncompatDensityDpi =
+                hardwareConfig.getDensity().getDpiValue();
 
         metrics.density = metrics.noncompatDensity =
                 metrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT;
 
         metrics.scaledDensity = metrics.noncompatScaledDensity = metrics.density;
 
-        metrics.widthPixels = metrics.noncompatWidthPixels = mParams.getScreenWidth();
-        metrics.heightPixels = metrics.noncompatHeightPixels = mParams.getScreenHeight();
-        metrics.xdpi = metrics.noncompatXdpi = mParams.getXdpi();
-        metrics.ydpi = metrics.noncompatYdpi = mParams.getYdpi();
+        metrics.widthPixels = metrics.noncompatWidthPixels = hardwareConfig.getScreenWidth();
+        metrics.heightPixels = metrics.noncompatHeightPixels = hardwareConfig.getScreenHeight();
+        metrics.xdpi = metrics.noncompatXdpi = hardwareConfig.getXdpi();
+        metrics.ydpi = metrics.noncompatYdpi = hardwareConfig.getYdpi();
 
         RenderResources resources = mParams.getResources();
 
@@ -305,7 +309,9 @@
     private Configuration getConfiguration() {
         Configuration config = new Configuration();
 
-        ScreenSize screenSize = mParams.getConfigScreenSize();
+        HardwareConfig hardwareConfig = mParams.getHardwareConfig();
+
+        ScreenSize screenSize = hardwareConfig.getScreenSize();
         if (screenSize != null) {
             switch (screenSize) {
                 case SMALL:
@@ -323,13 +329,13 @@
             }
         }
 
-        Density density = mParams.getDensity();
+        Density density = hardwareConfig.getDensity();
         if (density == null) {
             density = Density.MEDIUM;
         }
 
-        config.screenWidthDp = mParams.getScreenWidth() / density.getDpiValue();
-        config.screenHeightDp = mParams.getScreenHeight() / density.getDpiValue();
+        config.screenWidthDp = hardwareConfig.getScreenWidth() / density.getDpiValue();
+        config.screenHeightDp = hardwareConfig.getScreenHeight() / density.getDpiValue();
         if (config.screenHeightDp < config.screenWidthDp) {
             config.smallestScreenWidthDp = config.screenHeightDp;
         } else {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java
index 8133210..b677131 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java
@@ -19,6 +19,7 @@
 import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN;
 
 import com.android.ide.common.rendering.api.DrawableParams;
+import com.android.ide.common.rendering.api.HardwareConfig;
 import com.android.ide.common.rendering.api.ResourceValue;
 import com.android.ide.common.rendering.api.Result;
 import com.android.ide.common.rendering.api.Result.Status;
@@ -59,6 +60,7 @@
         try {
             // get the drawable resource value
             DrawableParams params = getParams();
+            HardwareConfig hardwareConfig = params.getHardwareConfig();
             ResourceValue drawableResource = params.getDrawable();
 
             // resolve it
@@ -75,15 +77,15 @@
 
             // get the actual Drawable object to draw
             Drawable d = ResourceHelper.getDrawable(drawableResource, context);
-            content.setBackgroundDrawable(d);
+            content.setBackground(d);
 
             // set the AttachInfo on the root view.
             AttachInfo_Accessor.setAttachInfo(content);
 
 
             // measure
-            int w = params.getScreenWidth();
-            int h = params.getScreenHeight();
+            int w = hardwareConfig.getScreenWidth();
+            int h = hardwareConfig.getScreenHeight();
             int w_spec = MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY);
             int h_spec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY);
             content.measure(w_spec, h_spec);
@@ -99,11 +101,11 @@
 
             // create an Android bitmap around the BufferedImage
             Bitmap bitmap = Bitmap_Delegate.createBitmap(image,
-                    true /*isMutable*/, params.getDensity());
+                    true /*isMutable*/, hardwareConfig.getDensity());
 
             // create a Canvas around the Android bitmap
             Canvas canvas = new Canvas(bitmap);
-            canvas.setDensity(params.getDensity().getDpiValue());
+            canvas.setDensity(hardwareConfig.getDensity().getDpiValue());
 
             // and draw
             content.draw(canvas);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index cc0f077..c14af4a 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -24,6 +24,7 @@
 import static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
 
 import com.android.ide.common.rendering.api.AdapterBinding;
+import com.android.ide.common.rendering.api.HardwareConfig;
 import com.android.ide.common.rendering.api.IAnimationListener;
 import com.android.ide.common.rendering.api.ILayoutPullParser;
 import com.android.ide.common.rendering.api.IProjectCallback;
@@ -43,13 +44,13 @@
 import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
 import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
 import com.android.layoutlib.bridge.bars.FakeActionBar;
-import com.android.layoutlib.bridge.bars.PhoneSystemBar;
-import com.android.layoutlib.bridge.bars.TabletSystemBar;
+import com.android.layoutlib.bridge.bars.NavigationBar;
+import com.android.layoutlib.bridge.bars.StatusBar;
 import com.android.layoutlib.bridge.bars.TitleBar;
 import com.android.layoutlib.bridge.impl.binding.FakeAdapter;
 import com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter;
 import com.android.resources.ResourceType;
-import com.android.resources.ScreenSize;
+import com.android.resources.ScreenOrientation;
 import com.android.util.Pair;
 
 import org.xmlpull.v1.XmlPullParserException;
@@ -68,8 +69,8 @@
 import android.util.TypedValue;
 import android.view.AttachInfo_Accessor;
 import android.view.BridgeInflater;
-import android.view.IWindowManagerImpl;
 import android.view.IWindowManager;
+import android.view.IWindowManagerImpl;
 import android.view.Surface;
 import android.view.View;
 import android.view.View.MeasureSpec;
@@ -124,7 +125,8 @@
     private boolean mWindowIsFloating;
 
     private int mStatusBarSize;
-    private int mSystemBarSize;
+    private int mNavigationBarSize;
+    private int mNavigationBarOrientation = LinearLayout.HORIZONTAL;
     private int mTitleBarSize;
     private int mActionBarSize;
 
@@ -187,7 +189,7 @@
         findBackground(resources);
         findStatusBar(resources, metrics);
         findActionBar(resources, metrics);
-        findSystemBar(resources, metrics);
+        findNavigationBar(resources, metrics);
 
         // FIXME: find those out, and possibly add them to the render params
         boolean hasSystemNavBar = true;
@@ -221,19 +223,57 @@
         try {
 
             SessionParams params = getParams();
+            HardwareConfig hardwareConfig = params.getHardwareConfig();
             BridgeContext context = getContext();
 
+
             // the view group that receives the window background.
             ViewGroup backgroundView = null;
 
             if (mWindowIsFloating || params.isForceNoDecor()) {
                 backgroundView = mViewRoot = mContentRoot = new FrameLayout(context);
             } else {
+                if (hasSoftwareButtons() && mNavigationBarOrientation == LinearLayout.VERTICAL) {
+                    /*
+                     * This is a special case where the navigation bar is on the right.
+                       +-------------------------------------------------+---+
+                       | Status bar (always)                             |   |
+                       +-------------------------------------------------+   |
+                       | (Layout with background drawable)               |   |
+                       | +---------------------------------------------+ |   |
+                       | | Title/Action bar (optional)                 | |   |
+                       | +---------------------------------------------+ |   |
+                       | | Content, vertical extending                 | |   |
+                       | |                                             | |   |
+                       | +---------------------------------------------+ |   |
+                       +-------------------------------------------------+---+
+
+                       So we create a horizontal layout, with the nav bar on the right,
+                       and the left part is the normal layout below without the nav bar at
+                       the bottom
+                     */
+                    LinearLayout topLayout = new LinearLayout(context);
+                    mViewRoot = topLayout;
+                    topLayout.setOrientation(LinearLayout.HORIZONTAL);
+
+                    try {
+                        NavigationBar navigationBar = new NavigationBar(context,
+                                hardwareConfig.getDensity(), LinearLayout.VERTICAL);
+                        navigationBar.setLayoutParams(
+                                new LinearLayout.LayoutParams(
+                                        mNavigationBarSize,
+                                        LayoutParams.MATCH_PARENT));
+                        topLayout.addView(navigationBar);
+                    } catch (XmlPullParserException e) {
+
+                    }
+                }
+
                 /*
                  * we're creating the following layout
                  *
                    +-------------------------------------------------+
-                   | System bar (only in phone UI)                   |
+                   | Status bar (always)                             |
                    +-------------------------------------------------+
                    | (Layout with background drawable)               |
                    | +---------------------------------------------+ |
@@ -243,20 +283,31 @@
                    | |                                             | |
                    | +---------------------------------------------+ |
                    +-------------------------------------------------+
-                   | System bar (only in tablet UI)                  |
+                   | Navigation bar for soft buttons, maybe see above|
                    +-------------------------------------------------+
 
                  */
 
                 LinearLayout topLayout = new LinearLayout(context);
-                mViewRoot = topLayout;
                 topLayout.setOrientation(LinearLayout.VERTICAL);
+                // if we don't already have a view root this is it
+                if (mViewRoot == null) {
+                    mViewRoot = topLayout;
+                } else {
+                    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
+                            LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
+                    layoutParams.weight = 1;
+                    topLayout.setLayoutParams(layoutParams);
+
+                    // this is the case of soft buttons + vertical bar.
+                    // this top layout is the first layout in the horizontal layout. see above)
+                    mViewRoot.addView(topLayout, 0);
+                }
 
                 if (mStatusBarSize > 0) {
                     // system bar
                     try {
-                        PhoneSystemBar systemBar = new PhoneSystemBar(context,
-                                params.getDensity());
+                        StatusBar systemBar = new StatusBar(context, hardwareConfig.getDensity());
                         systemBar.setLayoutParams(
                                 new LinearLayout.LayoutParams(
                                         LayoutParams.MATCH_PARENT, mStatusBarSize));
@@ -280,7 +331,7 @@
                 if (mActionBarSize > 0) {
                     try {
                         FakeActionBar actionBar = new FakeActionBar(context,
-                                params.getDensity(),
+                                hardwareConfig.getDensity(),
                                 params.getAppLabel(), params.getAppIcon());
                         actionBar.setLayoutParams(
                                 new LinearLayout.LayoutParams(
@@ -292,7 +343,7 @@
                 } else if (mTitleBarSize > 0) {
                     try {
                         TitleBar titleBar = new TitleBar(context,
-                                params.getDensity(), params.getAppLabel());
+                                hardwareConfig.getDensity(), params.getAppLabel());
                         titleBar.setLayoutParams(
                                 new LinearLayout.LayoutParams(
                                         LayoutParams.MATCH_PARENT, mTitleBarSize));
@@ -310,15 +361,16 @@
                 mContentRoot.setLayoutParams(layoutParams);
                 backgroundLayout.addView(mContentRoot);
 
-                if (mSystemBarSize > 0) {
+                if (mNavigationBarOrientation == LinearLayout.HORIZONTAL &&
+                        mNavigationBarSize > 0) {
                     // system bar
                     try {
-                        TabletSystemBar systemBar = new TabletSystemBar(context,
-                                params.getDensity());
-                        systemBar.setLayoutParams(
+                        NavigationBar navigationBar = new NavigationBar(context,
+                                hardwareConfig.getDensity(), LinearLayout.HORIZONTAL);
+                        navigationBar.setLayoutParams(
                                 new LinearLayout.LayoutParams(
-                                        LayoutParams.MATCH_PARENT, mSystemBarSize));
-                        topLayout.addView(systemBar);
+                                        LayoutParams.MATCH_PARENT, mNavigationBarSize));
+                        topLayout.addView(navigationBar);
                     } catch (XmlPullParserException e) {
 
                     }
@@ -346,7 +398,7 @@
             // get the background drawable
             if (mWindowBackground != null && backgroundView != null) {
                 Drawable d = ResourceHelper.getDrawable(mWindowBackground, context);
-                backgroundView.setBackgroundDrawable(d);
+                backgroundView.setBackground(d);
             }
 
             return SUCCESS.createResult();
@@ -389,13 +441,14 @@
             }
 
             RenderingMode renderingMode = params.getRenderingMode();
+            HardwareConfig hardwareConfig = params.getHardwareConfig();
 
             // only do the screen measure when needed.
             boolean newRenderSize = false;
             if (mMeasuredScreenWidth == -1) {
                 newRenderSize = true;
-                mMeasuredScreenWidth = params.getScreenWidth();
-                mMeasuredScreenHeight = params.getScreenHeight();
+                mMeasuredScreenWidth = hardwareConfig.getScreenWidth();
+                mMeasuredScreenHeight = hardwareConfig.getScreenHeight();
 
                 if (renderingMode != RenderingMode.NORMAL) {
                     int widthMeasureSpecMode = renderingMode.isHorizExpand() ?
@@ -495,11 +548,11 @@
 
                     // create an Android bitmap around the BufferedImage
                     Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage,
-                            true /*isMutable*/, params.getDensity());
+                            true /*isMutable*/, hardwareConfig.getDensity());
 
                     // create a Canvas around the Android bitmap
                     mCanvas = new Canvas(bitmap);
-                    mCanvas.setDensity(params.getDensity().getDpiValue());
+                    mCanvas.setDensity(hardwareConfig.getDensity().getDpiValue());
                 }
 
                 if (freshRender && newImage == false) {
@@ -972,30 +1025,28 @@
         }
     }
 
-    private boolean isTabletUi() {
-        return getParams().getConfigScreenSize() == ScreenSize.XLARGE;
+    private boolean hasSoftwareButtons() {
+        return getParams().getHardwareConfig().hasSoftwareButtons();
     }
 
     private void findStatusBar(RenderResources resources, DisplayMetrics metrics) {
-        if (isTabletUi() == false) {
-            boolean windowFullscreen = getBooleanThemeValue(resources,
-                    "windowFullscreen", false /*defaultValue*/);
+        boolean windowFullscreen = getBooleanThemeValue(resources,
+                "windowFullscreen", false /*defaultValue*/);
 
-            if (windowFullscreen == false && mWindowIsFloating == false) {
-                // default value
-                mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT;
+        if (windowFullscreen == false && mWindowIsFloating == false) {
+            // default value
+            mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT;
 
-                // get the real value
-                ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
-                        "status_bar_height");
+            // get the real value
+            ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
+                    "status_bar_height");
 
-                if (value != null) {
-                    TypedValue typedValue = ResourceHelper.getValue("status_bar_height",
-                            value.getValue(), true /*requireUnit*/);
-                    if (typedValue != null) {
-                        // compute the pixel value based on the display metrics
-                        mStatusBarSize = (int)typedValue.getDimension(metrics);
-                    }
+            if (value != null) {
+                TypedValue typedValue = ResourceHelper.getValue("status_bar_height",
+                        value.getValue(), true /*requireUnit*/);
+                if (typedValue != null) {
+                    // compute the pixel value based on the display metrics
+                    mStatusBarSize = (int)typedValue.getDimension(metrics);
                 }
             }
         }
@@ -1062,22 +1113,48 @@
         }
     }
 
-    private void findSystemBar(RenderResources resources, DisplayMetrics metrics) {
-        if (isTabletUi() && mWindowIsFloating == false) {
+    private void findNavigationBar(RenderResources resources, DisplayMetrics metrics) {
+        if (hasSoftwareButtons() && mWindowIsFloating == false) {
 
             // default value
-            mSystemBarSize = 48; // ??
+            mNavigationBarSize = 48; // ??
+
+            HardwareConfig hardwareConfig = getParams().getHardwareConfig();
+
+            boolean barOnBottom = true;
+
+            if (hardwareConfig.getOrientation() == ScreenOrientation.LANDSCAPE) {
+                // compute the dp of the screen.
+                int shortSize = hardwareConfig.getScreenHeight();
+
+                // compute in dp
+                int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / hardwareConfig.getDensity().getDpiValue();
+
+                if (shortSizeDp < 600) {
+                    // 0-599dp: "phone" UI with bar on the side
+                    barOnBottom = false;
+                } else {
+                    // 600+dp: "tablet" UI with bar on the bottom
+                    barOnBottom = true;
+                }
+            }
+
+            if (barOnBottom) {
+                mNavigationBarOrientation = LinearLayout.HORIZONTAL;
+            } else {
+                mNavigationBarOrientation = LinearLayout.VERTICAL;
+            }
 
             // get the real value
             ResourceValue value = resources.getFrameworkResource(ResourceType.DIMEN,
-                    "status_bar_height");
+                    barOnBottom ? "navigation_bar_height" : "navigation_bar_width");
 
             if (value != null) {
-                TypedValue typedValue = ResourceHelper.getValue("status_bar_height",
+                TypedValue typedValue = ResourceHelper.getValue("navigation_bar_height",
                         value.getValue(), true /*requireUnit*/);
                 if (typedValue != null) {
                     // compute the pixel value based on the display metrics
-                    mSystemBarSize = (int)typedValue.getDimension(metrics);
+                    mNavigationBarSize = (int)typedValue.getDimension(metrics);
                 }
             }
         }