am a2c99407: am edc14f48: am df5919fd: Merge "Fixing cache pruning to avoid pruning those in the visible range" into jb-dev

* commit 'a2c99407db6ef00dfc6905f7e7701d083f819608':
  Fixing cache pruning to avoid pruning those in the visible range
diff --git a/Android.mk b/Android.mk
index 5fb66ab..61e8a77 100644
--- a/Android.mk
+++ b/Android.mk
@@ -114,6 +114,7 @@
 	core/java/android/content/pm/IPackageStatsObserver.aidl \
 	core/java/android/database/IContentObserver.aidl \
 	core/java/android/hardware/ISerialManager.aidl \
+	core/java/android/hardware/display/IDisplayManager.aidl \
 	core/java/android/hardware/input/IInputManager.aidl \
 	core/java/android/hardware/input/IInputDevicesChangedListener.aidl \
 	core/java/android/hardware/usb/IUsbManager.aidl \
diff --git a/api/16.txt b/api/16.txt
index 85464ce..984b844 100644
--- a/api/16.txt
+++ b/api/16.txt
@@ -22892,7 +22892,7 @@
     method protected void onApplyThemeResource(android.content.res.Resources.Theme, int, boolean);
   }
 
-  public class Display {
+  public final class Display {
     method public void getCurrentSizeRange(android.graphics.Point, android.graphics.Point);
     method public int getDisplayId();
     method public deprecated int getHeight();
diff --git a/api/current.txt b/api/current.txt
index 2716d5b..c910bd0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5355,6 +5355,7 @@
     field public static final int CONTEXT_INCLUDE_CODE = 1; // 0x1
     field public static final int CONTEXT_RESTRICTED = 4; // 0x4
     field public static final java.lang.String DEVICE_POLICY_SERVICE = "device_policy";
+    field public static final java.lang.String DISPLAY_SERVICE = "display";
     field public static final java.lang.String DOWNLOAD_SERVICE = "download";
     field public static final java.lang.String DROPBOX_SERVICE = "dropbox";
     field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method";
@@ -9952,6 +9953,13 @@
 
 }
 
+package android.hardware.display {
+
+  public final class DisplayManager {
+  }
+
+}
+
 package android.hardware.input {
 
   public final class InputManager {
@@ -23120,13 +23128,15 @@
     method protected void onApplyThemeResource(android.content.res.Resources.Theme, int, boolean);
   }
 
-  public class Display {
+  public final class Display {
     method public void getCurrentSizeRange(android.graphics.Point, android.graphics.Point);
     method public int getDisplayId();
     method public deprecated int getHeight();
     method public void getMetrics(android.util.DisplayMetrics);
     method public deprecated int getOrientation();
-    method public int getPixelFormat();
+    method public deprecated int getPixelFormat();
+    method public void getRealMetrics(android.util.DisplayMetrics);
+    method public void getRealSize(android.graphics.Point);
     method public void getRectSize(android.graphics.Rect);
     method public float getRefreshRate();
     method public int getRotation();
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 6b5048607..2471a2e 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -217,7 +217,7 @@
     mAssets.addDefaultAssets();
 
     DisplayInfo dinfo;
-    status_t status = session()->getDisplayInfo(0, &dinfo);
+    status_t status = SurfaceComposerClient::getDisplayInfo(0, &dinfo);
     if (status)
         return -1;
 
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 9364a57..74fce62 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -47,6 +47,7 @@
 import android.hardware.SensorManager;
 import android.hardware.SerialManager;
 import android.hardware.SystemSensorManager;
+import android.hardware.display.DisplayManager;
 import android.hardware.input.IInputManager;
 import android.hardware.input.InputManager;
 import android.hardware.usb.IUsbManager;
@@ -343,6 +344,11 @@
                     return InputManager.getInstance();
                 }});
 
+        registerService(DISPLAY_SERVICE, new StaticServiceFetcher() {
+            public Object createStaticService() {
+                return DisplayManager.getInstance();
+            }});
+
         registerService(INPUT_METHOD_SERVICE, new ServiceFetcher() {
                 public Object createService(ContextImpl ctx) {
                     return InputMethodManager.getInstance(ctx);
@@ -477,7 +483,7 @@
                 public Object createService(ContextImpl ctx) {
                     IBinder b = ServiceManager.getService(WIFI_SERVICE);
                     IWifiManager service = IWifiManager.Stub.asInterface(b);
-                    return new WifiManager(service, ctx.mMainThread.getHandler());
+                    return new WifiManager(ctx.getOuterContext(), service);
                 }});
 
         registerService(WIFI_P2P_SERVICE, new ServiceFetcher() {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 490165d..8597993 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1955,6 +1955,15 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a
+     * {@link android.hardware.display.DisplayManager} for interacting with display devices.
+     *
+     * @see #getSystemService
+     * @see android.hardware.display.DisplayManager
+     */
+    public static final String DISPLAY_SERVICE = "display";
+
+    /**
+     * Use with {@link #getSystemService} to retrieve a
      * {@link android.os.SchedulingPolicyService} for managing scheduling policy.
      *
      * @see #getSystemService
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
new file mode 100644
index 0000000..640044b
--- /dev/null
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2012 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.hardware.display;
+
+import android.content.Context;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+import android.view.DisplayInfo;
+
+/**
+ * Manages the properties, media routing and power state of attached displays.
+ * <p>
+ * Get an instance of this class by calling
+ * {@link android.content.Context#getSystemService(java.lang.String)
+ * Context.getSystemService()} with the argument
+ * {@link android.content.Context#DISPLAY_SERVICE}.
+ * </p>
+ */
+public final class DisplayManager {
+    private static final String TAG = "DisplayManager";
+
+    private static DisplayManager sInstance;
+
+    private final IDisplayManager mDm;
+
+    private DisplayManager(IDisplayManager dm) {
+        mDm = dm;
+    }
+
+    /**
+     * Gets an instance of the display manager.
+     * @return The display manager instance.
+     * @hide
+     */
+    public static DisplayManager getInstance() {
+        synchronized (DisplayManager.class) {
+            if (sInstance == null) {
+                IBinder b = ServiceManager.getService(Context.DISPLAY_SERVICE);
+                sInstance = new DisplayManager(IDisplayManager.Stub.asInterface(b));
+            }
+            return sInstance;
+        }
+    }
+
+    /**
+     * Get information about a particular logical display.
+     *
+     * @param displayId The logical display id.
+     * @param outInfo A structure to populate with the display info.
+     * @return True if the logical display exists, false otherwise.
+     * @hide
+     */
+    public boolean getDisplayInfo(int displayId, DisplayInfo outInfo) {
+        try {
+            return mDm.getDisplayInfo(displayId, outInfo);
+        } catch (RemoteException ex) {
+            Log.e(TAG, "Could not get display information from display manager.", ex);
+            return false;
+        }
+    }
+}
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
new file mode 100644
index 0000000..fd8c35f
--- /dev/null
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2012 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.hardware.display;
+
+import android.view.DisplayInfo;
+
+/** @hide */
+interface IDisplayManager {
+    boolean getDisplayInfo(int displayId, out DisplayInfo outInfo);
+}
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index ce49268..46e4d6e 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -17,20 +17,56 @@
 package android.view;
 
 import android.content.res.CompatibilityInfo;
+import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
 import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.util.DisplayMetrics;
-import android.util.Slog;
+import android.util.Log;
 
 /**
- * Provides information about the display size and density.
+ * Provides information about the size and density of a logical display.
+ * <p>
+ * The display area is described in two different ways.
+ * <ul>
+ * <li>The application display area specifies the part of the display that may contain
+ * an application window, excluding the system decorations.  The application display area may
+ * be smaller than the real display area because the system subtracts the space needed
+ * for decor elements such as the status bar.  Use the following methods to query the
+ * application display area: {@link #getSize}, {@link #getRectSize} and {@link #getMetrics}.</li>
+ * <li>The real display area specifies the part of the display that contains content
+ * including the system decorations.  Even so, the real display area may be smaller than the
+ * physical size of the display if the window manager is emulating a smaller display
+ * using (adb shell am display-size).  Use the following methods to query the
+ * real display area: {@link #getRealSize}, {@link #getRealMetrics}.</li>
+ * </ul>
+ * </p><p>
+ * A logical display does not necessarily represent a particular physical display device
+ * such as the built-in screen or an external monitor.  The contents of a logical
+ * display may be presented on one or more physical displays according to the devices
+ * that are currently attached and whether mirroring has been enabled.
+ * </p>
  */
-public class Display {
-    static final String TAG = "Display";
-    static final boolean DEBUG_DISPLAY_SIZE = false;
+public final class Display {
+    private static final String TAG = "Display";
+
+    private final int mDisplayId;
+    private final CompatibilityInfoHolder mCompatibilityInfo;
+    private final DisplayInfo mDisplayInfo = new DisplayInfo();
+
+    // Temporary display metrics structure used for compatibility mode.
+    private final DisplayMetrics mTempMetrics = new DisplayMetrics();
+
+    // We cache the app width and height properties briefly between calls
+    // to getHeight() and getWidth() to ensure that applications perceive
+    // consistent results when the size changes (most of the time).
+    // Applications should now be using getSize() instead.
+    private static final int CACHED_APP_SIZE_DURATION_MILLIS = 20;
+    private long mLastCachedAppSizeUpdate;
+    private int mCachedAppWidthCompat;
+    private int mCachedAppHeightCompat;
 
     /**
      * The default Display id.
@@ -38,40 +74,29 @@
     public static final int DEFAULT_DISPLAY = 0;
 
     /**
-     * Use {@link android.view.WindowManager#getDefaultDisplay()
-     * WindowManager.getDefaultDisplay()} to create a Display object.
-     * Display gives you access to some information about a particular display
-     * connected to the device.
+     * Internal method to create a display.
+     * Applications should use {@link android.view.WindowManager#getDefaultDisplay()}
+     * to get a display object for the default display.
+     *
+     * @hide
      */
-    Display(int display, CompatibilityInfoHolder compatInfo) {
-        // initalize the statics when this class is first instansiated. This is
-        // done here instead of in the static block because Zygote
-        synchronized (sStaticInit) {
-            if (!sInitialized) {
-                nativeClassInit();
-                sInitialized = true;
-            }
-        }
-        mCompatibilityInfo = compatInfo != null ? compatInfo : new CompatibilityInfoHolder();
-        mDisplay = display;
-        init(display);
+    public Display(int displayId, CompatibilityInfoHolder compatibilityInfo) {
+        mDisplayId = displayId;
+        mCompatibilityInfo = compatibilityInfo;
     }
 
     /**
-     * Returns the index of this display.  This is currently undefined; do
-     * not use.
+     * Gets the display id.
+     * <p>
+     * Each logical display has a unique id.
+     * The default display has id {@link #DEFAULT_DISPLAY}.
+     * </p>
      */
     public int getDisplayId() {
-        return mDisplay;
+        return mDisplayId;
     }
 
     /**
-     * Returns the number of displays connected to the device.  This is
-     * currently undefined; do not use.
-     */
-    native static int getDisplayCount();
-    
-    /**
      * Gets the size of the display, in pixels.
      * <p>
      * Note that this value should <em>not</em> be used for computing layouts,
@@ -84,7 +109,7 @@
      * </p><p>
      * The size returned by this method does not necessarily represent the
      * actual raw size (native resolution) of the display.  The returned size may
-     * be adjusted to exclude certain system decor elements that are always visible.
+     * be adjusted to exclude certain system decoration elements that are always visible.
      * It may also be scaled to provide compatibility with older applications that
      * were originally designed for smaller displays.
      * </p>
@@ -92,43 +117,14 @@
      * @param outSize A {@link Point} object to receive the size information.
      */
     public void getSize(Point outSize) {
-        getSizeInternal(outSize, true);
-    }
-
-    private void getSizeInternal(Point outSize, boolean doCompat) {
-        try {
-            IWindowManager wm = getWindowManager();
-            if (wm != null) {
-                wm.getDisplaySize(outSize);
-                CompatibilityInfo ci;
-                if (doCompat && (ci=mCompatibilityInfo.getIfNeeded()) != null) {
-                    synchronized (mTmpMetrics) {
-                        mTmpMetrics.noncompatWidthPixels = outSize.x;
-                        mTmpMetrics.noncompatHeightPixels = outSize.y;
-                        mTmpMetrics.density = mDensity;
-                        ci.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.x = getRawWidth();
-                outSize.y = getRawHeight();
-            }
-            if (false) {
-                RuntimeException here = new RuntimeException("here");
-                here.fillInStackTrace();
-                Slog.v(TAG, "Returning display size: " + outSize, here);
-            }
-            if (DEBUG_DISPLAY_SIZE && doCompat) Slog.v(
-                    TAG, "Returning display size: " + outSize);
-        } catch (RemoteException e) {
-            Slog.w("Display", "Unable to get display size", e);
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
+            outSize.x = mTempMetrics.widthPixels;
+            outSize.y = mTempMetrics.heightPixels;
         }
     }
-    
+
     /**
      * Gets the size of the display as a rectangle, in pixels.
      *
@@ -136,9 +132,10 @@
      * @see #getSize(Point)
      */
     public void getRectSize(Rect outSize) {
-        synchronized (mTmpPoint) {
-            getSizeInternal(mTmpPoint, true);
-            outSize.set(0, 0, mTmpPoint.x, mTmpPoint.y);
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
+            outSize.set(0, 0, mTempMetrics.widthPixels, mTempMetrics.heightPixels);
         }
     }
 
@@ -173,15 +170,12 @@
      * for example, screen decorations like the status bar are being hidden.
      */
     public void getCurrentSizeRange(Point outSmallestSize, Point outLargestSize) {
-        try {
-            IWindowManager wm = getWindowManager();
-            wm.getCurrentSizeRange(outSmallestSize, outLargestSize);
-        } catch (RemoteException e) {
-            Slog.w("Display", "Unable to get display size range", e);
-            outSmallestSize.x = 0;
-            outSmallestSize.y = 0;
-            outLargestSize.x = 0;
-            outLargestSize.y = 0;
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            outSmallestSize.x = mDisplayInfo.smallestNominalAppWidth;
+            outSmallestSize.y = mDisplayInfo.smallestNominalAppHeight;
+            outLargestSize.x = mDisplayInfo.largestNominalAppWidth;
+            outLargestSize.y = mDisplayInfo.largestNominalAppHeight;
         }
     }
 
@@ -191,12 +185,9 @@
      * @hide
      */
     public int getMaximumSizeDimension() {
-        try {
-            IWindowManager wm = getWindowManager();
-            return wm.getMaximumSizeDimension();
-        } catch (RemoteException e) {
-            Slog.w("Display", "Unable to get display maximum size dimension", e);
-            return 0;
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            return Math.max(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
         }
     }
 
@@ -205,13 +196,9 @@
      */
     @Deprecated
     public int getWidth() {
-        synchronized (mTmpPoint) {
-            long now = SystemClock.uptimeMillis();
-            if (now > (mLastGetTime+20)) {
-                getSizeInternal(mTmpPoint, true);
-                mLastGetTime = now;
-            }
-            return mTmpPoint.x;
+        synchronized (this) {
+            updateCachedAppSizeIfNeededLocked();
+            return mCachedAppWidthCompat;
         }
     }
 
@@ -220,76 +207,13 @@
      */
     @Deprecated
     public int getHeight() {
-        synchronized (mTmpPoint) {
-            long now = SystemClock.uptimeMillis();
-            if (now > (mLastGetTime+20)) {
-                getSizeInternal(mTmpPoint, true);
-                mLastGetTime = now;
-            }
-            return mTmpPoint.y;
+        synchronized (this) {
+            updateCachedAppSizeIfNeededLocked();
+            return mCachedAppHeightCompat;
         }
     }
 
     /**
-     * Gets the real size of the display without subtracting any window decor or
-     * applying any compatibility scale factors.
-     * <p>
-     * The real size may be smaller than the raw size when the window manager
-     * is emulating a smaller display (using adb shell am display-size).
-     * </p><p>
-     * The size is adjusted based on the current rotation of the display.
-     * </p>
-     * @hide
-     */
-    public void getRealSize(Point outSize) {
-        try {
-            IWindowManager wm = getWindowManager();
-            if (wm != null) {
-                wm.getRealDisplaySize(outSize);
-            } else {
-                // This is just for boot-strapping, initializing the
-                // system process before the window manager is up.
-                outSize.x = getRawWidth();
-                outSize.y = getRawHeight();
-            }
-            if (DEBUG_DISPLAY_SIZE) Slog.v(
-                    TAG, "Returning real display size: " + outSize);
-        } catch (RemoteException e) {
-            Slog.w("Display", "Unable to get real display size", e);
-        }
-    }
-
-    /**
-     * Gets the raw width of the display, in pixels.
-     * <p>
-     * The size is adjusted based on the current rotation of the display.
-     * </p>
-     * @hide
-     */
-    public int getRawWidth() {
-        int w = getRawWidthNative();
-        if (DEBUG_DISPLAY_SIZE) Slog.v(
-                TAG, "Returning raw display width: " + w);
-        return w;
-    }
-    private native int getRawWidthNative();
-
-    /**
-     * Gets the raw height of the display, in pixels.
-     * <p>
-     * The size is adjusted based on the current rotation of the display.
-     * </p>
-     * @hide
-     */
-    public int getRawHeight() {
-        int h = getRawHeightNative();
-        if (DEBUG_DISPLAY_SIZE) Slog.v(
-                TAG, "Returning raw display height: " + h);
-        return h;
-    }
-    private native int getRawHeightNative();
-    
-    /**
      * Returns the rotation of the screen from its "natural" orientation.
      * The returned value may be {@link Surface#ROTATION_0 Surface.ROTATION_0}
      * (no rotation), {@link Surface#ROTATION_90 Surface.ROTATION_90},
@@ -307,30 +231,43 @@
      * {@link Surface#ROTATION_90 Surface.ROTATION_90}.
      */
     public int getRotation() {
-        return getOrientation();
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            return mDisplayInfo.rotation;
+        }
     }
-    
+
     /**
      * @deprecated use {@link #getRotation}
      * @return orientation of this display.
      */
-    @Deprecated native public int getOrientation();
+    @Deprecated
+    public int getOrientation() {
+        return getRotation();
+    }
 
     /**
-     * Return the native pixel format of the display.  The returned value
-     * may be one of the constants int {@link android.graphics.PixelFormat}.
+     * Gets the pixel format of the display.
+     * @return One of the constants defined in {@link android.graphics.PixelFormat}.
+     *
+     * @deprecated This method is no longer supported.
+     * The result is always {@link PixelFormat#RGBA_8888}.
      */
+    @Deprecated
     public int getPixelFormat() {
-        return mPixelFormat;
+        return PixelFormat.RGBA_8888;
     }
-    
+
     /**
-     * Return the refresh rate of this display in frames per second.
+     * Gets the refresh rate of this display in frames per second.
      */
     public float getRefreshRate() {
-        return mRefreshRate;
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            return mDisplayInfo.refreshRate;
+        }
     }
-    
+
     /**
      * Gets display metrics that describe the size and density of this display.
      * <p>
@@ -346,109 +283,71 @@
      * @param outMetrics A {@link DisplayMetrics} object to receive the metrics.
      */
     public void getMetrics(DisplayMetrics outMetrics) {
-        synchronized (mTmpPoint) {
-            getSizeInternal(mTmpPoint, false);
-            getMetricsWithSize(outMetrics, mTmpPoint.x, mTmpPoint.y);
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            mDisplayInfo.getAppMetrics(outMetrics, mCompatibilityInfo);
         }
 
-        CompatibilityInfo ci = mCompatibilityInfo.getIfNeeded();
+        final CompatibilityInfo ci = mCompatibilityInfo.getIfNeeded();
         if (ci != null) {
             ci.applyToDisplayMetrics(outMetrics);
         }
+    }
 
-        if (DEBUG_DISPLAY_SIZE) Slog.v(TAG, "Returning DisplayMetrics: "
-                + outMetrics.widthPixels + "x" + outMetrics.heightPixels
-                + " " + outMetrics.density);
+    /**
+     * Gets the real size of the display without subtracting any window decor or
+     * applying any compatibility scale factors.
+     * <p>
+     * The size is adjusted based on the current rotation of the display.
+     * </p><p>
+     * The real size may be smaller than the physical size of the screen when the
+     * window manager is emulating a smaller display (using adb shell am display-size).
+     * </p>
+     *
+     * @param outSize Set to the real size of the display.
+     */
+    public void getRealSize(Point outSize) {
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            outSize.x = mDisplayInfo.logicalWidth;
+            outSize.y = mDisplayInfo.logicalHeight;
+        }
     }
 
     /**
      * Gets display metrics based on the real size of this display.
-     * @hide
+     * <p>
+     * The size is adjusted based on the current rotation of the display.
+     * </p><p>
+     * The real size may be smaller than the physical size of the screen when the
+     * window manager is emulating a smaller display (using adb shell am display-size).
+     * </p>
+     *
+     * @param outMetrics A {@link DisplayMetrics} object to receive the metrics.
      */
     public void getRealMetrics(DisplayMetrics outMetrics) {
-        synchronized (mTmpPoint) {
-            getRealSize(mTmpPoint);
-            getMetricsWithSize(outMetrics, mTmpPoint.x, mTmpPoint.y);
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            mDisplayInfo.getLogicalMetrics(outMetrics, null);
         }
     }
 
-    /**
-     * If the display is mirrored to an external HDMI display, returns the
-     * width of that display.
-     * @hide
-     */
-    public int getRawExternalWidth() {
-        return 1280;
-    }
-
-    /**
-     * If the display is mirrored to an external HDMI display, returns the
-     * height of that display.
-     * @hide
-     */
-    public int getRawExternalHeight() {
-        return 720;
-    }
-
-    /**
-     * If the display is mirrored to an external HDMI display, returns the
-     * rotation of that display relative to its natural orientation.
-     * @hide
-     */
-    public int getExternalRotation() {
-        return Surface.ROTATION_0;
-    }
-
-    /**
-     * Gets display metrics based on an explicit assumed display size.
-     * @hide
-     */
-    public void getMetricsWithSize(DisplayMetrics outMetrics,
-            int width, int height) {
-        outMetrics.densityDpi   = (int)((mDensity*DisplayMetrics.DENSITY_DEFAULT)+.5f);
-
-        outMetrics.noncompatWidthPixels  = outMetrics.widthPixels = width;
-        outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height;
-
-        outMetrics.density = outMetrics.noncompatDensity = mDensity;
-        outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density;
-        outMetrics.xdpi = outMetrics.noncompatXdpi = mDpiX;
-        outMetrics.ydpi = outMetrics.noncompatYdpi = mDpiY;
-    }
-
-    static IWindowManager getWindowManager() {
-        synchronized (sStaticInit) {
-            if (sWindowManager == null) {
-                sWindowManager = IWindowManager.Stub.asInterface(
-                        ServiceManager.getService("window"));
-            }
-            return sWindowManager;
+    private void updateDisplayInfoLocked() {
+        // TODO: only refresh the display information when needed
+        if (!DisplayManager.getInstance().getDisplayInfo(mDisplayId, mDisplayInfo)) {
+            Log.e(TAG, "Could not get information about logical display " + mDisplayId);
         }
     }
 
-    /*
-     * We use a class initializer to allow the native code to cache some
-     * field offsets.
-     */
-    native private static void nativeClassInit();
-    
-    private native void init(int display);
-
-    private final CompatibilityInfoHolder mCompatibilityInfo;
-    private final int   mDisplay;
-    // Following fields are initialized from native code
-    private int         mPixelFormat;
-    private float       mRefreshRate;
-    /*package*/ float   mDensity;
-    /*package*/ float   mDpiX;
-    /*package*/ float   mDpiY;
-    
-    private final Point mTmpPoint = new Point();
-    private final DisplayMetrics mTmpMetrics = new DisplayMetrics();
-    private float mLastGetTime;
-
-    private static final Object sStaticInit = new Object();
-    private static boolean sInitialized = false;
-    private static IWindowManager sWindowManager;
+    private void updateCachedAppSizeIfNeededLocked() {
+        long now = SystemClock.uptimeMillis();
+        if (now > mLastCachedAppSizeUpdate + CACHED_APP_SIZE_DURATION_MILLIS) {
+            updateDisplayInfoLocked();
+            mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
+            mCachedAppWidthCompat = mTempMetrics.widthPixels;
+            mCachedAppHeightCompat = mTempMetrics.heightPixels;
+            mLastCachedAppSizeUpdate = now;
+        }
+    }
 }
 
diff --git a/core/java/android/view/DisplayInfo.aidl b/core/java/android/view/DisplayInfo.aidl
new file mode 100644
index 0000000..e679208
--- /dev/null
+++ b/core/java/android/view/DisplayInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+parcelable DisplayInfo;
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
new file mode 100644
index 0000000..69b6d67
--- /dev/null
+++ b/core/java/android/view/DisplayInfo.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.content.res.CompatibilityInfo;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.DisplayMetrics;
+
+/**
+ * Describes the characteristics of a particular logical display.
+ * @hide
+ */
+public final class DisplayInfo implements Parcelable {
+    /**
+     * The width of the portion of the display that is available to applications, in pixels.
+     * Represents the size of the display minus any system decorations.
+     */
+    public int appWidth;
+
+    /**
+     * The height of the portion of the display that is available to applications, in pixels.
+     * Represents the size of the display minus any system decorations.
+     */
+    public int appHeight;
+
+    /**
+     * The smallest value of {@link #appWidth} that an application is likely to encounter,
+     * in pixels, excepting cases where the width may be even smaller due to the presence
+     * of a soft keyboard, for example.
+     */
+    public int smallestNominalAppWidth;
+
+    /**
+     * The smallest value of {@link #appHeight} that an application is likely to encounter,
+     * in pixels, excepting cases where the height may be even smaller due to the presence
+     * of a soft keyboard, for example.
+     */
+    public int smallestNominalAppHeight;
+
+    /**
+     * The largest value of {@link #appWidth} that an application is likely to encounter,
+     * in pixels, excepting cases where the width may be even larger due to system decorations
+     * such as the status bar being hidden, for example.
+     */
+    public int largestNominalAppWidth;
+
+    /**
+     * The largest value of {@link #appHeight} that an application is likely to encounter,
+     * in pixels, excepting cases where the height may be even larger due to system decorations
+     * such as the status bar being hidden, for example.
+     */
+    public int largestNominalAppHeight;
+
+    /**
+     * The logical width of the display, in pixels.
+     * Represents the usable size of the display which may be smaller than the
+     * physical size when the system is emulating a smaller display.
+     */
+    public int logicalWidth;
+
+    /**
+     * The logical height of the display, in pixels.
+     * Represents the usable size of the display which may be smaller than the
+     * physical size when the system is emulating a smaller display.
+     */
+    public int logicalHeight;
+
+    /**
+     * The rotation of the display relative to its natural orientation.
+     * May be one of {@link android.view.Surface#ROTATION_0},
+     * {@link android.view.Surface#ROTATION_90}, {@link android.view.Surface#ROTATION_180},
+     * {@link android.view.Surface#ROTATION_270}.
+     * <p>
+     * The value of this field is indeterminate if the logical display is presented on
+     * more than one physical display.
+     * </p>
+     */
+    public int rotation;
+
+    /**
+     * The refresh rate of this display in frames per second.
+     * <p>
+     * The value of this field is indeterminate if the logical display is presented on
+     * more than one physical display.
+     * </p>
+     */
+    public float refreshRate;
+
+    /**
+     * The logical display density which represents the scaling factor for
+     * the Density Independent Pixel unit.
+     */
+    public float logicalDensity;
+
+    /**
+     * The exact physical pixels per inch of the screen in the X dimension.
+     * <p>
+     * The value of this field is indeterminate if the logical display is presented on
+     * more than one physical display.
+     * </p>
+     */
+    public float physicalXDpi;
+
+    /**
+     * The exact physical pixels per inch of the screen in the Y dimension.
+     * <p>
+     * The value of this field is indeterminate if the logical display is presented on
+     * more than one physical display.
+     * </p>
+     */
+    public float physicalYDpi;
+
+    public static final Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() {
+        public DisplayInfo createFromParcel(Parcel source) {
+            return new DisplayInfo(source);
+        }
+
+        public DisplayInfo[] newArray(int size) {
+            return new DisplayInfo[size];
+        }
+    };
+
+    public DisplayInfo() {
+    }
+
+    private DisplayInfo(Parcel source) {
+        readFromParcel(source);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public void copyFrom(DisplayInfo other) {
+        appWidth = other.appWidth;
+        appHeight = other.appHeight;
+        smallestNominalAppWidth = other.smallestNominalAppWidth;
+        smallestNominalAppHeight = other.smallestNominalAppHeight;
+        largestNominalAppWidth = other.largestNominalAppWidth;
+        largestNominalAppHeight = other.largestNominalAppHeight;
+        logicalWidth = other.logicalWidth;
+        logicalHeight = other.logicalHeight;
+        rotation = other.rotation;
+        refreshRate = other.refreshRate;
+        logicalDensity = other.logicalDensity;
+        physicalXDpi = other.physicalXDpi;
+        physicalYDpi = other.physicalYDpi;
+    }
+
+    public void readFromParcel(Parcel source) {
+        appWidth = source.readInt();
+        appHeight = source.readInt();
+        smallestNominalAppWidth = source.readInt();
+        smallestNominalAppHeight = source.readInt();
+        largestNominalAppWidth = source.readInt();
+        largestNominalAppHeight = source.readInt();
+        logicalWidth = source.readInt();
+        logicalHeight = source.readInt();
+        rotation = source.readInt();
+        refreshRate = source.readFloat();
+        logicalDensity = source.readFloat();
+        physicalXDpi = source.readFloat();
+        physicalYDpi = source.readFloat();
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(appWidth);
+        dest.writeInt(appHeight);
+        dest.writeInt(smallestNominalAppWidth);
+        dest.writeInt(smallestNominalAppHeight);
+        dest.writeInt(largestNominalAppWidth);
+        dest.writeInt(largestNominalAppHeight);
+        dest.writeInt(logicalWidth);
+        dest.writeInt(logicalHeight);
+        dest.writeInt(rotation);
+        dest.writeFloat(refreshRate);
+        dest.writeFloat(logicalDensity);
+        dest.writeFloat(physicalXDpi);
+        dest.writeFloat(physicalYDpi);
+    }
+
+    public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfoHolder cih) {
+        getMetricsWithSize(outMetrics, cih, appWidth, appHeight);
+    }
+
+    public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfoHolder cih) {
+        getMetricsWithSize(outMetrics, cih, logicalWidth, logicalHeight);
+    }
+
+    private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfoHolder cih,
+            int width, int height) {
+        outMetrics.densityDpi =
+                (int)((logicalDensity * DisplayMetrics.DENSITY_DEFAULT) + .5f);
+        outMetrics.noncompatWidthPixels  = outMetrics.widthPixels = width;
+        outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height;
+
+        outMetrics.density = outMetrics.noncompatDensity = logicalDensity;
+        outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density;
+        outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi;
+        outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi;
+
+        if (cih != null) {
+            CompatibilityInfo ci = cih.getIfNeeded();
+            if (ci != null) {
+                ci.applyToDisplayMetrics(outMetrics);
+            }
+        }
+    }
+}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 5941e44..a65d6f5b 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -25,6 +25,7 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.IRemoteCallback;
+import android.view.DisplayInfo;
 import android.view.IApplicationToken;
 import android.view.IOnKeyguardExitResult;
 import android.view.IRotationWatcher;
@@ -56,11 +57,6 @@
     IWindowSession openSession(in IInputMethodClient client,
             in IInputContext inputContext);
     boolean inputMethodClientHasFocus(IInputMethodClient client);
-    
-    void getDisplaySize(out Point size);
-    void getRealDisplaySize(out Point size);
-    int getMaximumSizeDimension();
-    void getCurrentSizeRange(out Point smallestSize, out Point largestSize);
 
     void setForcedDisplaySize(int longDimen, int shortDimen);
     void clearForcedDisplaySize();
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 1105038..02ecb65 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -403,19 +403,6 @@
     public native void destroy();
     
     private native Canvas lockCanvasNative(Rect dirty);   
-    
-    /*
-     * set display parameters & screenshots
-     */
-
-    /**
-     * set the orientation of the given display.
-     * @param display
-     * @param orientation
-     * @param flags Currently unused, set to 0.
-     * @hide
-     */
-    public static native   void setOrientation(int display, int orientation, int flags);
 
     /**
      * set the orientation of the given display.
@@ -423,10 +410,8 @@
      * @param orientation
      * @hide
      */
-    public static void setOrientation(int display, int orientation) {
-        setOrientation(display, orientation, 0);
-    }
-    
+    public static native void setOrientation(int display, int orientation);
+
     /**
      * Like {@link #screenshot(int, int, int, int)} but includes all
      * Surfaces in the screenshot.
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 107f1cc..3082976 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.graphics.Point;
 import android.os.RemoteException;
 import android.provider.Settings;
 import android.util.DisplayMetrics;
@@ -277,15 +278,17 @@
         mDoubleTapSlop = (int) (sizeAndDensity * DOUBLE_TAP_SLOP + 0.5f);
         mWindowTouchSlop = (int) (sizeAndDensity * WINDOW_TOUCH_SLOP + 0.5f);
 
-        final Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
         // Size of the screen in bytes, in ARGB_8888 format
-        mMaximumDrawingCacheSize = 4 * display.getRawWidth() * display.getRawHeight();
+        final Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
+        final Point size = new Point();
+        display.getRealSize(size);
+        mMaximumDrawingCacheSize = 4 * size.x * size.y;
 
         mOverscrollDistance = (int) (sizeAndDensity * OVERSCROLL_DISTANCE + 0.5f);
         mOverflingDistance = (int) (sizeAndDensity * OVERFLING_DISTANCE + 0.5f);
 
         if (!sHasPermanentMenuKeySet) {
-            IWindowManager wm = Display.getWindowManager();
+            IWindowManager wm = WindowManagerImpl.getWindowManagerService();
             try {
                 sHasPermanentMenuKey = !wm.hasSystemNavBar() && !wm.hasNavigationBar();
                 sHasPermanentMenuKeySet = true;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index cd6c502..e8bd618 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -331,7 +331,7 @@
             if (!mInitialized) {
                 try {
                     InputMethodManager imm = InputMethodManager.getInstance(mainLooper);
-                    IWindowManager windowManager = Display.getWindowManager();
+                    IWindowManager windowManager = WindowManagerImpl.getWindowManagerService();
                     sWindowSession = windowManager.openSession(
                             imm.getClient(), imm.getInputContext());
                     float animatorScale = windowManager.getAnimationScale(2);
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index dedee97..bd95cdb 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -21,6 +21,7 @@
 import android.content.res.Configuration;
 import android.opengl.ManagedEGLContext;
 import android.os.IBinder;
+import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.util.AndroidRuntimeException;
 import android.util.Log;
@@ -111,6 +112,7 @@
     public static final int ADD_PERMISSION_DENIED = -8;
 
     private static WindowManagerImpl sDefaultWindowManager;
+    private static IWindowManager sWindowManagerService;
 
     private final WindowManagerState mState;
     private final Window mParentWindow;
@@ -135,6 +137,16 @@
         }
     }
 
+    public static IWindowManager getWindowManagerService() {
+        synchronized (WindowManagerImpl.class) {
+            if (sWindowManagerService == null) {
+                sWindowManagerService = IWindowManager.Stub.asInterface(
+                        ServiceManager.getService("window"));
+            }
+            return sWindowManagerService;
+        }
+    }
+
     public WindowManagerImpl makeLocal(Window parentWindow) {
         return new WindowManagerImpl(mState, parentWindow, parentWindow.getCompatibilityInfo());
     }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 25f0131..5be9899 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4837,18 +4837,23 @@
         }
         canvas.translate(compoundPaddingLeft, extendedPaddingTop + voffsetText);
 
+        final boolean isLayoutRtl = isLayoutRtl();
+
         final int layoutDirection = getResolvedLayoutDirection();
         final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
         if (mEllipsize == TextUtils.TruncateAt.MARQUEE &&
                 mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
             if (!mSingleLine && getLineCount() == 1 && canMarquee() &&
                     (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) != Gravity.LEFT) {
-                canvas.translate(mLayout.getLineRight(0) - (mRight - mLeft -
-                        getCompoundPaddingLeft() - getCompoundPaddingRight()), 0.0f);
+                final int width = mRight - mLeft;
+                final int padding = getCompoundPaddingLeft() + getCompoundPaddingRight();
+                final float dx = mLayout.getLineRight(0) - (width - padding);
+                canvas.translate(isLayoutRtl ? -dx : +dx, 0.0f);
             }
 
             if (mMarquee != null && mMarquee.isRunning()) {
-                canvas.translate(-mMarquee.mScroll, 0.0f);
+                final float dx = -mMarquee.getScroll();
+                canvas.translate(isLayoutRtl ? -dx : +dx, 0.0f);
             }
         }
 
@@ -4862,7 +4867,8 @@
         }
 
         if (mMarquee != null && mMarquee.shouldDrawGhost()) {
-            canvas.translate((int) mMarquee.getGhostOffset(), 0.0f);
+            final int dx = (int) mMarquee.getGhostOffset();
+            canvas.translate(isLayoutRtl ? -dx : dx, 0.0f);
             layout.draw(canvas, highlight, mHighlightPaint, cursorOffsetVertical);
         }
 
@@ -7455,7 +7461,8 @@
             if (mMarquee != null && !mMarquee.isStopped()) {
                 final Marquee marquee = mMarquee;
                 if (marquee.shouldDrawLeftFade()) {
-                    return marquee.mScroll / getHorizontalFadingEdgeLength();
+                    final float scroll = marquee.getScroll();
+                    return scroll / getHorizontalFadingEdgeLength();
                 } else {
                     return 0.0f;
                 }
@@ -7483,7 +7490,9 @@
                 mMarqueeFadeMode != MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
             if (mMarquee != null && !mMarquee.isStopped()) {
                 final Marquee marquee = mMarquee;
-                return (marquee.mMaxFadeScroll - marquee.mScroll) / getHorizontalFadingEdgeLength();
+                final float maxFadeScroll = marquee.getMaxFadeScroll();
+                final float scroll = marquee.getScroll();
+                return (maxFadeScroll - scroll) / getHorizontalFadingEdgeLength();
             } else if (getLineCount() == 1) {
                 final int layoutDirection = getResolvedLayoutDirection();
                 final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
@@ -8577,13 +8586,13 @@
         private byte mStatus = MARQUEE_STOPPED;
         private final float mScrollUnit;
         private float mMaxScroll;
-        float mMaxFadeScroll;
+        private float mMaxFadeScroll;
         private float mGhostStart;
         private float mGhostOffset;
         private float mFadeStop;
         private int mRepeatLimit;
 
-        float mScroll;
+        private float mScroll;
 
         Marquee(TextView v) {
             final float density = v.getContext().getResources().getDisplayMetrics().density;
@@ -8675,6 +8684,14 @@
             return mGhostOffset;
         }
 
+        float getScroll() {
+            return mScroll;
+        }
+
+        float getMaxFadeScroll() {
+            return mMaxFadeScroll;
+        }
+
         boolean shouldDrawLeftFade() {
             return mScroll <= mFadeStop;
         }
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index e429ffc..b1423ca 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -44,7 +44,6 @@
 	android_database_SQLiteGlobal.cpp \
 	android_database_SQLiteDebug.cpp \
 	android_emoji_EmojiFactory.cpp \
-	android_view_Display.cpp \
 	android_view_DisplayEventReceiver.cpp \
 	android_view_Surface.cpp \
 	android_view_TextureView.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index f0dd321..c936b0b 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -116,7 +116,6 @@
 extern int register_android_graphics_SurfaceTexture(JNIEnv* env);
 extern int register_android_graphics_Xfermode(JNIEnv* env);
 extern int register_android_graphics_PixelFormat(JNIEnv* env);
-extern int register_android_view_Display(JNIEnv* env);
 extern int register_android_view_DisplayEventReceiver(JNIEnv* env);
 extern int register_android_view_GLES20DisplayList(JNIEnv* env);
 extern int register_android_view_GLES20Canvas(JNIEnv* env);
@@ -1088,7 +1087,6 @@
     REG_JNI(register_android_os_SystemProperties),
     REG_JNI(register_android_os_Binder),
     REG_JNI(register_android_os_Parcel),
-    REG_JNI(register_android_view_Display),
     REG_JNI(register_android_view_DisplayEventReceiver),
     REG_JNI(register_android_nio_utils),
     REG_JNI(register_android_graphics_PixelFormat),
diff --git a/core/jni/android_view_Display.cpp b/core/jni/android_view_Display.cpp
deleted file mode 100644
index aedf1e4..0000000
--- a/core/jni/android_view_Display.cpp
+++ /dev/null
@@ -1,151 +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.
- */
-
-#include <stdio.h>
-#include <assert.h>
-
-#include <cutils/properties.h>
-
-#include <gui/SurfaceComposerClient.h>
-#include <ui/PixelFormat.h>
-#include <ui/DisplayInfo.h>
-
-#include "jni.h"
-#include "JNIHelp.h"
-#include <android_runtime/AndroidRuntime.h>
-#include <utils/misc.h>
-#include <utils/Log.h>
-#include <cutils/properties.h>
-
-// ----------------------------------------------------------------------------
-
-namespace android {
-
-// ----------------------------------------------------------------------------
-
-struct offsets_t {
-    jfieldID display;
-    jfieldID pixelFormat;
-    jfieldID fps;
-    jfieldID density;
-    jfieldID xdpi;
-    jfieldID ydpi;
-};
-static offsets_t offsets;
-static bool headless = false;
-
-// ----------------------------------------------------------------------------
-
-static void android_view_Display_init(
-        JNIEnv* env, jobject clazz, jint dpy)
-{
-    DisplayInfo info;
-    if (headless) {
-        // initialize dummy display with reasonable values
-        info.pixelFormatInfo.format = 1; // RGB_8888
-        info.fps = 60;
-        info.density = 160;
-        info.xdpi = 160;
-        info.ydpi = 160;
-    } else {
-        status_t err = SurfaceComposerClient::getDisplayInfo(DisplayID(dpy), &info);
-        if (err < 0) {
-            jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
-            return;
-        }
-    }
-    env->SetIntField(clazz, offsets.pixelFormat,info.pixelFormatInfo.format);
-    env->SetFloatField(clazz, offsets.fps,      info.fps);
-    env->SetFloatField(clazz, offsets.density,  info.density);
-    env->SetFloatField(clazz, offsets.xdpi,     info.xdpi);
-    env->SetFloatField(clazz, offsets.ydpi,     info.ydpi);
-}
-
-static jint android_view_Display_getRawWidthNative(
-        JNIEnv* env, jobject clazz)
-{
-    if (headless) return 640;
-    DisplayID dpy = env->GetIntField(clazz, offsets.display);
-    return SurfaceComposerClient::getDisplayWidth(dpy);
-}
-
-static jint android_view_Display_getRawHeightNative(
-        JNIEnv* env, jobject clazz)
-{
-    if (headless) return 480;
-    DisplayID dpy = env->GetIntField(clazz, offsets.display);
-    return SurfaceComposerClient::getDisplayHeight(dpy);
-}
-
-static jint android_view_Display_getOrientation(
-        JNIEnv* env, jobject clazz)
-{
-    if (headless) return 0; // Surface.ROTATION_0
-    DisplayID dpy = env->GetIntField(clazz, offsets.display);
-    return SurfaceComposerClient::getDisplayOrientation(dpy);
-}
-
-static jint android_view_Display_getDisplayCount(
-        JNIEnv* env, jclass clazz)
-{
-    if (headless) return 1;
-    return SurfaceComposerClient::getNumberOfDisplays();
-}
-
-// ----------------------------------------------------------------------------
-
-const char* const kClassPathName = "android/view/Display";
-
-static void nativeClassInit(JNIEnv* env, jclass clazz);
-
-static JNINativeMethod gMethods[] = {
-    {   "nativeClassInit", "()V",
-            (void*)nativeClassInit },
-    {   "getDisplayCount", "()I",
-            (void*)android_view_Display_getDisplayCount },
-	{   "init", "(I)V",
-            (void*)android_view_Display_init },
-    {   "getRawWidthNative", "()I",
-            (void*)android_view_Display_getRawWidthNative },
-    {   "getRawHeightNative", "()I",
-            (void*)android_view_Display_getRawHeightNative },
-    {   "getOrientation", "()I",
-            (void*)android_view_Display_getOrientation }
-};
-
-void nativeClassInit(JNIEnv* env, jclass clazz)
-{
-    char value[PROPERTY_VALUE_MAX];
-
-    property_get("ro.config.headless", value, "0");
-    if (strcmp(value, "1") == 0)
-        headless = true;
-
-    offsets.display     = env->GetFieldID(clazz, "mDisplay", "I");
-    offsets.pixelFormat = env->GetFieldID(clazz, "mPixelFormat", "I");
-    offsets.fps         = env->GetFieldID(clazz, "mRefreshRate", "F");
-    offsets.density     = env->GetFieldID(clazz, "mDensity", "F");
-    offsets.xdpi        = env->GetFieldID(clazz, "mDpiX", "F");
-    offsets.ydpi        = env->GetFieldID(clazz, "mDpiY", "F");
-}
-
-int register_android_view_Display(JNIEnv* env)
-{
-    return AndroidRuntime::registerNativeMethods(env,
-            kClassPathName, gMethods, NELEM(gMethods));
-}
-
-};
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 60f8c48..3cd28b1 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -473,9 +473,9 @@
 }
 
 static void Surface_setOrientation(
-        JNIEnv* env, jobject clazz, jint display, jint orientation, jint flags)
+        JNIEnv* env, jobject clazz, jint display, jint orientation)
 {
-    int err = SurfaceComposerClient::setOrientation(display, orientation, flags);
+    int err = SurfaceComposerClient::setOrientation(display, orientation, 0);
     if (err < 0) {
         doThrowIAE(env);
     }
@@ -839,7 +839,7 @@
     {"unlockCanvas",        "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvas },
     {"openTransaction",     "()V",  (void*)Surface_openTransaction },
     {"closeTransaction",    "()V",  (void*)Surface_closeTransaction },
-    {"setOrientation",      "(III)V", (void*)Surface_setOrientation },
+    {"setOrientation",      "(II)V", (void*)Surface_setOrientation },
     {"screenshot",          "(II)Landroid/graphics/Bitmap;", (void*)Surface_screenshotAll },
     {"screenshot",          "(IIII)Landroid/graphics/Bitmap;", (void*)Surface_screenshot },
     {"setLayer",            "(I)V", (void*)Surface_setLayer },
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index c6c4d5f..04765cf 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -824,7 +824,7 @@
     <string name="searchview_description_query" msgid="5911778593125355124">"Zoekopdracht"</string>
     <string name="searchview_description_clear" msgid="1330281990951833033">"Zoekopdracht wissen"</string>
     <string name="searchview_description_submit" msgid="2688450133297983542">"Zoekopdracht verzenden"</string>
-    <string name="searchview_description_voice" msgid="2453203695674994440">"Spraakgestuurd zoeken"</string>
+    <string name="searchview_description_voice" msgid="2453203695674994440">"Gesproken zoekopdrachten"</string>
     <string name="enable_explore_by_touch_warning_title" msgid="7460694070309730149">"\'Verkennen via aanraking\' aan?"</string>
     <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="8655887539089910577">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> wil \'Verkennen via aanraking\' inschakelen. Wanneer \'Verkennen via aanraking\' is ingeschakeld, kunt u beschrijvingen beluisteren of bekijken van wat er onder uw vinger staat of aanraakbewerkingen uitvoeren op de tablet."</string>
     <string name="enable_explore_by_touch_warning_message" product="default" msgid="2708199672852373195">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> wil \'Verkennen via aanraking\' inschakelen. Wanneer \'Verkennen via aanraking\' is ingeschakeld, kunt u beschrijvingen beluisteren of bekijken van wat er onder uw vinger staat of aanraakbewerkingen uitvoeren op de telefoon."</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 59cdab1..7c9a500 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -245,7 +245,7 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Ivumela insiza ukuthi ithole okuqukethe kwi-Window. Izinsiza ezinobungozi zingathola kabush iwindi eliphelele bese ibheka konke okuqukethwe ngaphandle kwaaaphasiwedi."</string>
     <string name="permlab_retrieve_window_info" msgid="8532295199112519378">"buyisa ulwazi lewindi"</string>
     <string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Ivumela uhlelo lokusebenza ukubuyisa ulwazi mayelana namawindi avela kumphathi wewindi. Izinhlelo zokusebenza zingabuyisa ulwazi olubhekiswe ukusetshenziselwa kohlelo lwangaphakathi."</string>
-    <string name="permlab_filter_events" msgid="8675535648807427389">"hlunga izehlakalo"</string>
+    <string name="permlab_filter_events" msgid="8675535648807427389">"hlunga imicimbi"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Ivumela uhlelo lokusebenza ukubhalisa isihlungi sokufaka ukusakaza kwazo zonke izehlakalo zomsebenzisi ngaphambi kokuthunyelwa. Izinhlelo zokusebenza zingalawula i-UI yohlelo ngaphandle kokungena komsebenzisi."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"ukuvala shaqa kwengxenye"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Ibeka imeneja yomsebenzi kwisimo sokuvala shaqa. Ayenzi ukuvala shaqa okuphelele."</string>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
index f01562c..6630601 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
@@ -94,7 +94,6 @@
      * Control Wifi States
      */
     public WifiManager mWifiManager;
-    public WifiManager.Channel mChannel;
 
     /*
      * Verify connectivity state
@@ -242,7 +241,6 @@
         // Get an instance of WifiManager
         mWifiManager =(WifiManager)getSystemService(Context.WIFI_SERVICE);
         mContext = this;
-        mChannel = mWifiManager.initialize(mContext, mContext.getMainLooper(), null);
 
         if (mWifiManager.isWifiApEnabled()) {
             // if soft AP is enabled, disable it
@@ -599,7 +597,7 @@
                         log("found " + ssid + " in the scan result list");
                         log("retry: " + retry);
                         foundApInScanResults = true;
-                        mWifiManager.connect(mChannel, config,
+                        mWifiManager.connect(config,
                                 new WifiManager.ActionListener() {
                                     public void onSuccess() {
                                     }
@@ -658,7 +656,7 @@
         for (WifiConfiguration wifiConfig: wifiConfigList) {
             log("remove wifi configuration: " + wifiConfig.networkId);
             int netId = wifiConfig.networkId;
-            mWifiManager.forget(mChannel, netId, new WifiManager.ActionListener() {
+            mWifiManager.forget(netId, new WifiManager.ActionListener() {
                     public void onSuccess() {
                     }
                     public void onFailure(int reason) {
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
index 8d73bc0..81075ef 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/WifiConnectionTest.java
@@ -63,7 +63,6 @@
     private ConnectivityManagerTestActivity mAct;
     private ConnectivityManagerTestRunner mRunner;
     private WifiManager mWifiManager = null;
-    private WifiManager.Channel mChannel;
     private Set<WifiConfiguration> enabledNetworks = null;
 
     public WifiConnectionTest() {
@@ -77,7 +76,6 @@
         mWifiManager = (WifiManager) mRunner.getContext().getSystemService(Context.WIFI_SERVICE);
 
         mAct = getActivity();
-        mChannel = mWifiManager.initialize(mAct, mAct.getMainLooper(), null);
 
         networks = mAct.loadNetworkConfigurations();
         if (DEBUG) {
@@ -93,24 +91,6 @@
         assertTrue("wpa_supplicant is not started ", mAct.mWifiManager.pingSupplicant());
     }
 
-    private class WifiServiceHandler extends Handler {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
-                    if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
-                        //AsyncChannel in msg.obj
-                    } else {
-                        log("Failed to establish AsyncChannel connection");
-                    }
-                    break;
-                default:
-                    //Ignore
-                    break;
-            }
-        }
-    }
-
     private void printNetworkConfigurations() {
         log("==== print network configurations parsed from XML file ====");
         log("number of access points: " + networks.size());
diff --git a/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java b/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java
index c3cc7c5..d5fcc1c 100644
--- a/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java
+++ b/core/tests/bandwidthtests/src/com/android/bandwidthtest/util/ConnectionUtil.java
@@ -74,7 +74,6 @@
     private int mWifiState;
     private NetworkInfo mWifiNetworkInfo;
     private WifiManager mWifiManager;
-    private WifiManager.Channel mChannel;
     private Context mContext;
     // Verify connectivity state
     private static final int NUM_NETWORK_TYPES = ConnectivityManager.MAX_NETWORK_TYPE + 1;
@@ -115,7 +114,6 @@
 
         // Get an instance of WifiManager
         mWifiManager =(WifiManager)mContext.getSystemService(Context.WIFI_SERVICE);
-        mChannel = mWifiManager.initialize(mContext, mContext.getMainLooper(), null);
 
         mDownloadManager = (DownloadManager)mContext.getSystemService(Context.DOWNLOAD_SERVICE);
 
@@ -574,7 +572,7 @@
                         Log.v(LOG_TAG, "Found " + ssid + " in the scan result list.");
                         Log.v(LOG_TAG, "Retry: " + retry);
                         foundApInScanResults = true;
-                        mWifiManager.connect(mChannel, config, new WifiManager.ActionListener() {
+                        mWifiManager.connect(config, new WifiManager.ActionListener() {
                                 public void onSuccess() {
                                 }
                                 public void onFailure(int reason) {
@@ -628,7 +626,7 @@
         for (WifiConfiguration wifiConfig: wifiConfigList) {
             Log.v(LOG_TAG, "Remove wifi configuration: " + wifiConfig.networkId);
             int netId = wifiConfig.networkId;
-            mWifiManager.forget(mChannel, netId, new WifiManager.ActionListener() {
+            mWifiManager.forget(netId, new WifiManager.ActionListener() {
                     public void onSuccess() {
                     }
                     public void onFailure(int reason) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 00d6d6f..63c9b79 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -22,6 +22,7 @@
 import android.app.StatusBarManager;
 import android.content.Context;
 import android.content.res.Resources;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
@@ -431,13 +432,14 @@
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("NavigationBarView {");
         final Rect r = new Rect();
+        final Point size = new Point();
+        mDisplay.getRealSize(size);
 
         pw.println(String.format("      this: " + PhoneStatusBar.viewInfo(this)
                         + " " + visibilityToString(getVisibility())));
 
         getWindowVisibleDisplayFrame(r);
-        final boolean offscreen = r.right > mDisplay.getRawWidth()
-            || r.bottom > mDisplay.getRawHeight();
+        final boolean offscreen = r.right > size.x || r.bottom > size.y;
         pw.println("      window: " 
                 + r.toShortString()
                 + " " + visibilityToString(getWindowVisibility())
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index cca9cbb..867f4f4 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -340,8 +340,6 @@
     boolean mSystemReady;
     boolean mSystemBooted;
     boolean mHdmiPlugged;
-    int mExternalDisplayWidth;
-    int mExternalDisplayHeight;
     int mUiMode;
     int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
     int mLidOpenRotation;
@@ -998,9 +996,6 @@
             }
         }
 
-        mExternalDisplayWidth = mDisplay.getRawExternalWidth();
-        mExternalDisplayHeight = mDisplay.getRawExternalHeight();
-
         mStatusBarHeight = mContext.getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.status_bar_height);
 
@@ -3037,10 +3032,6 @@
     void setHdmiPlugged(boolean plugged) {
         if (mHdmiPlugged != plugged) {
             mHdmiPlugged = plugged;
-            if (plugged && mDisplay != null) {
-                mExternalDisplayWidth = mDisplay.getRawExternalWidth();
-                mExternalDisplayHeight = mDisplay.getRawExternalHeight();
-            }
             updateRotation(true, true);
             Intent intent = new Intent(ACTION_HDMI_PLUGGED);
             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
diff --git a/services/java/com/android/server/AppWidgetServiceImpl.java b/services/java/com/android/server/AppWidgetServiceImpl.java
index 77b3b50..8836bac 100644
--- a/services/java/com/android/server/AppWidgetServiceImpl.java
+++ b/services/java/com/android/server/AppWidgetServiceImpl.java
@@ -36,6 +36,7 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
+import android.graphics.Point;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -49,6 +50,7 @@
 import android.util.Slog;
 import android.util.TypedValue;
 import android.util.Xml;
+import android.view.Display;
 import android.view.WindowManager;
 import android.widget.RemoteViews;
 
@@ -188,11 +190,12 @@
 
     void computeMaximumWidgetBitmapMemory() {
         WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
-        int height = wm.getDefaultDisplay().getRawHeight();
-        int width = wm.getDefaultDisplay().getRawWidth();
+        Display display = wm.getDefaultDisplay();
+        Point size = new Point();
+        display.getRealSize(size);
         // Cap memory usage at 1.5 times the size of the display
         // 1.5 * 4 bytes/pixel * w * h ==> 6 * w * h
-        mMaxWidgetBitmapMemory = 6 * width * height;
+        mMaxWidgetBitmapMemory = 6 * size.x * size.y;
     }
 
     public void systemReady(boolean safeMode) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 2185456..d766afd 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -49,6 +49,7 @@
 import com.android.internal.widget.LockSettingsService;
 import com.android.server.accessibility.AccessibilityManagerService;
 import com.android.server.am.ActivityManagerService;
+import com.android.server.display.DisplayManagerService;
 import com.android.server.input.InputManagerService;
 import com.android.server.net.NetworkPolicyManagerService;
 import com.android.server.net.NetworkStatsService;
@@ -115,6 +116,7 @@
 
         LightsService lights = null;
         PowerManagerService power = null;
+        DisplayManagerService display = null;
         BatteryService battery = null;
         VibratorService vibrator = null;
         AlarmManagerService alarm = null;
@@ -148,8 +150,13 @@
             power = new PowerManagerService();
             ServiceManager.addService(Context.POWER_SERVICE, power);
 
+            Slog.i(TAG, "Display Manager");
+            display = new DisplayManagerService();
+            ServiceManager.addService(Context.DISPLAY_SERVICE, display);
+
             Slog.i(TAG, "Activity Manager");
             context = ActivityManagerService.main(factoryTest);
+            display.setContext(context);
 
             Slog.i(TAG, "Telephony Registry");
             ServiceManager.addService("telephony.registry", new TelephonyRegistry(context));
@@ -214,7 +221,7 @@
 
             // only initialize the power service after we have started the
             // lights service, content providers and the battery service.
-            power.init(context, lights, ActivityManagerService.self(), battery);
+            power.init(context, lights, ActivityManagerService.self(), battery, display);
 
             Slog.i(TAG, "Alarm Manager");
             alarm = new AlarmManagerService(context);
@@ -225,7 +232,7 @@
                     ActivityManagerService.self());
 
             Slog.i(TAG, "Window Manager");
-            wm = WindowManagerService.main(context, power,
+            wm = WindowManagerService.main(context, power, display,
                     factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,
                     !firstBoot, onlyCore);
             ServiceManager.addService(Context.WINDOW_SERVICE, wm);
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index c23a1d9..087e8db 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -35,6 +35,7 @@
 import android.util.Slog;
 
 import java.util.ArrayList;
+import java.util.List;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.net.NetworkInterface;
@@ -109,7 +110,7 @@
 
     private int mOtaspMode = ServiceStateTracker.OTASP_UNKNOWN;
 
-    private CellInfo mCellInfo = null;
+    private List<CellInfo> mCellInfo = null;
 
     static final int PHONE_STATE_PERMISSION_MASK =
                 PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
@@ -242,7 +243,7 @@
                     }
                     if ((events & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
                         try {
-                            r.callback.onCellInfoChanged(new CellInfo(mCellInfo));
+                            r.callback.onCellInfoChanged(mCellInfo);
                         } catch (RemoteException ex) {
                             remove(r.binder);
                         }
@@ -336,7 +337,7 @@
         broadcastSignalStrengthChanged(signalStrength);
     }
 
-    public void notifyCellInfo(CellInfo cellInfo) {
+    public void notifyCellInfo(List<CellInfo> cellInfo) {
         if (!checkNotifyPermission("notifyCellInfo()")) {
             return;
         }
@@ -346,7 +347,7 @@
             for (Record r : mRecords) {
                 if ((r.events & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
                     try {
-                        r.callback.onCellInfoChanged(new CellInfo(cellInfo));
+                        r.callback.onCellInfoChanged(cellInfo);
                     } catch (RemoteException ex) {
                         mRemoveList.add(r.binder);
                     }
diff --git a/services/java/com/android/server/display/DisplayAdapter.java b/services/java/com/android/server/display/DisplayAdapter.java
new file mode 100644
index 0000000..e150bf8
--- /dev/null
+++ b/services/java/com/android/server/display/DisplayAdapter.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2012 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.display;
+
+/**
+ * A display adapter makes one or more display devices available to the system.
+ * <p>
+ * For now, all display adapters are registered in the system server but
+ * in principle it could be done from other processes.
+ * </p>
+ */
+public abstract class DisplayAdapter {
+    /**
+     * Gets the display adapter name.
+     * @return The display adapter name.
+     */
+    public abstract String getName();
+
+    // TODO: dynamically register display devices
+    public abstract DisplayDevice[] getDisplayDevices();
+}
diff --git a/services/java/com/android/server/display/DisplayDevice.java b/services/java/com/android/server/display/DisplayDevice.java
new file mode 100644
index 0000000..6d723f2
--- /dev/null
+++ b/services/java/com/android/server/display/DisplayDevice.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2012 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.display;
+
+/**
+ * Represents a physical display device such as the built-in display
+ * or an external monitor.
+ */
+public abstract class DisplayDevice {
+    public abstract void getInfo(DisplayDeviceInfo outInfo);
+}
diff --git a/services/java/com/android/server/display/DisplayDeviceInfo.java b/services/java/com/android/server/display/DisplayDeviceInfo.java
new file mode 100644
index 0000000..c28b9bb
--- /dev/null
+++ b/services/java/com/android/server/display/DisplayDeviceInfo.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2012 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.display;
+
+/**
+ * Describes the characteristics of a physical display device.
+ */
+public final class DisplayDeviceInfo {
+    /**
+     * The width of the display in its natural orientation, in pixels.
+     * This value is not affected by display rotation.
+     */
+    public int width;
+
+    /**
+     * The height of the display in its natural orientation, in pixels.
+     * This value is not affected by display rotation.
+     */
+    public int height;
+
+    public float refreshRate;
+    public float density;
+    public float xDpi;
+    public float yDpi;
+
+    public void copyFrom(DisplayDeviceInfo other) {
+        width = other.width;
+        height = other.height;
+        refreshRate = other.refreshRate;
+        density = other.density;
+        xDpi = other.xDpi;
+        yDpi = other.yDpi;
+    }
+
+    @Override
+    public String toString() {
+        return width + " x " + height + ", " + refreshRate + " fps, "
+                + "density " + density + ", " + xDpi + " x " + yDpi + " dpi";
+    }
+}
diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java
new file mode 100644
index 0000000..082d28f
--- /dev/null
+++ b/services/java/com/android/server/display/DisplayManagerService.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2012 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.display;
+
+import android.Manifest;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.display.IDisplayManager;
+import android.os.Binder;
+import android.os.SystemProperties;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.Surface;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * Manages the properties, media routing and power state of attached displays.
+ * <p>
+ * The display manager service does not own or directly control the displays.
+ * Instead, other components in the system register their display adapters with the
+ * display manager service which acts as a central controller.
+ * </p>
+ */
+public final class DisplayManagerService extends IDisplayManager.Stub {
+    private static final String TAG = "DisplayManagerService";
+
+    private static final String SYSTEM_HEADLESS = "ro.config.headless";
+
+    private final Object mLock = new Object();
+
+    private Context mContext;
+    private final boolean mHeadless;
+    private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
+
+    // TODO: represent this as a map between logical and physical devices
+    private DisplayInfo mDefaultDisplayInfo;
+    private DisplayDevice mDefaultDisplayDevice;
+    private DisplayDeviceInfo mDefaultDisplayDeviceInfo;
+
+    public DisplayManagerService() {
+        mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1");
+        registerDisplayAdapters();
+        initializeDefaultDisplay();
+    }
+
+    public void setContext(Context context) {
+        mContext = context;
+    }
+
+    // FIXME: this isn't the right API for the long term
+    public void setDefaultDisplayInfo(DisplayInfo info) {
+        synchronized (mLock) {
+            mDefaultDisplayInfo.copyFrom(info);
+        }
+    }
+
+    // FIXME: this isn't the right API for the long term
+    public void getDefaultExternalDisplayDeviceInfo(DisplayDeviceInfo info) {
+        // hardcoded assuming 720p touch screen plugged into HDMI and USB
+        // need to redesign this
+        info.width = 1280;
+        info.height = 720;
+    }
+
+    public boolean isHeadless() {
+        return mHeadless;
+    }
+
+    @Override // Binder call
+    public boolean getDisplayInfo(int displayId, DisplayInfo outInfo) {
+        synchronized (mLock) {
+            if (displayId == Display.DEFAULT_DISPLAY) {
+                outInfo.copyFrom(mDefaultDisplayInfo);
+                return true;
+            }
+            return false;
+        }
+    }
+
+    @Override // Binder call
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (mContext == null
+                || mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
+                        != PackageManager.PERMISSION_GRANTED) {
+            pw.println("Permission Denial: can't dump DisplayManager from from pid="
+                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
+            return;
+        }
+
+        pw.println("DISPLAY MANAGER (dumpsys display)\n");
+
+        pw.println("Headless: " + mHeadless);
+
+        DisplayDeviceInfo info = new DisplayDeviceInfo();
+        for (DisplayAdapter adapter : mDisplayAdapters) {
+            pw.println("Displays for adapter " + adapter.getName());
+            for (DisplayDevice device : adapter.getDisplayDevices()) {
+                device.getInfo(info);
+                pw.print("  ");
+                pw.println(info);
+            }
+        }
+    }
+
+    private void registerDisplayAdapters() {
+        if (mHeadless) {
+            registerDisplayAdapter(new HeadlessDisplayAdapter());
+        } else {
+            registerDisplayAdapter(new SurfaceFlingerDisplayAdapter());
+        }
+    }
+
+    private void registerDisplayAdapter(DisplayAdapter adapter) {
+        // TODO: do this dynamically
+        mDisplayAdapters.add(adapter);
+        mDefaultDisplayDevice = adapter.getDisplayDevices()[0];
+        mDefaultDisplayDeviceInfo = new DisplayDeviceInfo();
+        mDefaultDisplayDevice.getInfo(mDefaultDisplayDeviceInfo);
+    }
+
+    private void initializeDefaultDisplay() {
+        // Bootstrap the default logical display using the default physical display.
+        mDefaultDisplayInfo = new DisplayInfo();
+        mDefaultDisplayInfo.appWidth = mDefaultDisplayDeviceInfo.width;
+        mDefaultDisplayInfo.appHeight = mDefaultDisplayDeviceInfo.height;
+        mDefaultDisplayInfo.logicalWidth = mDefaultDisplayDeviceInfo.width;
+        mDefaultDisplayInfo.logicalHeight = mDefaultDisplayDeviceInfo.height;
+        mDefaultDisplayInfo.rotation = Surface.ROTATION_0;
+        mDefaultDisplayInfo.refreshRate = mDefaultDisplayDeviceInfo.refreshRate;
+        mDefaultDisplayInfo.logicalDensity = mDefaultDisplayDeviceInfo.density;
+        mDefaultDisplayInfo.physicalXDpi = mDefaultDisplayDeviceInfo.xDpi;
+        mDefaultDisplayInfo.physicalYDpi = mDefaultDisplayDeviceInfo.yDpi;
+        mDefaultDisplayInfo.smallestNominalAppWidth = mDefaultDisplayDeviceInfo.width;
+        mDefaultDisplayInfo.smallestNominalAppHeight = mDefaultDisplayDeviceInfo.height;
+        mDefaultDisplayInfo.largestNominalAppWidth = mDefaultDisplayDeviceInfo.width;
+        mDefaultDisplayInfo.largestNominalAppHeight = mDefaultDisplayDeviceInfo.height;
+    }
+}
diff --git a/services/java/com/android/server/display/HeadlessDisplayAdapter.java b/services/java/com/android/server/display/HeadlessDisplayAdapter.java
new file mode 100644
index 0000000..d2a70d2
--- /dev/null
+++ b/services/java/com/android/server/display/HeadlessDisplayAdapter.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2012 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.display;
+
+/**
+ * Provides a fake default display for headless systems.
+ */
+public final class HeadlessDisplayAdapter extends DisplayAdapter {
+    private final DisplayDevice mDefaultDisplay = new DisplayDevice() {
+        @Override
+        public void getInfo(DisplayDeviceInfo outInfo) {
+            outInfo.width = 640;
+            outInfo.height = 480;
+            outInfo.refreshRate = 60;
+            outInfo.density = 1.0f;
+            outInfo.xDpi = 160;
+            outInfo.yDpi = 160;
+        }
+    };
+
+    @Override
+    public String getName() {
+        return "HeadlessDisplayAdapter";
+    }
+
+    @Override
+    public DisplayDevice[] getDisplayDevices() {
+        return new DisplayDevice[] { mDefaultDisplay };
+    }
+}
diff --git a/services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java b/services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java
new file mode 100644
index 0000000..89934d3
--- /dev/null
+++ b/services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2012 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.display;
+
+/**
+ * A display adapter for the displays managed by Surface Flinger.
+ */
+public final class SurfaceFlingerDisplayAdapter extends DisplayAdapter {
+    private static native void nativeGetDefaultDisplayDeviceInfo(DisplayDeviceInfo outInfo);
+
+    private final DisplayDevice mDefaultDisplay = new DisplayDevice() {
+        @Override
+        public void getInfo(DisplayDeviceInfo outInfo) {
+            nativeGetDefaultDisplayDeviceInfo(outInfo);
+        }
+    };
+
+    @Override
+    public String getName() {
+        return "SurfaceFlingerDisplayAdapter";
+    }
+
+    @Override
+    public DisplayDevice[] getDisplayDevices() {
+        return new DisplayDevice[] { mDefaultDisplay };
+    }
+}
diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java
index 2940b70..b3cd0f2f 100644
--- a/services/java/com/android/server/power/PowerManagerService.java
+++ b/services/java/com/android/server/power/PowerManagerService.java
@@ -22,6 +22,7 @@
 import com.android.server.LightsService;
 import com.android.server.Watchdog;
 import com.android.server.am.BatteryStatsService;
+import com.android.server.display.DisplayManagerService;
 
 import android.app.ActivityManagerNative;
 import android.app.IActivityManager;
@@ -254,6 +255,7 @@
     private IActivityManager mActivityService;
     private IBatteryStats mBatteryStats;
     private BatteryService mBatteryService;
+    private DisplayManagerService mDisplayManagerService;
     private SensorManager mSensorManager;
     private Sensor mProximitySensor;
     private Sensor mLightSensor;
@@ -543,12 +545,13 @@
     private ContentQueryMap mSettings;
 
     public void init(Context context, LightsService lights, IActivityManager activity,
-            BatteryService battery) {
+            BatteryService battery, DisplayManagerService displayManagerService) {
         mLightsService = lights;
         mContext = context;
         mActivityService = activity;
         mBatteryStats = BatteryStatsService.getService();
         mBatteryService = battery;
+        mDisplayManagerService = displayManagerService;
 
         mLcdLight = lights.getLight(LightsService.LIGHT_ID_BACKLIGHT);
         mButtonLight = lights.getLight(LightsService.LIGHT_ID_BUTTONS);
diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java
index b2cf3e0..f0b0e1f 100644
--- a/services/java/com/android/server/wm/DragState.java
+++ b/services/java/com/android/server/wm/DragState.java
@@ -125,8 +125,8 @@
             // The drag window covers the entire display
             mDragWindowHandle.frameLeft = 0;
             mDragWindowHandle.frameTop = 0;
-            mDragWindowHandle.frameRight = mService.mCurDisplayWidth;
-            mDragWindowHandle.frameBottom = mService.mCurDisplayHeight;
+            mDragWindowHandle.frameRight = mService.mDisplayInfo.logicalWidth;
+            mDragWindowHandle.frameBottom = mService.mDisplayInfo.logicalHeight;
 
             // Pause rotations before a drag.
             if (WindowManagerService.DEBUG_ORIENTATION) {
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index d0456ee..ac0fa87 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -45,6 +45,8 @@
 import com.android.server.EventLogTags;
 import com.android.server.Watchdog;
 import com.android.server.am.BatteryStatsService;
+import com.android.server.display.DisplayDeviceInfo;
+import com.android.server.display.DisplayManagerService;
 import com.android.server.input.InputManagerService;
 import com.android.server.power.PowerManagerService;
 import com.android.server.power.ShutdownThread;
@@ -104,6 +106,7 @@
 import android.util.TypedValue;
 import android.view.Choreographer;
 import android.view.Display;
+import android.view.DisplayInfo;
 import android.view.Gravity;
 import android.view.IApplicationToken;
 import android.view.IInputFilter;
@@ -271,7 +274,6 @@
 
     private static final String SYSTEM_SECURE = "ro.secure";
     private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
-    private static final String SYSTEM_HEADLESS = "ro.config.headless";
 
     /**
      * Condition waited on by {@link #reenableKeyguard} to know the call to
@@ -482,14 +484,7 @@
     int mInitialDisplayHeight = 0;
     int mBaseDisplayWidth = 0;
     int mBaseDisplayHeight = 0;
-    int mCurDisplayWidth = 0;
-    int mCurDisplayHeight = 0;
-    int mAppDisplayWidth = 0;
-    int mAppDisplayHeight = 0;
-    int mSmallestDisplayWidth = 0;
-    int mSmallestDisplayHeight = 0;
-    int mLargestDisplayWidth = 0;
-    int mLargestDisplayHeight = 0;
+    final DisplayInfo mDisplayInfo = new DisplayInfo();
 
     int mRotation = 0;
     int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -616,6 +611,7 @@
     float mAnimatorDurationScale = 1.0f;
 
     final InputManagerService mInputManager;
+    final DisplayManagerService mDisplayManager;
 
     // Who is holding the screen on.
     Session mHoldingScreenOn;
@@ -785,9 +781,10 @@
     final boolean mOnlyCore;
 
     public static WindowManagerService main(Context context,
-            PowerManagerService pm, boolean haveInputMethods, boolean allowBootMsgs,
+            PowerManagerService pm, DisplayManagerService dm,
+            boolean haveInputMethods, boolean allowBootMsgs,
             boolean onlyCore) {
-        WMThread thr = new WMThread(context, pm, haveInputMethods, allowBootMsgs, onlyCore);
+        WMThread thr = new WMThread(context, pm, dm, haveInputMethods, allowBootMsgs, onlyCore);
         thr.start();
 
         synchronized (thr) {
@@ -806,15 +803,18 @@
 
         private final Context mContext;
         private final PowerManagerService mPM;
+        private final DisplayManagerService mDisplayManager;
         private final boolean mHaveInputMethods;
         private final boolean mAllowBootMessages;
         private final boolean mOnlyCore;
 
         public WMThread(Context context, PowerManagerService pm,
+                DisplayManagerService dm,
                 boolean haveInputMethods, boolean allowBootMsgs, boolean onlyCore) {
             super("WindowManager");
             mContext = context;
             mPM = pm;
+            mDisplayManager = dm;
             mHaveInputMethods = haveInputMethods;
             mAllowBootMessages = allowBootMsgs;
             mOnlyCore = onlyCore;
@@ -825,7 +825,7 @@
             Looper.prepare();
             //Looper.myLooper().setMessageLogging(new LogPrinter(
             //        android.util.Log.DEBUG, TAG, android.util.Log.LOG_ID_SYSTEM));
-            WindowManagerService s = new WindowManagerService(mContext, mPM,
+            WindowManagerService s = new WindowManagerService(mContext, mPM, mDisplayManager,
                     mHaveInputMethods, mAllowBootMessages, mOnlyCore);
             android.os.Process.setThreadPriority(
                     android.os.Process.THREAD_PRIORITY_DISPLAY);
@@ -892,6 +892,7 @@
     }
 
     private WindowManagerService(Context context, PowerManagerService pm,
+            DisplayManagerService displayManager,
             boolean haveInputMethods, boolean showBootMsgs, boolean onlyCore) {
         mContext = context;
         mHaveInputMethods = haveInputMethods;
@@ -899,7 +900,8 @@
         mOnlyCore = onlyCore;
         mLimitedAlphaCompositing = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_sf_limitedAlpha);
-        mHeadless = "1".equals(SystemProperties.get(SYSTEM_HEADLESS, "0"));
+        mDisplayManager = displayManager;
+        mHeadless = displayManager.isHeadless();
 
         mPowerManager = pm;
         mPowerManager.setPolicy(mPolicy);
@@ -1650,8 +1652,8 @@
         mInnerFields.mWallpaperMayChange = false;
         int changed = 0;
 
-        final int dw = mAppDisplayWidth;
-        final int dh = mAppDisplayHeight;
+        final int dw = mDisplayInfo.appWidth;
+        final int dh = mDisplayInfo.appHeight;
 
         // First find top-most window that has asked to be on top of the
         // wallpaper; all wallpapers go behind it.
@@ -2060,8 +2062,8 @@
     }
 
     void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
-        final int dw = mAppDisplayWidth;
-        final int dh = mAppDisplayHeight;
+        final int dw = mDisplayInfo.appWidth;
+        final int dh = mDisplayInfo.appHeight;
 
         WindowState target = mWallpaperTarget;
         if (target != null) {
@@ -2123,8 +2125,8 @@
 
     void updateWallpaperVisibilityLocked() {
         final boolean visible = isWallpaperVisible(mWallpaperTarget);
-        final int dw = mAppDisplayWidth;
-        final int dh = mAppDisplayHeight;
+        final int dw = mDisplayInfo.appWidth;
+        final int dh = mDisplayInfo.appHeight;
 
         int curTokenIndex = mWallpaperTokens.size();
         while (curTokenIndex > 0) {
@@ -2699,9 +2701,11 @@
         mTmpFloats[Matrix.MSKEW_X] = dsdy;
         mTmpFloats[Matrix.MSCALE_Y] = dtdy;
         matrix.setValues(mTmpFloats);
-        final RectF dispRect = new RectF(0, 0, mCurDisplayWidth, mCurDisplayHeight);
+        final RectF dispRect = new RectF(0, 0,
+                mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
         matrix.mapRect(dispRect);
-        window.mGivenTouchableRegion.set(0, 0, mCurDisplayWidth, mCurDisplayHeight);
+        window.mGivenTouchableRegion.set(0, 0,
+                mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
         window.mGivenTouchableRegion.op((int)dispRect.left, (int)dispRect.top,
                 (int)dispRect.right, (int)dispRect.bottom, Region.Op.DIFFERENCE);
         window.mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
@@ -2981,7 +2985,8 @@
             configChanged = updateOrientationFromAppTokensLocked(false);
             performLayoutAndPlaceSurfacesLocked();
             if (toBeDisplayed && win.mIsWallpaper) {
-                updateWallpaperOffsetLocked(win, mAppDisplayWidth, mAppDisplayHeight, false);
+                updateWallpaperOffsetLocked(win,
+                        mDisplayInfo.appWidth, mDisplayInfo.appHeight, false);
             }
             if (win.mAppToken != null) {
                 win.mAppToken.updateReportedVisibilityLocked();
@@ -3201,8 +3206,8 @@
         }
         if (enter) {
             // Entering app zooms out from the center of the initial rect.
-            float scaleW = mNextAppTransitionStartWidth / (float) mAppDisplayWidth;
-            float scaleH = mNextAppTransitionStartHeight / (float) mAppDisplayHeight;
+            float scaleW = mNextAppTransitionStartWidth / (float) mDisplayInfo.appWidth;
+            float scaleH = mNextAppTransitionStartHeight / (float) mDisplayInfo.appHeight;
             Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1,
                     computePivot(mNextAppTransitionStartX, scaleW),
                     computePivot(mNextAppTransitionStartY, scaleH));
@@ -3222,8 +3227,8 @@
         final Interpolator interpolator = AnimationUtils.loadInterpolator(mContext,
                 com.android.internal.R.interpolator.decelerate_cubic);
         a.setInterpolator(interpolator);
-        a.initialize(mAppDisplayWidth, mAppDisplayHeight,
-                mAppDisplayWidth, mAppDisplayHeight);
+        a.initialize(mDisplayInfo.appWidth, mDisplayInfo.appHeight,
+                mDisplayInfo.appWidth, mDisplayInfo.appHeight);
         return a;
     }
 
@@ -3252,8 +3257,8 @@
         if (thumb) {
             // Animation for zooming thumbnail from its initial size to
             // filling the screen.
-            float scaleW = mAppDisplayWidth/thumbWidth;
-            float scaleH = mAppDisplayHeight/thumbHeight;
+            float scaleW = mDisplayInfo.appWidth/thumbWidth;
+            float scaleH = mDisplayInfo.appHeight/thumbHeight;
 
             Animation scale = new ScaleAnimation(1, scaleW, 1, scaleH,
                     computePivot(mNextAppTransitionStartX, 1/scaleW),
@@ -3273,8 +3278,8 @@
             a = set;
         } else if (enter) {
             // Entering app zooms out from the center of the thumbnail.
-            float scaleW = thumbWidth / mAppDisplayWidth;
-            float scaleH = thumbHeight / mAppDisplayHeight;
+            float scaleW = thumbWidth / mDisplayInfo.appWidth;
+            float scaleH = thumbHeight / mDisplayInfo.appHeight;
             Animation scale = new ScaleAnimation(scaleW, 1, scaleH, 1,
                     computePivot(mNextAppTransitionStartX, scaleW),
                     computePivot(mNextAppTransitionStartY, scaleH));
@@ -3300,8 +3305,8 @@
         final Interpolator interpolator = AnimationUtils.loadInterpolator(mContext,
                 com.android.internal.R.interpolator.decelerate_quad);
         a.setInterpolator(interpolator);
-        a.initialize(mAppDisplayWidth, mAppDisplayHeight,
-                mAppDisplayWidth, mAppDisplayHeight);
+        a.initialize(mDisplayInfo.appWidth, mDisplayInfo.appHeight,
+                mDisplayInfo.appWidth, mDisplayInfo.appHeight);
         return a;
     }
 
@@ -5498,8 +5503,8 @@
         synchronized(mWindowMap) {
             long ident = Binder.clearCallingIdentity();
 
-            dw = mCurDisplayWidth;
-            dh = mCurDisplayHeight;
+            dw = mDisplayInfo.logicalWidth;
+            dh = mDisplayInfo.logicalHeight;
 
             int aboveAppLayer = mPolicy.windowTypeToLayerLw(
                     WindowManager.LayoutParams.TYPE_APPLICATION) * TYPE_LAYER_MULTIPLIER
@@ -5793,8 +5798,7 @@
         mWaitingForConfig = true;
         mLayoutNeeded = true;
         startFreezingDisplayLocked(inTransaction);
-        mInputManager.setDisplayOrientation(0, rotation,
-                mDisplay != null ? mDisplay.getExternalRotation() : Surface.ROTATION_0);
+        mInputManager.setDisplayOrientation(0, rotation, Surface.ROTATION_0);
 
         // We need to update our screen size information to match the new
         // rotation.  Note that this is redundant with the later call to
@@ -5816,7 +5820,7 @@
                     && mAnimator.mScreenRotationAnimation.hasScreenshot()) {
                 if (mAnimator.mScreenRotationAnimation.setRotation(rotation, mFxSession,
                         MAX_ANIMATION_DURATION, mTransitionAnimationScale,
-                        mCurDisplayWidth, mCurDisplayHeight)) {
+                        mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight)) {
                     updateLayoutToAnimationLocked();
                 }
             }
@@ -6315,18 +6319,18 @@
 
     private void adjustDisplaySizeRanges(int rotation, int dw, int dh) {
         final int width = mPolicy.getConfigDisplayWidth(dw, dh, rotation);
-        if (width < mSmallestDisplayWidth) {
-            mSmallestDisplayWidth = width;
+        if (width < mDisplayInfo.smallestNominalAppWidth) {
+            mDisplayInfo.smallestNominalAppWidth = width;
         }
-        if (width > mLargestDisplayWidth) {
-            mLargestDisplayWidth = width;
+        if (width > mDisplayInfo.largestNominalAppWidth) {
+            mDisplayInfo.largestNominalAppWidth = width;
         }
         final int height = mPolicy.getConfigDisplayHeight(dw, dh, rotation);
-        if (height < mSmallestDisplayHeight) {
-            mSmallestDisplayHeight = height;
+        if (height < mDisplayInfo.smallestNominalAppHeight) {
+            mDisplayInfo.smallestNominalAppHeight = height;
         }
-        if (height > mLargestDisplayHeight) {
-            mLargestDisplayHeight = height;
+        if (height > mDisplayInfo.largestNominalAppHeight) {
+            mDisplayInfo.largestNominalAppHeight = height;
         }
     }
 
@@ -6423,10 +6427,10 @@
             unrotDw = dw;
             unrotDh = dh;
         }
-        mSmallestDisplayWidth = 1<<30;
-        mSmallestDisplayHeight = 1<<30;
-        mLargestDisplayWidth = 0;
-        mLargestDisplayHeight = 0;
+        mDisplayInfo.smallestNominalAppWidth = 1<<30;
+        mDisplayInfo.smallestNominalAppHeight = 1<<30;
+        mDisplayInfo.largestNominalAppWidth = 0;
+        mDisplayInfo.largestNominalAppHeight = 0;
         adjustDisplaySizeRanges(Surface.ROTATION_0, unrotDw, unrotDh);
         adjustDisplaySizeRanges(Surface.ROTATION_90, unrotDh, unrotDw);
         adjustDisplaySizeRanges(Surface.ROTATION_180, unrotDw, unrotDh);
@@ -6437,7 +6441,7 @@
         sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw);
         sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh);
         sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw);
-        outConfig.smallestScreenWidthDp = (int)(mSmallestDisplayWidth / density);
+        outConfig.smallestScreenWidthDp = (int)(mDisplayInfo.smallestNominalAppWidth / density);
         outConfig.screenLayout = sl;
     }
 
@@ -6481,33 +6485,25 @@
                 || mRotation == Surface.ROTATION_270);
         final int realdw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
         final int realdh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
+        int dw = realdw;
+        int dh = realdh;
 
-        synchronized(mDisplaySizeLock) {
-            if (mAltOrientation) {
-                mCurDisplayWidth = realdw;
-                mCurDisplayHeight = realdh;
-                if (realdw > realdh) {
-                    // Turn landscape into portrait.
-                    int maxw = (int)(realdh/1.3f);
-                    if (maxw < realdw) {
-                        mCurDisplayWidth = maxw;
-                    }
-                } else {
-                    // Turn portrait into landscape.
-                    int maxh = (int)(realdw/1.3f);
-                    if (maxh < realdh) {
-                        mCurDisplayHeight = maxh;
-                    }
+        if (mAltOrientation) {
+            if (realdw > realdh) {
+                // Turn landscape into portrait.
+                int maxw = (int)(realdh/1.3f);
+                if (maxw < realdw) {
+                    dw = maxw;
                 }
             } else {
-                mCurDisplayWidth = realdw;
-                mCurDisplayHeight = realdh;
+                // Turn portrait into landscape.
+                int maxh = (int)(realdw/1.3f);
+                if (maxh < realdh) {
+                    dh = maxh;
+                }
             }
         }
 
-        final int dw = mCurDisplayWidth;
-        final int dh = mCurDisplayHeight;
-
         if (config != null) {
             int orientation = Configuration.ORIENTATION_SQUARE;
             if (dw < dh) {
@@ -6518,25 +6514,26 @@
             config.orientation = orientation;
         }
 
-        // Update real display metrics.
-        mDisplay.getMetricsWithSize(mRealDisplayMetrics, mCurDisplayWidth, mCurDisplayHeight);
-
         // Update application display metrics.
-        final DisplayMetrics dm = mDisplayMetrics;
         final int appWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
         final int appHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
         synchronized(mDisplaySizeLock) {
-            mAppDisplayWidth = appWidth;
-            mAppDisplayHeight = appHeight;
-            mAnimator.setDisplayDimensions(mCurDisplayWidth, mCurDisplayHeight,
-                    mAppDisplayWidth, mAppDisplayHeight);
+            mDisplayInfo.rotation = mRotation;
+            mDisplayInfo.logicalWidth = dw;
+            mDisplayInfo.logicalHeight = dh;
+            mDisplayInfo.appWidth = appWidth;
+            mDisplayInfo.appHeight = appHeight;
+            mDisplayInfo.getLogicalMetrics(mRealDisplayMetrics, null);
+            mDisplayInfo.getAppMetrics(mDisplayMetrics, null);
+            mDisplayManager.setDefaultDisplayInfo(mDisplayInfo);
+
+            mAnimator.setDisplayDimensions(dw, dh, appWidth, appHeight);
         }
         if (false) {
-            Slog.i(TAG, "Set app display size: " + mAppDisplayWidth
-                    + " x " + mAppDisplayHeight);
+            Slog.i(TAG, "Set app display size: " + appWidth + " x " + appHeight);
         }
-        mDisplay.getMetricsWithSize(dm, mAppDisplayWidth, mAppDisplayHeight);
 
+        final DisplayMetrics dm = mDisplayMetrics;
         mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
                 mCompatDisplayMetrics);
 
@@ -6843,27 +6840,26 @@
             mDisplay = wm.getDefaultDisplay();
             mIsTouchDevice = mContext.getPackageManager().hasSystemFeature(
                     PackageManager.FEATURE_TOUCHSCREEN);
+
             synchronized(mDisplaySizeLock) {
-                mInitialDisplayWidth = mDisplay.getRawWidth();
-                mInitialDisplayHeight = mDisplay.getRawHeight();
-                int rot = mDisplay.getRotation();
-                if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
-                    // If the screen is currently rotated, we need to swap the
-                    // initial width and height to get the true natural values.
-                    int tmp = mInitialDisplayWidth;
-                    mInitialDisplayWidth = mInitialDisplayHeight;
-                    mInitialDisplayHeight = tmp;
-                }
-                mBaseDisplayWidth = mCurDisplayWidth = mAppDisplayWidth = mInitialDisplayWidth;
-                mBaseDisplayHeight = mCurDisplayHeight = mAppDisplayHeight = mInitialDisplayHeight;
-                mAnimator.setDisplayDimensions(mCurDisplayWidth, mCurDisplayHeight,
-                        mAppDisplayWidth, mAppDisplayHeight);
+                // Bootstrap the default logical display from the display manager.
+                mDisplayManager.getDisplayInfo(Display.DEFAULT_DISPLAY, mDisplayInfo);
+                mInitialDisplayWidth = mDisplayInfo.logicalWidth;
+                mInitialDisplayHeight = mDisplayInfo.logicalHeight;
+                mBaseDisplayWidth = mInitialDisplayWidth;
+                mBaseDisplayHeight = mInitialDisplayHeight;
+
+                mAnimator.setDisplayDimensions(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight,
+                        mDisplayInfo.appWidth, mDisplayInfo.appHeight);
             }
+
+            DisplayDeviceInfo info = new DisplayDeviceInfo();
+            mDisplayManager.getDefaultExternalDisplayDeviceInfo(info);
             mInputManager.setDisplaySize(Display.DEFAULT_DISPLAY,
-                    mDisplay.getRawWidth(), mDisplay.getRawHeight(),
-                    mDisplay.getRawExternalWidth(), mDisplay.getRawExternalHeight());
+                    mInitialDisplayWidth, mInitialDisplayHeight,
+                    info.width, info.height);
             mInputManager.setDisplayOrientation(Display.DEFAULT_DISPLAY,
-                    mDisplay.getRotation(), mDisplay.getExternalRotation());
+                    mDisplay.getRotation(), Surface.ROTATION_0);
             mPolicy.setInitialDisplaySize(mDisplay, mInitialDisplayWidth, mInitialDisplayHeight);
         }
 
@@ -7471,20 +7467,6 @@
         return false;
     }
 
-    public void getDisplaySize(Point size) {
-        synchronized(mDisplaySizeLock) {
-            size.x = mAppDisplayWidth;
-            size.y = mAppDisplayHeight;
-        }
-    }
-
-    public void getRealDisplaySize(Point size) {
-        synchronized(mDisplaySizeLock) {
-            size.x = mCurDisplayWidth;
-            size.y = mCurDisplayHeight;
-        }
-    }
-
     public void getInitialDisplaySize(Point size) {
         synchronized(mDisplaySizeLock) {
             size.x = mInitialDisplayWidth;
@@ -7492,23 +7474,6 @@
         }
     }
 
-    public int getMaximumSizeDimension() {
-        synchronized(mDisplaySizeLock) {
-            // Do this based on the raw screen size, until we are smarter.
-            return mBaseDisplayWidth > mBaseDisplayHeight
-                    ? mBaseDisplayWidth : mBaseDisplayHeight;
-        }
-    }
-
-    public void getCurrentSizeRange(Point smallestSize, Point largestSize) {
-        synchronized(mDisplaySizeLock) {
-            smallestSize.x = mSmallestDisplayWidth;
-            smallestSize.y = mSmallestDisplayHeight;
-            largestSize.x = mLargestDisplayWidth;
-            largestSize.y = mLargestDisplayHeight;
-        }
-    }
-
     public void setForcedDisplaySize(int longDimen, int shortDimen) {
         synchronized(mWindowMap) {
             int width, height;
@@ -7899,8 +7864,8 @@
         
         mLayoutNeeded = false;
         
-        final int dw = mCurDisplayWidth;
-        final int dh = mCurDisplayHeight;
+        final int dw = mDisplayInfo.logicalWidth;
+        final int dh = mDisplayInfo.logicalHeight;
 
         final int NFW = mFakeWindows.size();
         for (int i=0; i<NFW; i++) {
@@ -8492,8 +8457,8 @@
                 if (!mAnimator.isDimming(winAnimator)) {
                     final int width, height;
                     if (attrs.type == WindowManager.LayoutParams.TYPE_BOOT_PROGRESS) {
-                        width = mCurDisplayWidth;
-                        height = mCurDisplayHeight;
+                        width = mDisplayInfo.logicalWidth;
+                        height = mDisplayInfo.logicalHeight;
                     } else {
                         width = innerDw;
                         height = innerDh;
@@ -8537,10 +8502,10 @@
         }
 
         final long currentTime = SystemClock.uptimeMillis();
-        final int dw = mCurDisplayWidth;
-        final int dh = mCurDisplayHeight;
-        final int innerDw = mAppDisplayWidth;
-        final int innerDh = mAppDisplayHeight;
+        final int dw = mDisplayInfo.logicalWidth;
+        final int dh = mDisplayInfo.logicalHeight;
+        final int innerDw = mDisplayInfo.appWidth;
+        final int innerDh = mDisplayInfo.appHeight;
 
         int i;
 
@@ -9456,7 +9421,7 @@
             }
 
             mAnimator.mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
-                    mFxSession, inTransaction, mCurDisplayWidth, mCurDisplayHeight,
+                    mFxSession, inTransaction, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight,
                     mDisplay.getRotation());
         }
     }
@@ -9486,7 +9451,7 @@
                 && mAnimator.mScreenRotationAnimation.hasScreenshot()) {
             if (DEBUG_ORIENTATION) Slog.i(TAG, "**** Dismissing screen rotation animation");
             if (mAnimator.mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION,
-                    mTransitionAnimationScale, mCurDisplayWidth, mCurDisplayHeight)) {
+                    mTransitionAnimationScale, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight)) {
                 updateLayoutToAnimationLocked();
             } else {
                 mAnimator.mScreenRotationAnimation.kill();
@@ -9935,19 +9900,21 @@
                         pw.print(" base=");
                         pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
                     }
-                    final int rawWidth = mDisplay.getRawWidth();
-                    final int rawHeight = mDisplay.getRawHeight();
-                    if (rawWidth != mCurDisplayWidth || rawHeight != mCurDisplayHeight) {
-                        pw.print(" raw="); pw.print(rawWidth); pw.print("x"); pw.print(rawHeight);
+                    if (mInitialDisplayWidth != mDisplayInfo.logicalWidth
+                            || mInitialDisplayHeight != mDisplayInfo.logicalHeight) {
+                        pw.print(" init="); pw.print(mInitialDisplayWidth);
+                        pw.print("x"); pw.print(mInitialDisplayHeight);
                     }
                     pw.print(" cur=");
-                    pw.print(mCurDisplayWidth); pw.print("x"); pw.print(mCurDisplayHeight);
+                    pw.print(mDisplayInfo.logicalWidth);
+                    pw.print("x"); pw.print(mDisplayInfo.logicalHeight);
                     pw.print(" app=");
-                    pw.print(mAppDisplayWidth); pw.print("x"); pw.print(mAppDisplayHeight);
-                    pw.print(" rng="); pw.print(mSmallestDisplayWidth);
-                    pw.print("x"); pw.print(mSmallestDisplayHeight);
-                    pw.print("-"); pw.print(mLargestDisplayWidth);
-                    pw.print("x"); pw.println(mLargestDisplayHeight);
+                    pw.print(mDisplayInfo.appWidth);
+                    pw.print("x"); pw.print(mDisplayInfo.appHeight);
+                    pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth);
+                    pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
+                    pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
+                    pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
         } else {
             pw.println("  NO DISPLAY");
         }
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index 94fd199..d371828 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -480,7 +480,7 @@
 
         if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
             mService.updateWallpaperOffsetLocked(this,
-                    mService.mAppDisplayWidth, mService.mAppDisplayHeight, false);
+                    mService.mDisplayInfo.appWidth, mService.mDisplayInfo.appHeight, false);
         }
 
         if (WindowManagerService.localLOGV) {
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index f08204f..ce87f4c 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -151,8 +151,8 @@
         mAnimator = service.mAnimator;
         mPolicy = service.mPolicy;
         mContext = service.mContext;
-        mAnimDw = service.mAppDisplayWidth;
-        mAnimDh = service.mAppDisplayHeight;
+        mAnimDw = service.mDisplayInfo.appWidth;
+        mAnimDh = service.mDisplayInfo.appHeight;
 
         mWin = win;
         mAttachedWinAnimator = win.mAttachedWindow == null
@@ -248,8 +248,8 @@
                         " scale=" + mService.mWindowAnimationScale);
                     mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(),
                             mAnimDw, mAnimDh);
-                    mAnimDw = mService.mAppDisplayWidth;
-                    mAnimDh = mService.mAppDisplayHeight;
+                    mAnimDw = mService.mDisplayInfo.appWidth;
+                    mAnimDh = mService.mDisplayInfo.appHeight;
                     mAnimation.setStartTime(currentTime);
                     mLocalAnimating = true;
                     mAnimating = true;
@@ -1102,7 +1102,7 @@
                         WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
                 if ((w.mAttrs.flags & LayoutParams.FLAG_DIM_BEHIND) != 0) {
                     mService.startDimming(this, w.mExiting ? 0 : w.mAttrs.dimAmount,
-                            mService.mAppDisplayWidth, mService.mAppDisplayHeight);
+                            mService.mDisplayInfo.appWidth, mService.mDisplayInfo.appHeight);
                 }
             } catch (RuntimeException e) {
                 // If something goes wrong with the surface (such
diff --git a/services/jni/Android.mk b/services/jni/Android.mk
index d097a93..43e59b2 100644
--- a/services/jni/Android.mk
+++ b/services/jni/Android.mk
@@ -4,6 +4,7 @@
 LOCAL_SRC_FILES:= \
     com_android_server_AlarmManagerService.cpp \
     com_android_server_BatteryService.cpp \
+    com_android_server_display_SurfaceFlingerDisplayAdapter.cpp \
     com_android_server_input_InputApplicationHandle.cpp \
     com_android_server_input_InputManagerService.cpp \
     com_android_server_input_InputWindowHandle.cpp \
diff --git a/services/jni/com_android_server_display_SurfaceFlingerDisplayAdapter.cpp b/services/jni/com_android_server_display_SurfaceFlingerDisplayAdapter.cpp
new file mode 100644
index 0000000..e636eed
--- /dev/null
+++ b/services/jni/com_android_server_display_SurfaceFlingerDisplayAdapter.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SurfaceFlingerDisplayAdapter"
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include <gui/SurfaceComposerClient.h>
+#include <ui/DisplayInfo.h>
+
+#include <utils/Log.h>
+
+namespace android {
+
+static struct {
+    jfieldID width;
+    jfieldID height;
+    jfieldID refreshRate;
+    jfieldID density;
+    jfieldID xDpi;
+    jfieldID yDpi;
+} gDisplayDeviceInfoClassInfo;
+
+
+static void nativeGetDefaultDisplayDeviceInfo(JNIEnv* env, jclass clazz, jobject infoObj) {
+    DisplayInfo info;
+    status_t err = SurfaceComposerClient::getDisplayInfo(0, &info);
+    if (err < 0) {
+        jniThrowExceptionFmt(env, "java/lang/RuntimeException",
+                "Could not get display info.  err=%d", err);
+        return;
+    }
+
+    env->SetIntField(infoObj, gDisplayDeviceInfoClassInfo.width, info.w);
+    env->SetIntField(infoObj, gDisplayDeviceInfoClassInfo.height, info.h);
+    env->SetFloatField(infoObj, gDisplayDeviceInfoClassInfo.refreshRate, info.fps);
+    env->SetFloatField(infoObj, gDisplayDeviceInfoClassInfo.density, info.density);
+    env->SetFloatField(infoObj, gDisplayDeviceInfoClassInfo.xDpi, info.xdpi);
+    env->SetFloatField(infoObj, gDisplayDeviceInfoClassInfo.yDpi, info.ydpi);
+}
+
+
+static JNINativeMethod gSurfaceFlingerDisplayAdapterMethods[] = {
+    /* name, signature, funcPtr */
+    { "nativeGetDefaultDisplayDeviceInfo",
+            "(Lcom/android/server/display/DisplayDeviceInfo;)V",
+            (void*) nativeGetDefaultDisplayDeviceInfo },
+};
+
+#define FIND_CLASS(var, className) \
+        var = env->FindClass(className); \
+        LOG_FATAL_IF(! var, "Unable to find class " className);
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+int register_android_server_display_SurfaceFlingerDisplayAdapter(JNIEnv* env) {
+    int res = jniRegisterNativeMethods(env,
+            "com/android/server/display/SurfaceFlingerDisplayAdapter",
+            gSurfaceFlingerDisplayAdapterMethods, NELEM(gSurfaceFlingerDisplayAdapterMethods));
+    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
+
+    jclass clazz;
+    FIND_CLASS(clazz, "com/android/server/display/DisplayDeviceInfo");
+    GET_FIELD_ID(gDisplayDeviceInfoClassInfo.width, clazz, "width", "I");
+    GET_FIELD_ID(gDisplayDeviceInfoClassInfo.height, clazz, "height", "I");
+    GET_FIELD_ID(gDisplayDeviceInfoClassInfo.refreshRate, clazz, "refreshRate", "F");
+    GET_FIELD_ID(gDisplayDeviceInfoClassInfo.density, clazz, "density", "F");
+    GET_FIELD_ID(gDisplayDeviceInfoClassInfo.xDpi, clazz, "xDpi", "F");
+    GET_FIELD_ID(gDisplayDeviceInfoClassInfo.yDpi, clazz, "yDpi", "F");
+    return 0;
+}
+
+} /* namespace android */
diff --git a/services/jni/onload.cpp b/services/jni/onload.cpp
index 423ebd1..50873fc 100644
--- a/services/jni/onload.cpp
+++ b/services/jni/onload.cpp
@@ -22,6 +22,7 @@
 namespace android {
 int register_android_server_AlarmManagerService(JNIEnv* env);
 int register_android_server_BatteryService(JNIEnv* env);
+int register_android_server_display_SurfaceFlingerDisplayAdapter(JNIEnv* env);
 int register_android_server_InputApplicationHandle(JNIEnv* env);
 int register_android_server_InputWindowHandle(JNIEnv* env);
 int register_android_server_InputManager(JNIEnv* env);
@@ -51,6 +52,7 @@
 
     register_android_server_PowerManagerService(env);
     register_android_server_SerialService(env);
+    register_android_server_display_SurfaceFlingerDisplayAdapter(env);
     register_android_server_InputApplicationHandle(env);
     register_android_server_InputWindowHandle(env);
     register_android_server_InputManager(env);
diff --git a/telephony/java/android/telephony/CdmaCellIdentity.java b/telephony/java/android/telephony/CdmaCellIdentity.java
deleted file mode 100644
index 5b8454f..0000000
--- a/telephony/java/android/telephony/CdmaCellIdentity.java
+++ /dev/null
@@ -1,164 +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.telephony;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * CellIdentity is to represent a unique CDMA cell
- *
- * @hide pending API review
- */
-public final class CdmaCellIdentity extends CellIdentity implements Parcelable {
-    // Network Id 0..65535
-    private final int mNetworkId;
-    // CDMA System Id 0..32767
-    private final int mSystemId;
-    // Base Station Id 0..65535
-    private final int mBasestationId;
-    /**
-     * Longitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0.
-     * It is represented in units of 0.25 seconds and ranges from -2592000
-     * to 2592000, both values inclusive (corresponding to a range of -180
-     * to +180 degrees).
-     */
-    private final int mLongitude;
-    /**
-     * Latitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0.
-     * It is represented in units of 0.25 seconds and ranges from -1296000
-     * to 1296000, both values inclusive (corresponding to a range of -90
-     * to +90 degrees).
-     */
-    private final int mLatitude;
-
-    /**
-     * public constructor
-     * @param nid Network Id 0..65535
-     * @param sid CDMA System Id 0..32767
-     * @param bid Base Station Id 0..65535
-     * @param lon Longitude is a decimal number ranges from -2592000
-     *        to 2592000
-     * @param lat Latitude is a decimal number ranges from -1296000
-     *        to 1296000
-     * @param attr is comma separated “key=value” attribute pairs.
-     */
-    public CdmaCellIdentity (int nid, int sid,
-            int bid, int lon, int lat, String attr) {
-        super(CELLID_TYPE_CDMA, attr);
-        mNetworkId = nid;
-        mSystemId = sid;
-        mBasestationId = bid;
-        mLongitude = lon;
-        mLatitude = lat;
-    }
-
-    private CdmaCellIdentity(Parcel in) {
-        super(in);
-        mNetworkId = in.readInt();
-        mSystemId = in.readInt();
-        mBasestationId = in.readInt();
-        mLongitude = in.readInt();
-        mLatitude = in.readInt();
-    }
-
-    CdmaCellIdentity(CdmaCellIdentity cid) {
-        super(cid);
-        mNetworkId = cid.mNetworkId;
-        mSystemId = cid.mSystemId;
-        mBasestationId = cid.mBasestationId;
-        mLongitude = cid.mLongitude;
-        mLatitude = cid.mLatitude;
-    }
-
-    /**
-     * @return Network Id 0..65535
-     */
-    public int getNetworkId() {
-        return mNetworkId;
-    }
-
-    /**
-     * @return System Id 0..32767
-     */
-    public int getSystemId() {
-        return mSystemId;
-    }
-
-    /**
-     * @return Base Station Id 0..65535
-     */
-    public int getBasestationId() {
-        return mBasestationId;
-    }
-
-    /**
-     * @return Base station longitude, which is a decimal number as
-     * specified in 3GPP2 C.S0005-A v6.0. It is represented in units
-     * of 0.25 seconds and ranges from -2592000 to 2592000, both
-     * values inclusive (corresponding to a range of -180
-     * to +180 degrees).
-     */
-    public int getLongitude() {
-        return mLongitude;
-    }
-
-    /**
-     * @return Base station
-     */
-    /**
-     * @return Base station latitude, which is a decimal number as
-     * specified in 3GPP2 C.S0005-A v6.0. It is represented in units
-     * of 0.25 seconds and ranges from -1296000 to 1296000, both
-     * values inclusive (corresponding to a range of -90
-     * to +90 degrees).
-     */
-    public int getLatitude() {
-        return mLatitude;
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        super.writeToParcel(dest, flags);
-        dest.writeInt(mNetworkId);
-        dest.writeInt(mSystemId);
-        dest.writeInt(mBasestationId);
-        dest.writeInt(mLongitude);
-        dest.writeInt(mLatitude);
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    public static final Creator<CdmaCellIdentity> CREATOR =
-            new Creator<CdmaCellIdentity>() {
-        @Override
-        public CdmaCellIdentity createFromParcel(Parcel in) {
-            return new CdmaCellIdentity(in);
-        }
-
-        @Override
-        public CdmaCellIdentity[] newArray(int size) {
-            return new CdmaCellIdentity[size];
-        }
-    };
-}
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index 65c220f..1f4f78e 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2012 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.
@@ -20,70 +20,79 @@
 import android.os.Parcelable;
 
 /**
- * CellIdentity is to represent ONE unique cell in the world
+ * CellIdentity is immutable and represents ONE unique cell in the world
  * it contains all levels of info to identity country, carrier, etc.
  *
- * @hide pending API review
+ * @hide
  */
 public abstract class CellIdentity implements Parcelable {
 
-    // Cell is a GSM Cell {@link GsmCellIdentity}
-    public static final int CELLID_TYPE_GSM = 1;
-    // Cell is a CMDA Cell {@link CdmaCellIdentity}
-    public static final int CELLID_TYPE_CDMA = 2;
-    // Cell is a LTE Cell {@link LteCellIdentity}
-    public static final int CELLID_TYPE_LTE = 3;
+    // Type fields for parceling
+    protected static final int TYPE_GSM = 1;
+    protected static final int TYPE_CDMA = 2;
+    protected static final int TYPE_LTE = 3;
 
-    private int mCellIdType;
-    private String mCellIdAttributes;
-
-    protected CellIdentity(int type, String attr) {
-        this.mCellIdType = type;
-        this.mCellIdAttributes = new String(attr);
+    protected CellIdentity() {
     }
 
     protected CellIdentity(Parcel in) {
-        this.mCellIdType = in.readInt();
-        this.mCellIdAttributes = new String(in.readString());
     }
 
     protected CellIdentity(CellIdentity cid) {
-        this.mCellIdType = cid.mCellIdType;
-        this.mCellIdAttributes = new String(cid.mCellIdAttributes);
     }
 
     /**
-     * @return Cell Identity type as one of CELLID_TYPE_XXXX
+     * @return a copy of this object with package visibility.
      */
-    public int getCellIdType() {
-        return mCellIdType;
+    abstract CellIdentity copy();
+
+    @Override
+    public abstract int hashCode();
+
+    @Override
+    public boolean equals(Object other) {
+        if (other == null) {
+            return false;
+        }
+        if (this == other) {
+            return true;
+        }
+        return (other instanceof CellIdentity);
     }
 
-
-    /**
-     * @return Cell identity attribute pairs
-     * Comma separated “key=value” pairs.
-     *   key := must must an single alpha-numeric word
-     *   value := “quoted value string”
-     *
-     * Current list of keys and values:
-     *   type = fixed | mobile
-     */
-    public String getCellIdAttributes() {
-        return mCellIdAttributes;
+    @Override
+    public String toString() {
+        return "";
     }
 
-
-    /** Implement the Parcelable interface {@hide} */
+    /** Implement the Parcelable interface */
     @Override
     public int describeContents() {
         return 0;
     }
 
-    /** Implement the Parcelable interface {@hide} */
+    /** Implement the Parcelable interface */
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mCellIdType);
-        dest.writeString(mCellIdAttributes);
     }
+
+    /** Implement the Parcelable interface */
+    public static final Creator<CellIdentity> CREATOR =
+            new Creator<CellIdentity>() {
+        @Override
+        public CellIdentity createFromParcel(Parcel in) {
+            int type = in.readInt();
+            switch (type) {
+                case TYPE_GSM: return CellIdentityGsm.createFromParcelBody(in);
+                case TYPE_CDMA: return CellIdentityCdma.createFromParcelBody(in);
+                case TYPE_LTE: return CellIdentityLte.createFromParcelBody(in);
+                default: throw new RuntimeException("Bad CellIdentity Parcel");
+            }
+        }
+
+        @Override
+        public CellIdentity[] newArray(int size) {
+            return new CellIdentity[size];
+        }
+    };
 }
diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java
new file mode 100644
index 0000000..0169d89
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentityCdma.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2012 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * CellIdentity is to represent a unique CDMA cell
+ *
+ * @hide
+ */
+public final class CellIdentityCdma extends CellIdentity implements Parcelable {
+
+    private static final String LOG_TAG = "CellSignalStrengthCdma";
+    private static final boolean DBG = false;
+
+    // Network Id 0..65535
+    private final int mNetworkId;
+    // CDMA System Id 0..32767
+    private final int mSystemId;
+    // Base Station Id 0..65535
+    private final int mBasestationId;
+    /**
+     * Longitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0.
+     * It is represented in units of 0.25 seconds and ranges from -2592000
+     * to 2592000, both values inclusive (corresponding to a range of -180
+     * to +180 degrees).
+     */
+    private final int mLongitude;
+    /**
+     * Latitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0.
+     * It is represented in units of 0.25 seconds and ranges from -1296000
+     * to 1296000, both values inclusive (corresponding to a range of -90
+     * to +90 degrees).
+     */
+    private final int mLatitude;
+
+    /**
+     * @hide
+     */
+    public CellIdentityCdma() {
+        mNetworkId = Integer.MAX_VALUE;
+        mSystemId = Integer.MAX_VALUE;
+        mBasestationId = Integer.MAX_VALUE;
+        mLongitude = Integer.MAX_VALUE;
+        mLatitude = Integer.MAX_VALUE;
+    }
+
+    /**
+     * public constructor
+     * @param nid Network Id 0..65535
+     * @param sid CDMA System Id 0..32767
+     * @param bid Base Station Id 0..65535
+     * @param lon Longitude is a decimal number ranges from -2592000
+     *        to 2592000
+     * @param lat Latitude is a decimal number ranges from -1296000
+     *        to 1296000
+     *
+     * @hide
+     */
+    public CellIdentityCdma (int nid, int sid, int bid, int lon, int lat) {
+        mNetworkId = nid;
+        mSystemId = sid;
+        mBasestationId = bid;
+        mLongitude = lon;
+        mLatitude = lat;
+    }
+
+    private CellIdentityCdma(CellIdentityCdma cid) {
+        super(cid);
+        mNetworkId = cid.mNetworkId;
+        mSystemId = cid.mSystemId;
+        mBasestationId = cid.mBasestationId;
+        mLongitude = cid.mLongitude;
+        mLatitude = cid.mLatitude;
+    }
+
+    @Override
+    CellIdentityCdma copy() {
+        return new CellIdentityCdma(this);
+    }
+
+    /**
+     * @return Network Id 0..65535
+     */
+    public int getNetworkId() {
+        return mNetworkId;
+    }
+
+    /**
+     * @return System Id 0..32767
+     */
+    public int getSystemId() {
+        return mSystemId;
+    }
+
+    /**
+     * @return Base Station Id 0..65535
+     */
+    public int getBasestationId() {
+        return mBasestationId;
+    }
+
+    /**
+     * @return Base station longitude, which is a decimal number as
+     * specified in 3GPP2 C.S0005-A v6.0. It is represented in units
+     * of 0.25 seconds and ranges from -2592000 to 2592000, both
+     * values inclusive (corresponding to a range of -180
+     * to +180 degrees).
+     */
+    public int getLongitude() {
+        return mLongitude;
+    }
+
+    /**
+     * @return Base station latitude, which is a decimal number as
+     * specified in 3GPP2 C.S0005-A v6.0. It is represented in units
+     * of 0.25 seconds and ranges from -1296000 to 1296000, both
+     * values inclusive (corresponding to a range of -90
+     * to +90 degrees).
+     */
+    public int getLatitude() {
+        return mLatitude;
+    }
+
+    @Override
+    public int hashCode() {
+        int primeNum = 31;
+        return (mNetworkId * primeNum) + (mSystemId * primeNum) + (mBasestationId * primeNum) +
+                (mLatitude * primeNum) + (mLongitude * primeNum);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (super.equals(other)) {
+            try {
+                CellIdentityCdma o = (CellIdentityCdma)other;
+                return mNetworkId == o.mNetworkId &&
+                        mSystemId == o.mSystemId &&
+                        mBasestationId == o.mBasestationId &&
+                        mLatitude == o.mLatitude &&
+                        mLongitude == o.mLongitude;
+            } catch (ClassCastException e) {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder("CdmaCellIdentitiy:");
+        sb.append(super.toString());
+        sb.append(" mNetworkId="); sb.append(mNetworkId);
+        sb.append(" mSystemId="); sb.append(mSystemId);
+        sb.append(" mBasestationId="); sb.append(mBasestationId);
+        sb.append(" mLongitude="); sb.append(mLongitude);
+        sb.append(" mLatitude="); sb.append(mLatitude);
+
+        return sb.toString();
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        if (DBG) log("writeToParcel(Parcel, int): " + toString());
+        dest.writeInt(TYPE_CDMA);
+        super.writeToParcel(dest, flags);
+        dest.writeInt(mNetworkId);
+        dest.writeInt(mSystemId);
+        dest.writeInt(mBasestationId);
+        dest.writeInt(mLongitude);
+        dest.writeInt(mLatitude);
+    }
+
+    /** Construct from Parcel, type has already been processed */
+    private CellIdentityCdma(Parcel in) {
+        super(in);
+        mNetworkId = in.readInt();
+        mSystemId = in.readInt();
+        mBasestationId = in.readInt();
+        mLongitude = in.readInt();
+        mLatitude = in.readInt();
+        if (DBG) log("CellIdentityCdma(Parcel): " + toString());
+    }
+
+    /** Implement the Parcelable interface */
+    @SuppressWarnings("hiding")
+    public static final Creator<CellIdentityCdma> CREATOR =
+            new Creator<CellIdentityCdma>() {
+        @Override
+        public CellIdentityCdma createFromParcel(Parcel in) {
+            in.readInt(); // Skip past token, we know what it is
+            return createFromParcelBody(in);
+        }
+
+        @Override
+        public CellIdentityCdma[] newArray(int size) {
+            return new CellIdentityCdma[size];
+        }
+    };
+
+    /** @hide */
+    static CellIdentityCdma createFromParcelBody(Parcel in) {
+        return new CellIdentityCdma(in);
+    }
+
+    /**
+     * log
+     */
+    private static void log(String s) {
+        Log.w(LOG_TAG, s);
+    }
+}
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
new file mode 100644
index 0000000..f46cd47
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2012 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * CellIdentity to represent a unique GSM or UMTS cell
+ *
+ * @hide
+ */
+public final class CellIdentityGsm extends CellIdentity implements Parcelable {
+
+    private static final String LOG_TAG = "CellIdentityGsm";
+    private static final boolean DBG = false;
+
+    // 3-digit Mobile Country Code, 0..999
+    private final int mMcc;
+    // 2 or 3-digit Mobile Network Code, 0..999
+    private final int mMnc;
+    // 16-bit Location Area Code, 0..65535
+    private final int mLac;
+    // 16-bit GSM Cell Identity described in TS 27.007, 0..65535
+    // 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455
+    private final int mCid;
+    // 9-bit UMTS Primary Scrambling Code described in TS 25.331, 0..511
+    private final int mPsc;
+
+    /**
+     * @hide
+     */
+    public CellIdentityGsm() {
+        mMcc = Integer.MAX_VALUE;
+        mMnc = Integer.MAX_VALUE;
+        mLac = Integer.MAX_VALUE;
+        mCid = Integer.MAX_VALUE;
+        mPsc = Integer.MAX_VALUE;
+    }
+    /**
+     * public constructor
+     * @param mcc 3-digit Mobile Country Code, 0..999
+     * @param mnc 2 or 3-digit Mobile Network Code, 0..999
+     * @param lac 16-bit Location Area Code, 0..65535
+     * @param cid 16-bit GSM Cell Identity or 28-bit UMTS Cell Identity
+     * @param psc 9-bit UMTS Primary Scrambling Code
+     *
+     * @hide
+     */
+    public CellIdentityGsm (int mcc, int mnc, int lac, int cid, int psc) {
+        mMcc = mcc;
+        mMnc = mnc;
+        mLac = lac;
+        mCid = cid;
+        mPsc = psc;
+    }
+
+    private CellIdentityGsm(CellIdentityGsm cid) {
+        super(cid);
+        mMcc = cid.mMcc;
+        mMnc = cid.mMnc;
+        mLac = cid.mLac;
+        mCid = cid.mCid;
+        mPsc = cid.mPsc;
+    }
+
+    @Override
+    CellIdentityGsm copy() {
+       return new CellIdentityGsm(this);
+    }
+
+    /**
+     * @return 3-digit Mobile Country Code, 0..999
+     */
+    public int getMcc() {
+        return mMcc;
+    }
+
+    /**
+     * @return 2 or 3-digit Mobile Network Code, 0..999
+     */
+    public int getMnc() {
+        return mMnc;
+    }
+
+    /**
+     * @return 16-bit Location Area Code, 0..65535
+     */
+    public int getLac() {
+        return mLac;
+    }
+
+    /**
+     * @return CID
+     * Either 16-bit GSM Cell Identity described
+     * in TS 27.007, 0..65535
+     * or 28-bit UMTS Cell Identity described
+     * in TS 25.331, 0..268435455
+     */
+    public int getCid() {
+        return mCid;
+    }
+
+    /**
+     * @return 9-bit UMTS Primary Scrambling Code described in
+     * TS 25.331, 0..511
+     */
+    public int getPsc() {
+        return mPsc;
+    }
+
+    @Override
+    public int hashCode() {
+        int primeNum = 31;
+        return (mMcc * primeNum) + (mMnc * primeNum) + (mLac * primeNum) + (mCid * primeNum) +
+                (mPsc * primeNum);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (super.equals(other)) {
+            try {
+                CellIdentityGsm o = (CellIdentityGsm)other;
+                return mMcc == o.mMcc &&
+                        mMnc == o.mMnc &&
+                        mLac == o.mLac &&
+                        mCid == o.mCid &&
+                        mPsc == o.mPsc;
+            } catch (ClassCastException e) {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder("GsmCellIdentitiy:");
+        sb.append(super.toString());
+        sb.append(" mMcc=").append(mMcc);
+        sb.append(" mMnc=").append(mMcc);
+        sb.append(" mLac=").append(mLac);
+        sb.append(" mCid=").append(mCid);
+        sb.append(" mPsc=").append(mPsc);
+
+        return sb.toString();
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        if (DBG) log("writeToParcel(Parcel, int): " + toString());
+        dest.writeInt(TYPE_GSM);
+        super.writeToParcel(dest, flags);
+        dest.writeInt(mMcc);
+        dest.writeInt(mMnc);
+        dest.writeInt(mLac);
+        dest.writeInt(mCid);
+        dest.writeInt(mPsc);
+    }
+
+    /** Construct from Parcel, type has already been processed */
+    private CellIdentityGsm(Parcel in) {
+        super(in);
+        mMcc = in.readInt();
+        mMnc = in.readInt();
+        mLac = in.readInt();
+        mCid = in.readInt();
+        mPsc = in.readInt();
+        if (DBG) log("CellIdentityGsm(Parcel): " + toString());
+    }
+
+    /** Implement the Parcelable interface */
+    @SuppressWarnings("hiding")
+    public static final Creator<CellIdentityGsm> CREATOR =
+            new Creator<CellIdentityGsm>() {
+        @Override
+        public CellIdentityGsm createFromParcel(Parcel in) {
+            in.readInt(); // Skip past token, we know what it is
+            return createFromParcelBody(in);
+        }
+
+        @Override
+        public CellIdentityGsm[] newArray(int size) {
+            return new CellIdentityGsm[size];
+        }
+    };
+
+    /** @hide */
+    static CellIdentityGsm createFromParcelBody(Parcel in) {
+        return new CellIdentityGsm(in);
+    }
+
+    /**
+     * log
+     */
+    private static void log(String s) {
+        Log.w(LOG_TAG, s);
+    }
+}
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
new file mode 100644
index 0000000..3d8532d
--- /dev/null
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2012 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * CellIdentity is to represent a unique LTE cell
+ *
+ * @hide
+ */
+public final class CellIdentityLte extends CellIdentity implements Parcelable {
+
+    private static final String LOG_TAG = "CellIdentityLte";
+    private static final boolean DBG = false;
+
+    // 3-digit Mobile Country Code, 0..999
+    private final int mMcc;
+    // 2 or 3-digit Mobile Network Code, 0..999
+    private final int mMnc;
+    // 28-bit cell identity
+    private final int mCi;
+    // physical cell id 0..503
+    private final int mPci;
+    // 16-bit tracking area code
+    private final int mTac;
+
+    /**
+     * @hide
+     */
+    public CellIdentityLte() {
+        mMcc = Integer.MAX_VALUE;
+        mMnc = Integer.MAX_VALUE;
+        mCi = Integer.MAX_VALUE;
+        mPci = Integer.MAX_VALUE;
+        mTac = Integer.MAX_VALUE;
+    }
+
+    /**
+     *
+     * @param mcc 3-digit Mobile Country Code, 0..999
+     * @param mnc 2 or 3-digit Mobile Network Code, 0..999
+     * @param ci 28-bit Cell Identity
+     * @param pci Physical Cell Id 0..503
+     * @param tac 16-bit Tracking Area Code
+     *
+     * @hide
+     */
+    public CellIdentityLte (int mcc, int mnc, int ci, int pci, int tac) {
+        mMcc = mcc;
+        mMnc = mnc;
+        mCi = ci;
+        mPci = pci;
+        mTac = tac;
+    }
+
+    private CellIdentityLte(CellIdentityLte cid) {
+        super(cid);
+        mMcc = cid.mMcc;
+        mMnc = cid.mMnc;
+        mCi = cid.mCi;
+        mPci = cid.mPci;
+        mTac = cid.mTac;
+    }
+
+    @Override
+    CellIdentityLte copy() {
+        return new CellIdentityLte(this);
+    }
+
+    /**
+     * @return 3-digit Mobile Country Code, 0..999
+     */
+    public int getMcc() {
+        return mMcc;
+    }
+
+    /**
+     * @return 2 or 3-digit Mobile Network Code, 0..999
+     */
+    public int getMnc() {
+        return mMnc;
+    }
+
+    /**
+     * @return 28-bit Cell Identity
+     */
+    public int getCi() {
+        return mCi;
+    }
+
+    /**
+     * @return Physical Cell Id 0..503
+     */
+    public int getPci() {
+        return mPci;
+    }
+
+    /**
+     * @return 16-bit Tracking Area Code
+     */
+    public int getTac() {
+        return mTac;
+    }
+
+    @Override
+    public int hashCode() {
+        int primeNum = 31;
+        return (mMcc * primeNum) + (mMnc * primeNum) + (mCi * primeNum) + (mPci * primeNum) +
+                (mTac * primeNum);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (super.equals(other)) {
+            try {
+                CellIdentityLte o = (CellIdentityLte)other;
+                return mMcc == o.mMcc &&
+                        mMnc == o.mMnc &&
+                        mCi == o.mCi &&
+                        mPci == o.mCi &&
+                        mTac == o.mTac;
+            } catch (ClassCastException e) {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder("LteCellIdentitiy:");
+        sb.append(super.toString());
+        sb.append(" mMcc="); sb.append(mMcc);
+        sb.append(" mMnc="); sb.append(mMnc);
+        sb.append(" mCi="); sb.append(mCi);
+        sb.append(" mPci="); sb.append(mPci);
+        sb.append(" mTac="); sb.append(mTac);
+
+        return sb.toString();
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        if (DBG) log("writeToParcel(Parcel, int): " + toString());
+        dest.writeInt(TYPE_LTE);
+        super.writeToParcel(dest, flags);
+        dest.writeInt(mMcc);
+        dest.writeInt(mMnc);
+        dest.writeInt(mCi);
+        dest.writeInt(mPci);
+        dest.writeInt(mTac);
+    }
+
+    /** Construct from Parcel, type has already been processed */
+    private CellIdentityLte(Parcel in) {
+        super(in);
+        mMcc = in.readInt();
+        mMnc = in.readInt();
+        mCi = in.readInt();
+        mPci = in.readInt();
+        mTac = in.readInt();
+        if (DBG) log("CellIdentityLte(Parcel): " + toString());
+    }
+
+    /** Implement the Parcelable interface */
+    @SuppressWarnings("hiding")
+    public static final Creator<CellIdentityLte> CREATOR =
+            new Creator<CellIdentityLte>() {
+        @Override
+        public CellIdentityLte createFromParcel(Parcel in) {
+            in.readInt(); // Skip past token, we know what it is
+            return createFromParcelBody(in);
+        }
+
+        @Override
+        public CellIdentityLte[] newArray(int size) {
+            return new CellIdentityLte[size];
+        }
+    };
+
+    /** @hide */
+    static CellIdentityLte createFromParcelBody(Parcel in) {
+        return new CellIdentityLte(in);
+    }
+
+    /**
+     * log
+     */
+    private static void log(String s) {
+        Log.w(LOG_TAG, s);
+    }
+}
diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java
index 9bea30c..5fdf7c0 100644
--- a/telephony/java/android/telephony/CellInfo.java
+++ b/telephony/java/android/telephony/CellInfo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2012 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.
@@ -20,194 +20,171 @@
 import android.os.Parcelable;
 
 /**
- * Represent one snapshot observation of one cell info
- * which contains the time of observation.
+ * Immutable cell information from a point in time.
  *
- * @hide Pending API review
+ * @hide
  */
-public final class CellInfo implements Parcelable {
+public class CellInfo implements Parcelable {
+
+    // Type fields for parceling
+    protected static final int TYPE_GSM = 1;
+    protected static final int TYPE_CDMA = 2;
+    protected static final int TYPE_LTE = 3;
+
     // Type to distinguish where time stamp gets recorded.
-    public static final int CELL_INFO_TIMESTAMP_TYPE_UNKNOWN = 0;
-    public static final int CELL_INFO_TIMESTAMP_TYPE_ANTENNA = 1;
-    public static final int CELL_INFO_TIMESTAMP_TYPE_MODEM = 2;
-    public static final int CELL_INFO_TIMESTAMP_TYPE_OEM_RIL = 3;
-    public static final int CELL_INFO_TIMESTAMP_TYPE_JAVA_RIL = 4;
+
+    /** @hide */
+    public static final int TIMESTAMP_TYPE_UNKNOWN = 0;
+    /** @hide */
+    public static final int TIMESTAMP_TYPE_ANTENNA = 1;
+    /** @hide */
+    public static final int TIMESTAMP_TYPE_MODEM = 2;
+    /** @hide */
+    public static final int TIMESTAMP_TYPE_OEM_RIL = 3;
+    /** @hide */
+    public static final int TIMESTAMP_TYPE_JAVA_RIL = 4;
+
+    // True if device is mRegistered to the mobile network
+    private boolean mRegistered;
 
     // Observation time stamped as type in nanoseconds since boot
-    private final long mTimeStamp;
+    private long mTimeStamp;
+
     // Where time stamp gets recorded.
-    // Value of CELL_INFO_TIMESTAMP_TYPE_XXXX
-    private final int mTimeStampType;
+    // Value of TIMESTAMP_TYPE_XXXX
+    private int mTimeStampType;
 
-    private final boolean mRegistered;
-
-    private final SignalStrength mStrength;
-    private final long mTimingAdvance;
-
-    private final int mCellIdentityType;
-    private final CellIdentity mCellIdentity;
-
-    /**
-     * Public constructor
-     * @param timeStampType is one of CELL_INFO_TIMESTAMP_TYPE_XXXX
-     * @param timeStamp is observation time in nanoseconds since boot
-     * @param timingAdv is observed timing advance
-     * @param registered is true when register to this cellIdentity
-     * @param strength is observed signal strength
-     * @param cellIdentity is observed mobile cell
-     */
-    public CellInfo(int timeStampType, long timeStamp, long timingAdv,
-            boolean registered, SignalStrength strength,
-            CellIdentity cellIdentity) {
-
-        if (timeStampType < CELL_INFO_TIMESTAMP_TYPE_UNKNOWN ||
-                timeStampType > CELL_INFO_TIMESTAMP_TYPE_JAVA_RIL) {
-            mTimeStampType = CELL_INFO_TIMESTAMP_TYPE_UNKNOWN;
-        } else {
-            mTimeStampType = timeStampType;
-        }
-
-        mRegistered = registered;
-        mTimeStamp = timeStamp;
-        mTimingAdvance = timingAdv;
-        mStrength = new SignalStrength(strength);
-
-        mCellIdentityType = cellIdentity.getCellIdType();
-        // TODO: make defense copy
-        mCellIdentity = cellIdentity;
+    protected CellInfo() {
+        this.mRegistered = false;
+        this.mTimeStampType = TIMESTAMP_TYPE_UNKNOWN;
+        this.mTimeStamp = Long.MAX_VALUE;
     }
 
-    public CellInfo(CellInfo ci) {
-        this.mTimeStampType = ci.mTimeStampType;
+    protected CellInfo(CellInfo ci) {
         this.mRegistered = ci.mRegistered;
+        this.mTimeStampType = ci.mTimeStampType;
         this.mTimeStamp = ci.mTimeStamp;
-        this.mTimingAdvance = ci.mTimingAdvance;
-        this.mCellIdentityType = ci.mCellIdentityType;
-        this.mStrength = new SignalStrength(ci.mStrength);
-        switch(mCellIdentityType) {
-            case CellIdentity.CELLID_TYPE_GSM:
-                mCellIdentity = new GsmCellIdentity((GsmCellIdentity)ci.mCellIdentity);
-                break;
-            default:
-                mCellIdentity = null;
-        }
     }
 
-    private CellInfo(Parcel in) {
-        mTimeStampType = in.readInt();
-        mRegistered = (in.readInt() == 1) ? true : false;
-        mTimeStamp = in.readLong();
-        mTimingAdvance = in.readLong();
-        mCellIdentityType = in.readInt();
-        mStrength = SignalStrength.CREATOR.createFromParcel(in);
-        switch(mCellIdentityType) {
-            case CellIdentity.CELLID_TYPE_GSM:
-                mCellIdentity = GsmCellIdentity.CREATOR.createFromParcel(in);
-                break;
-            default:
-                mCellIdentity = null;
-        }
+    /** True if this cell is registered to the mobile network */
+    public boolean isRegistered() {
+        return mRegistered;
+    }
+    /** @hide */
+    public void setRegisterd(boolean registered) {
+        mRegistered = registered;
     }
 
-    /**
-     * @return the observation time in nanoseconds since boot
-     */
+    /** Approximate time of this cell information in nanos since boot */
     public long getTimeStamp() {
         return mTimeStamp;
     }
+    /** @hide */
+    public void setTimeStamp(long timeStamp) {
+        mTimeStamp = timeStamp;
+    }
 
     /**
-     * @return Where time stamp gets recorded.
-     * one of CELL_INFO_TIMESTAMP_TYPE_XXXX
+     * Where time stamp gets recorded.
+     * @return one of TIMESTAMP_TYPE_XXXX
+     *
+     * @hide
      */
     public int getTimeStampType() {
         return mTimeStampType;
     }
-
-    /**
-     * @return true when register to this cellIdentity
-     */
-    public boolean isRegistered() {
-        return mRegistered;
+    /** @hide */
+    public void setTimeStampType(int timeStampType) {
+        if (timeStampType < TIMESTAMP_TYPE_UNKNOWN || timeStampType > TIMESTAMP_TYPE_JAVA_RIL) {
+            mTimeStampType = TIMESTAMP_TYPE_UNKNOWN;
+        } else {
+            mTimeStampType = timeStampType;
+        }
     }
 
-    /**
-     * @return observed timing advance
-     */
-    public long getTimingAdvance() {
-        return mTimingAdvance;
+    @Override
+    public int hashCode() {
+        int primeNum = 31;
+        return ((mRegistered ? 0 : 1) * primeNum) + ((int)(mTimeStamp / 1000) * primeNum)
+                + (mTimeStampType * primeNum);
     }
 
-    /**
-     * @return observed signal strength
-     */
-    public SignalStrength getSignalStrength() {
-        // make a defense copy
-        return new SignalStrength(mStrength);
+    @Override
+    public boolean equals(Object other) {
+        if (other == null) {
+            return false;
+        }
+        if (this == other) {
+            return true;
+        }
+        try {
+            CellInfo o = (CellInfo) other;
+            return mRegistered == o.mRegistered
+                    && mTimeStamp == o.mTimeStamp && mTimeStampType == o.mTimeStampType;
+        } catch (ClassCastException e) {
+            return false;
+        }
     }
 
-    /**
-     * @return observed cell identity
-     */
-    public CellIdentity getCellIdentity() {
-        // TODO: make a defense copy
-        return mCellIdentity;
+    private static String timeStampTypeToString(int type) {
+        switch (type) {
+            case 1:
+                return "antenna";
+            case 2:
+                return "modem";
+            case 3:
+                return "oem_ril";
+            case 4:
+                return "java_ril";
+            default:
+                return "unknown";
+        }
     }
 
     @Override
     public String toString() {
         StringBuffer sb = new StringBuffer();
+        String timeStampType;
 
-        sb.append("TimeStampType: ");
-        switch(mTimeStampType) {
-            case 1:
-                sb.append("antenna");
-                break;
-            case 2:
-                sb.append("modem");
-                break;
-            case 3:
-                sb.append("oem_ril");
-                break;
-            case 4:
-                sb.append("java_ril");
-                break;
-            default:
-                sb.append("unknown");
-        }
-        sb.append(", TimeStamp: ").append(mTimeStamp).append(" ns");
-        sb.append(", Registered: ").append(mRegistered ? "YES" : "NO");
-        sb.append(", TimingAdvance: ").append(mTimingAdvance);
-        sb.append(", Strength : " + mStrength);
-        sb.append(", Cell Iden: " + mCellIdentity);
+        sb.append(" mRegistered=").append(mRegistered ? "YES" : "NO");
+        timeStampType = timeStampTypeToString(mTimeStampType);
+        sb.append(" mTimeStampType=").append(timeStampType);
+        sb.append(" mTimeStamp=").append(mTimeStamp).append("ns");
 
         return sb.toString();
     }
 
-    /** Implement the Parcelable interface {@hide} */
+    /** Implement the Parcelable interface */
     @Override
     public int describeContents() {
         return 0;
     }
 
-    /** Implement the Parcelable interface {@hide} */
+    /** Implement the Parcelable interface */
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mTimeStampType);
         dest.writeInt(mRegistered ? 1 : 0);
+        dest.writeInt(mTimeStampType);
         dest.writeLong(mTimeStamp);
-        dest.writeLong(mTimingAdvance);
-        dest.writeInt(mCellIdentityType);
-        mStrength.writeToParcel(dest, flags);
-        mCellIdentity.writeToParcel(dest, flags);
     }
 
-    /** Implement the Parcelable interface {@hide} */
-    public static final Creator<CellInfo> CREATOR =
-            new Creator<CellInfo>() {
+    protected CellInfo(Parcel in) {
+        mRegistered = (in.readInt() == 1) ? true : false;
+        mTimeStampType = in.readInt();
+        mTimeStamp = in.readLong();
+    }
+
+    /** Implement the Parcelable interface */
+    public static final Creator<CellInfo> CREATOR = new Creator<CellInfo>() {
         @Override
         public CellInfo createFromParcel(Parcel in) {
-            return new CellInfo(in);
+                int type = in.readInt();
+                switch (type) {
+                    case TYPE_GSM: return CellInfoGsm.createFromParcelBody(in);
+                    case TYPE_CDMA: return CellInfoCdma.createFromParcelBody(in);
+                    case TYPE_LTE: return CellInfoLte.createFromParcelBody(in);
+                    default: throw new RuntimeException("Bad CellInfo Parcel");
+                }
         }
 
         @Override
diff --git a/telephony/java/android/telephony/CellInfoCdma.java b/telephony/java/android/telephony/CellInfoCdma.java
new file mode 100644
index 0000000..84c1560
--- /dev/null
+++ b/telephony/java/android/telephony/CellInfoCdma.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2012 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * Immutable cell information from a point in time.
+ *
+ * @hide
+ */
+public final class CellInfoCdma extends CellInfo implements Parcelable {
+
+    private static final String LOG_TAG = "CellInfoCdma";
+    private static final boolean DBG = false;
+
+    private CellIdentityCdma mCellIdentityCdma;
+    private CellSignalStrengthCdma mCellSignalStrengthCdma;
+
+    /** @hide */
+    public CellInfoCdma() {
+        super();
+        mCellIdentityCdma = new CellIdentityCdma();
+        mCellSignalStrengthCdma = new CellSignalStrengthCdma();
+    }
+
+    /** @hide */
+    public CellInfoCdma(CellInfoCdma ci) {
+        super(ci);
+        this.mCellIdentityCdma = ci.mCellIdentityCdma.copy();
+        this.mCellSignalStrengthCdma = ci.mCellSignalStrengthCdma.copy();
+    }
+
+    public CellIdentityCdma getCellIdentity() {
+        return mCellIdentityCdma;
+    }
+    /** @hide */
+    public void setCellIdentity(CellIdentityCdma cid) {
+        mCellIdentityCdma = cid;
+    }
+
+    public CellSignalStrengthCdma getCellSignalStrength() {
+        return mCellSignalStrengthCdma;
+    }
+    /** @hide */
+    public void setCellSignalStrength(CellSignalStrengthCdma css) {
+        mCellSignalStrengthCdma = css;
+    }
+
+    /**
+     * @return hash code
+     */
+    @Override
+    public int hashCode() {
+        return super.hashCode() + mCellIdentityCdma.hashCode() + mCellSignalStrengthCdma.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!super.equals(other)) {
+            return false;
+        }
+        try {
+            CellInfoCdma o = (CellInfoCdma) other;
+            return mCellIdentityCdma.equals(o.mCellIdentityCdma)
+                    && mCellSignalStrengthCdma.equals(o.mCellSignalStrengthCdma);
+        } catch (ClassCastException e) {
+            return false;
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+
+        sb.append("CellInfoCdma:");
+        sb.append(super.toString());
+        sb.append(", ").append(mCellIdentityCdma);
+        sb.append(", ").append(mCellSignalStrengthCdma);
+
+        return sb.toString();
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        if (DBG) log("writeToParcel(Parcel, int): " + toString());
+        dest.writeInt(TYPE_LTE);
+        super.writeToParcel(dest, flags);
+        mCellIdentityCdma.writeToParcel(dest, flags);
+        mCellSignalStrengthCdma.writeToParcel(dest, flags);
+    }
+
+    /**
+     * Construct a CellInfoCdma object from the given parcel
+     * where the token is already been processed.
+     */
+    private CellInfoCdma(Parcel in) {
+        super(in);
+        mCellIdentityCdma = CellIdentityCdma.CREATOR.createFromParcel(in);
+        mCellSignalStrengthCdma = CellSignalStrengthCdma.CREATOR.createFromParcel(in);
+        if (DBG) log("CellInfoCdma(Parcel): " + toString());
+    }
+
+    /** Implement the Parcelable interface */
+    public static final Creator<CellInfoCdma> CREATOR = new Creator<CellInfoCdma>() {
+        @Override
+        public CellInfoCdma createFromParcel(Parcel in) {
+            in.readInt(); // Skip past token, we know what it is
+            return createFromParcelBody(in);
+        }
+
+        @Override
+        public CellInfoCdma[] newArray(int size) {
+            return new CellInfoCdma[size];
+        }
+    };
+
+    /** @hide */
+    protected static CellInfoCdma createFromParcelBody(Parcel in) {
+        return new CellInfoCdma(in);
+    }
+
+    /**
+     * log
+     */
+    private static void log(String s) {
+        Log.w(LOG_TAG, s);
+    }
+}
diff --git a/telephony/java/android/telephony/CellInfoGsm.java b/telephony/java/android/telephony/CellInfoGsm.java
new file mode 100644
index 0000000..f913569
--- /dev/null
+++ b/telephony/java/android/telephony/CellInfoGsm.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2012 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * Immutable cell information from a point in time.
+ *
+ * @hide
+ */
+public final class CellInfoGsm extends CellInfo implements Parcelable {
+
+    private static final String LOG_TAG = "CellInfoGsm";
+    private static final boolean DBG = false;
+
+    private CellIdentityGsm mCellIdentityGsm;
+    private CellSignalStrengthGsm mCellSignalStrengthGsm;
+
+    /** @hide */
+    public CellInfoGsm() {
+        super();
+        mCellIdentityGsm = new CellIdentityGsm();
+        mCellSignalStrengthGsm = new CellSignalStrengthGsm();
+    }
+
+    /** @hide */
+    public CellInfoGsm(CellInfoGsm ci) {
+        super(ci);
+        this.mCellIdentityGsm = ci.mCellIdentityGsm.copy();
+        this.mCellSignalStrengthGsm = ci.mCellSignalStrengthGsm.copy();
+    }
+
+    public CellIdentityGsm getCellIdentity() {
+        return mCellIdentityGsm;
+    }
+    /** @hide */
+    public void setCellIdentity(CellIdentityGsm cid) {
+        mCellIdentityGsm = cid;
+    }
+
+    public CellSignalStrengthGsm getCellSignalStrength() {
+        return mCellSignalStrengthGsm;
+    }
+    /** @hide */
+    public void setCellSignalStrength(CellSignalStrengthGsm css) {
+        mCellSignalStrengthGsm = css;
+    }
+
+    /**
+     * @return hash code
+     */
+    @Override
+    public int hashCode() {
+        return super.hashCode() + mCellIdentityGsm.hashCode() + mCellSignalStrengthGsm.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!super.equals(other)) {
+            return false;
+        }
+        try {
+            CellInfoGsm o = (CellInfoGsm) other;
+            return mCellIdentityGsm.equals(o.mCellIdentityGsm)
+                    && mCellSignalStrengthGsm.equals(o.mCellSignalStrengthGsm);
+        } catch (ClassCastException e) {
+            return false;
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+
+        sb.append("CellInfoGsm:");
+        sb.append(super.toString());
+        sb.append(", ").append(mCellIdentityGsm);
+        sb.append(", ").append(mCellSignalStrengthGsm);
+
+        return sb.toString();
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(TYPE_LTE);
+        super.writeToParcel(dest, flags);
+        mCellIdentityGsm.writeToParcel(dest, flags);
+        mCellSignalStrengthGsm.writeToParcel(dest, flags);
+    }
+
+    /**
+     * Construct a CellInfoGsm object from the given parcel
+     * where the token is already been processed.
+     */
+    private CellInfoGsm(Parcel in) {
+        super(in);
+        mCellIdentityGsm = CellIdentityGsm.CREATOR.createFromParcel(in);
+        mCellSignalStrengthGsm = CellSignalStrengthGsm.CREATOR.createFromParcel(in);
+    }
+
+    /** Implement the Parcelable interface */
+    public static final Creator<CellInfoGsm> CREATOR = new Creator<CellInfoGsm>() {
+        @Override
+        public CellInfoGsm createFromParcel(Parcel in) {
+            in.readInt(); // Skip past token, we know what it is
+            return createFromParcelBody(in);
+        }
+
+        @Override
+        public CellInfoGsm[] newArray(int size) {
+            return new CellInfoGsm[size];
+        }
+    };
+
+    /** @hide */
+    protected static CellInfoGsm createFromParcelBody(Parcel in) {
+        return new CellInfoGsm(in);
+    }
+
+    /**
+     * log
+     */
+    private static void log(String s) {
+        Log.w(LOG_TAG, s);
+    }
+}
diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java
new file mode 100644
index 0000000..57b0402
--- /dev/null
+++ b/telephony/java/android/telephony/CellInfoLte.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2012 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * Immutable cell information from a point in time.
+ *
+ * @hide
+ */
+public final class CellInfoLte extends CellInfo implements Parcelable {
+
+    private static final String LOG_TAG = "CellInfoLte";
+    private static final boolean DBG = false;
+
+    private CellIdentityLte mCellIdentityLte;
+    private CellSignalStrengthLte mCellSignalStrengthLte;
+
+    /** @hide */
+    public CellInfoLte() {
+        super();
+        mCellIdentityLte = new CellIdentityLte();
+        mCellSignalStrengthLte = new CellSignalStrengthLte();
+    }
+
+    /** @hide */
+    public CellInfoLte(CellInfoLte ci) {
+        super(ci);
+        this.mCellIdentityLte = ci.mCellIdentityLte.copy();
+        this.mCellSignalStrengthLte = ci.mCellSignalStrengthLte.copy();
+    }
+
+    public CellIdentityLte getCellIdentity() {
+        return mCellIdentityLte;
+    }
+    /** @hide */
+    public void setCellIdentity(CellIdentityLte cid) {
+        mCellIdentityLte = cid;
+    }
+
+    public CellSignalStrengthLte getCellSignalStrength() {
+        return mCellSignalStrengthLte;
+    }
+    /** @hide */
+    public void setCellSignalStrength(CellSignalStrengthLte css) {
+        mCellSignalStrengthLte = css;
+    }
+
+    /**
+     * @return hash code
+     */
+    @Override
+    public int hashCode() {
+        return super.hashCode() + mCellIdentityLte.hashCode() + mCellSignalStrengthLte.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!super.equals(other)) {
+            return false;
+        }
+        try {
+            CellInfoLte o = (CellInfoLte) other;
+            return mCellIdentityLte.equals(o.mCellIdentityLte)
+                    && mCellSignalStrengthLte.equals(o.mCellSignalStrengthLte);
+        } catch (ClassCastException e) {
+            return false;
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+
+        sb.append("CellInfoLte:");
+        sb.append(super.toString());
+        sb.append(", ").append(mCellIdentityLte);
+        sb.append(", ").append(mCellSignalStrengthLte);
+
+        return sb.toString();
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        if (DBG) log("writeToParcel(Parcel, int): " + toString());
+        dest.writeInt(TYPE_LTE);
+        super.writeToParcel(dest, flags);
+        mCellIdentityLte.writeToParcel(dest, flags);
+        mCellSignalStrengthLte.writeToParcel(dest, flags);
+    }
+
+    /**
+     * Construct a CellInfoLte object from the given parcel
+     * where the TYPE_LTE token is already been processed.
+     */
+    private CellInfoLte(Parcel in) {
+        super(in);
+        mCellIdentityLte = CellIdentityLte.CREATOR.createFromParcel(in);
+        mCellSignalStrengthLte = CellSignalStrengthLte.CREATOR.createFromParcel(in);
+        if (DBG) log("CellInfoLte(Parcel): " + toString());
+    }
+
+    /** Implement the Parcelable interface */
+    public static final Creator<CellInfoLte> CREATOR = new Creator<CellInfoLte>() {
+        @Override
+        public CellInfoLte createFromParcel(Parcel in) {
+            in.readInt(); // Skip past token, we know what it is
+            return createFromParcelBody(in);
+        }
+
+        @Override
+        public CellInfoLte[] newArray(int size) {
+            return new CellInfoLte[size];
+        }
+    };
+
+    /** @hide */
+    protected static CellInfoLte createFromParcelBody(Parcel in) {
+        return new CellInfoLte(in);
+    }
+
+    /**
+     * log
+     */
+    private static void log(String s) {
+        Log.w(LOG_TAG, s);
+    }
+}
diff --git a/telephony/java/android/telephony/CellSignalStrength.java b/telephony/java/android/telephony/CellSignalStrength.java
new file mode 100644
index 0000000..4ed7dcf
--- /dev/null
+++ b/telephony/java/android/telephony/CellSignalStrength.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2012 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.InputEvent;
+
+/**
+ * Abstract base class for cell phone signal strength related information.
+ *
+ * @hide
+ */
+public abstract class CellSignalStrength implements Parcelable {
+
+    // Type fields for parceling
+    protected static final int TYPE_GSM = 1;
+    protected static final int TYPE_CDMA = 2;
+    protected static final int TYPE_LTE = 3;
+
+
+    /** @hide */
+    public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0;
+    /** @hide */
+    public static final int SIGNAL_STRENGTH_POOR = 1;
+    /** @hide */
+    public static final int SIGNAL_STRENGTH_MODERATE = 2;
+    /** @hide */
+    public static final int SIGNAL_STRENGTH_GOOD = 3;
+    /** @hide */
+    public static final int SIGNAL_STRENGTH_GREAT = 4;
+    /** @hide */
+    public static final int NUM_SIGNAL_STRENGTH_BINS = 5;
+    /** @hide */
+    public static final String[] SIGNAL_STRENGTH_NAMES = {
+        "none", "poor", "moderate", "good", "great"
+    };
+
+    /** @hide */
+    public abstract void setDefaultValues();
+
+    /**
+     * Get signal level as an int from 0..4
+     *
+     * @hide
+     */
+    public abstract int getLevel();
+
+    /**
+     * Get the signal level as an asu value between 0..31, 99 is unknown
+     *
+     * @hide
+     */
+    public abstract int getAsuLevel();
+
+    /**
+     * Get the signal strength as dBm
+     *
+     * @hide
+     */
+    public abstract int getDbm();
+
+    /**
+     * Copies the CellSignalStrength.
+     *
+     * @return A deep copy of this class.
+     * @hide
+     */
+    public abstract CellSignalStrength copy();
+
+    @Override
+    public abstract int hashCode();
+
+    @Override
+    public abstract boolean equals (Object o);
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public abstract void writeToParcel(Parcel dest, int flags);
+
+    /** Implement the Parcelable interface */
+    public static final Creator<CellSignalStrength> CREATOR =
+            new Creator<CellSignalStrength>() {
+        @Override
+        public CellSignalStrength createFromParcel(Parcel in) {
+            int type = in.readInt();
+            switch (type) {
+                case TYPE_GSM: return CellSignalStrengthGsm.createFromParcelBody(in);
+                case TYPE_CDMA: return CellSignalStrengthCdma.createFromParcelBody(in);
+                case TYPE_LTE: return CellSignalStrengthLte.createFromParcelBody(in);
+                default: throw new RuntimeException("Bad CellSignalStrength Parcel");
+            }
+        }
+
+        @Override
+        public CellSignalStrength[] newArray(int size) {
+            return new CellSignalStrength[size];
+        }
+    };
+}
diff --git a/telephony/java/android/telephony/CellSignalStrengthCdma.java b/telephony/java/android/telephony/CellSignalStrengthCdma.java
new file mode 100644
index 0000000..ee50fad
--- /dev/null
+++ b/telephony/java/android/telephony/CellSignalStrengthCdma.java
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2012 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * LTE signal strength related information.
+ *
+ * @hide
+ */
+public class CellSignalStrengthCdma extends CellSignalStrength implements Parcelable {
+
+    private static final String LOG_TAG = "CellSignalStrengthCdma";
+    private static final boolean DBG = false;
+
+    private int mCdmaDbm;   // This value is the RSSI value
+    private int mCdmaEcio;  // This value is the Ec/Io
+    private int mEvdoDbm;   // This value is the EVDO RSSI value
+    private int mEvdoEcio;  // This value is the EVDO Ec/Io
+    private int mEvdoSnr;   // Valid values are 0-8.  8 is the highest signal to noise ratio
+
+    /**
+     * Empty constructor
+     *
+     * @hide
+     */
+    public CellSignalStrengthCdma() {
+        setDefaultValues();
+    }
+
+    /**
+     * Constructor
+     *
+     * @hide
+     */
+    public CellSignalStrengthCdma(int cdmaDbm, int cdmaEcio, int evdoDbm, int evdoEcio,
+            int evdoSnr) {
+        initialize(cdmaDbm, cdmaEcio, evdoDbm, evdoEcio, evdoSnr);
+    }
+
+    /**
+     * Copy constructors
+     *
+     * @param s Source SignalStrength
+     *
+     * @hide
+     */
+    public CellSignalStrengthCdma(CellSignalStrengthCdma s) {
+        copyFrom(s);
+    }
+
+    /**
+     * Initialize all the values
+     *
+     * @param cdmaDbm
+     * @param cdmaEcio
+     * @param evdoDbm
+     * @param evdoEcio
+     * @param evdoSnr
+     *
+     * @hide
+     */
+    public void initialize(int cdmaDbm, int cdmaEcio, int evdoDbm, int evdoEcio, int evdoSnr) {
+        mCdmaDbm = cdmaDbm;
+        mCdmaEcio = cdmaEcio;
+        mEvdoDbm = evdoDbm;
+        mEvdoEcio = evdoEcio;
+        mEvdoSnr = evdoSnr;
+    }
+
+    /**
+     * @hide
+     */
+    protected void copyFrom(CellSignalStrengthCdma s) {
+        mCdmaDbm = s.mCdmaDbm;
+        mCdmaEcio = s.mCdmaEcio;
+        mEvdoDbm = s.mEvdoDbm;
+        mEvdoEcio = s.mEvdoEcio;
+        mEvdoSnr = s.mEvdoSnr;
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public CellSignalStrengthCdma copy() {
+        return new CellSignalStrengthCdma(this);
+    }
+
+    /** @hide */
+    @Override
+    public void setDefaultValues() {
+        mCdmaDbm = Integer.MAX_VALUE;
+        mCdmaEcio = Integer.MAX_VALUE;
+        mEvdoDbm = Integer.MAX_VALUE;
+        mEvdoEcio = Integer.MAX_VALUE;
+        mEvdoSnr = Integer.MAX_VALUE;
+    }
+
+    /**
+     * Get LTE as level 0..4
+     *
+     * @hide
+     */
+    @Override
+    public int getLevel() {
+        int level;
+
+        int cdmaLevel = getCdmaLevel();
+        int evdoLevel = getEvdoLevel();
+        if (evdoLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
+            /* We don't know evdo, use cdma */
+            level = getCdmaLevel();
+        } else if (cdmaLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
+            /* We don't know cdma, use evdo */
+            level = getEvdoLevel();
+        } else {
+            /* We know both, use the lowest level */
+            level = cdmaLevel < evdoLevel ? cdmaLevel : evdoLevel;
+        }
+        if (DBG) log("getLevel=" + level);
+        return level;
+    }
+
+    /**
+     * Get the LTE signal level as an asu value between 0..97, 99 is unknown
+     * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
+     *
+     * @hide
+     */
+    @Override
+    public int getAsuLevel() {
+        final int cdmaDbm = getCdmaDbm();
+        final int cdmaEcio = getCdmaEcio();
+        int cdmaAsuLevel;
+        int ecioAsuLevel;
+
+        if (cdmaDbm >= -75) cdmaAsuLevel = 16;
+        else if (cdmaDbm >= -82) cdmaAsuLevel = 8;
+        else if (cdmaDbm >= -90) cdmaAsuLevel = 4;
+        else if (cdmaDbm >= -95) cdmaAsuLevel = 2;
+        else if (cdmaDbm >= -100) cdmaAsuLevel = 1;
+        else cdmaAsuLevel = 99;
+
+        // Ec/Io are in dB*10
+        if (cdmaEcio >= -90) ecioAsuLevel = 16;
+        else if (cdmaEcio >= -100) ecioAsuLevel = 8;
+        else if (cdmaEcio >= -115) ecioAsuLevel = 4;
+        else if (cdmaEcio >= -130) ecioAsuLevel = 2;
+        else if (cdmaEcio >= -150) ecioAsuLevel = 1;
+        else ecioAsuLevel = 99;
+
+        int level = (cdmaAsuLevel < ecioAsuLevel) ? cdmaAsuLevel : ecioAsuLevel;
+        if (DBG) log("getAsuLevel=" + level);
+        return level;
+    }
+
+    /**
+     * Get cdma as level 0..4
+     *
+     * @hide
+     */
+    public int getCdmaLevel() {
+        final int cdmaDbm = getCdmaDbm();
+        final int cdmaEcio = getCdmaEcio();
+        int levelDbm;
+        int levelEcio;
+
+        if (cdmaDbm >= -75) levelDbm = SIGNAL_STRENGTH_GREAT;
+        else if (cdmaDbm >= -85) levelDbm = SIGNAL_STRENGTH_GOOD;
+        else if (cdmaDbm >= -95) levelDbm = SIGNAL_STRENGTH_MODERATE;
+        else if (cdmaDbm >= -100) levelDbm = SIGNAL_STRENGTH_POOR;
+        else levelDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+
+        // Ec/Io are in dB*10
+        if (cdmaEcio >= -90) levelEcio = SIGNAL_STRENGTH_GREAT;
+        else if (cdmaEcio >= -110) levelEcio = SIGNAL_STRENGTH_GOOD;
+        else if (cdmaEcio >= -130) levelEcio = SIGNAL_STRENGTH_MODERATE;
+        else if (cdmaEcio >= -150) levelEcio = SIGNAL_STRENGTH_POOR;
+        else levelEcio = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+
+        int level = (levelDbm < levelEcio) ? levelDbm : levelEcio;
+        if (DBG) log("getCdmaLevel=" + level);
+        return level;
+    }
+
+    /**
+     * Get Evdo as level 0..4
+     *
+     * @hide
+     */
+    public int getEvdoLevel() {
+        int evdoDbm = getEvdoDbm();
+        int evdoSnr = getEvdoSnr();
+        int levelEvdoDbm;
+        int levelEvdoSnr;
+
+        if (evdoDbm >= -65) levelEvdoDbm = SIGNAL_STRENGTH_GREAT;
+        else if (evdoDbm >= -75) levelEvdoDbm = SIGNAL_STRENGTH_GOOD;
+        else if (evdoDbm >= -90) levelEvdoDbm = SIGNAL_STRENGTH_MODERATE;
+        else if (evdoDbm >= -105) levelEvdoDbm = SIGNAL_STRENGTH_POOR;
+        else levelEvdoDbm = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+
+        if (evdoSnr >= 7) levelEvdoSnr = SIGNAL_STRENGTH_GREAT;
+        else if (evdoSnr >= 5) levelEvdoSnr = SIGNAL_STRENGTH_GOOD;
+        else if (evdoSnr >= 3) levelEvdoSnr = SIGNAL_STRENGTH_MODERATE;
+        else if (evdoSnr >= 1) levelEvdoSnr = SIGNAL_STRENGTH_POOR;
+        else levelEvdoSnr = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+
+        int level = (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
+        if (DBG) log("getEvdoLevel=" + level);
+        return level;
+    }
+
+    /**
+     * Get as dBm
+     *
+     * @hide
+     */
+    @Override
+    public int getDbm() {
+        int cdmaDbm = getCdmaDbm();
+        int evdoDbm = getEvdoDbm();
+
+        // Use the lower value to be conservative
+        return (cdmaDbm < evdoDbm) ? cdmaDbm : evdoDbm;
+    }
+
+    /**
+     * Get the CDMA RSSI value in dBm
+     */
+    public int getCdmaDbm() {
+        return mCdmaDbm;
+    }
+    /** @hide */
+    public void setCdmaDbm(int cdmaDbm) {
+        mCdmaDbm = cdmaDbm;
+    }
+
+    /**
+     * Get the CDMA Ec/Io value in dB*10
+     */
+    public int getCdmaEcio() {
+        return mCdmaEcio;
+    }
+    /** @hide */
+    public void setCdmaEcio(int cdmaEcio) {
+        mCdmaEcio = cdmaEcio;
+    }
+
+    /**
+     * Get the EVDO RSSI value in dBm
+     */
+    public int getEvdoDbm() {
+        return mEvdoDbm;
+    }
+    /** @hide */
+    public void setEvdoDbm(int evdoDbm) {
+        mEvdoDbm = evdoDbm;
+    }
+
+    /**
+     * Get the EVDO Ec/Io value in dB*10
+     */
+    public int getEvdoEcio() {
+        return mEvdoEcio;
+    }
+    /** @hide */
+    public void setEvdoEcio(int evdoEcio) {
+        mEvdoEcio = evdoEcio;
+    }
+
+    /**
+     * Get the signal to noise ratio. Valid values are 0-8. 8 is the highest.
+     */
+    public int getEvdoSnr() {
+        return mEvdoSnr;
+    }
+    /** @hide */
+    public void setEvdoSnr(int evdoSnr) {
+        mEvdoSnr = evdoSnr;
+    }
+
+    @Override
+    public int hashCode() {
+        int primeNum = 31;
+        return ((mCdmaDbm * primeNum) + (mCdmaEcio * primeNum)
+                + (mEvdoDbm * primeNum) + (mEvdoEcio * primeNum) + (mEvdoSnr * primeNum));
+    }
+
+    @Override
+    public boolean equals (Object o) {
+        CellSignalStrengthCdma s;
+
+        try {
+            s = (CellSignalStrengthCdma) o;
+        } catch (ClassCastException ex) {
+            return false;
+        }
+
+        if (o == null) {
+            return false;
+        }
+
+        return mCdmaDbm == s.mCdmaDbm
+                && mCdmaEcio == s.mCdmaEcio
+                && mEvdoDbm == s.mEvdoDbm
+                && mEvdoEcio == s.mEvdoEcio
+                && mEvdoSnr == s.mEvdoSnr;
+    }
+
+    /**
+     * @return string representation.
+     */
+    @Override
+    public String toString() {
+        return "CellSignalStrengthCdma:"
+                + " cdmaDbm=" + mCdmaDbm
+                + " cdmaEcio=" + mCdmaEcio
+                + " evdoDbm=" + mEvdoDbm
+                + " evdoEcio=" + mEvdoEcio
+                + " evdoSnr=" + mEvdoSnr;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        if (DBG) log("writeToParcel(Parcel, int): " + toString());
+        dest.writeInt(CellSignalStrength.TYPE_CDMA);
+        dest.writeInt(mCdmaDbm);
+        dest.writeInt(mCdmaEcio);
+        dest.writeInt(mEvdoDbm);
+        dest.writeInt(mEvdoEcio);
+        dest.writeInt(mEvdoSnr);
+    }
+
+    /**
+     * Construct a SignalStrength object from the given parcel
+     * where the TYPE_LTE token is already been processed.
+     */
+    private CellSignalStrengthCdma(Parcel in) {
+        mCdmaDbm = in.readInt();
+        mCdmaEcio = in.readInt();
+        mEvdoDbm = in.readInt();
+        mEvdoEcio = in.readInt();
+        mEvdoSnr = in.readInt();
+        if (DBG) log("CellSignalStrengthCdma(Parcel): " + toString());
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @SuppressWarnings("hiding")
+    public static final Parcelable.Creator<CellSignalStrengthCdma> CREATOR =
+            new Parcelable.Creator<CellSignalStrengthCdma>() {
+        @Override
+        public CellSignalStrengthCdma createFromParcel(Parcel in) {
+            if (in.readInt() != CellSignalStrength.TYPE_CDMA) {
+                throw new RuntimeException("Expecting TYPE_CDMA");
+            }
+            return createFromParcelBody(in);
+        }
+
+        @Override
+        public CellSignalStrengthCdma[] newArray(int size) {
+            return new CellSignalStrengthCdma[size];
+        }
+    };
+
+    /** @hide */
+    public static CellSignalStrengthCdma createFromParcelBody(Parcel in) {
+        return new CellSignalStrengthCdma(in);
+    }
+
+    /**
+     * log
+     */
+    private static void log(String s) {
+        Log.w(LOG_TAG, s);
+    }
+}
diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java
new file mode 100644
index 0000000..70876fb
--- /dev/null
+++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2012 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * LTE signal strength related information.
+ *
+ * @hide
+ */
+public class CellSignalStrengthGsm extends CellSignalStrength implements Parcelable {
+
+    private static final String LOG_TAG = "CellSignalStrengthGsm";
+    private static final boolean DBG = false;
+
+    private static final int GSM_SIGNAL_STRENGTH_GREAT = 12;
+    private static final int GSM_SIGNAL_STRENGTH_GOOD = 8;
+    private static final int GSM_SIGNAL_STRENGTH_MODERATE = 8;
+
+    private int mSignalStrength; // Valid values are (0-31, 99) as defined in TS 27.007 8.5
+    private int mBitErrorRate;   // bit error rate (0-7, 99) as defined in TS 27.007 8.5
+
+    /**
+     * Empty constructor
+     *
+     * @hide
+     */
+    public CellSignalStrengthGsm() {
+        setDefaultValues();
+    }
+
+    /**
+     * Constructor
+     *
+     * @hide
+     */
+    public CellSignalStrengthGsm(int ss, int ber) {
+        initialize(ss, ber);
+    }
+
+    /**
+     * Copy constructors
+     *
+     * @param s Source SignalStrength
+     *
+     * @hide
+     */
+    public CellSignalStrengthGsm(CellSignalStrengthGsm s) {
+        copyFrom(s);
+    }
+
+    /**
+     * Initialize all the values
+     *
+     * @param SignalStrength
+     *
+     * @hide
+     */
+    public void initialize(int ss, int ber) {
+        mSignalStrength = ss;
+        mBitErrorRate = ber;
+    }
+
+    /**
+     * @hide
+     */
+    protected void copyFrom(CellSignalStrengthGsm s) {
+        mSignalStrength = s.mSignalStrength;
+        mBitErrorRate = s.mBitErrorRate;
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public CellSignalStrengthGsm copy() {
+        return new CellSignalStrengthGsm(this);
+    }
+
+    /** @hide */
+    @Override
+    public void setDefaultValues() {
+        mSignalStrength = Integer.MAX_VALUE;
+        mBitErrorRate = Integer.MAX_VALUE;
+    }
+
+    /**
+     * Get LTE as level 0..4
+     *
+     * @hide
+     */
+    @Override
+    public int getLevel() {
+        int level;
+
+        // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
+        // asu = 0 (-113dB or less) is very weak
+        // signal, its better to show 0 bars to the user in such cases.
+        // asu = 99 is a special case, where the signal strength is unknown.
+        int asu = mSignalStrength;
+        if (asu <= 2 || asu == 99) level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        else if (asu >= GSM_SIGNAL_STRENGTH_GREAT) level = SIGNAL_STRENGTH_GREAT;
+        else if (asu >= GSM_SIGNAL_STRENGTH_GOOD)  level = SIGNAL_STRENGTH_GOOD;
+        else if (asu >= GSM_SIGNAL_STRENGTH_MODERATE)  level = SIGNAL_STRENGTH_MODERATE;
+        else level = SIGNAL_STRENGTH_POOR;
+        if (DBG) log("getLevel=" + level);
+        return level;
+    }
+
+    /**
+     * Get LTE as dBm
+     *
+     * @hide
+     */
+    @Override
+    public int getDbm() {
+        int dBm;
+
+        int level = mSignalStrength;
+        int asu = (level == 99 ? Integer.MAX_VALUE : level);
+        if (asu != Integer.MAX_VALUE) {
+            dBm = -113 + (2 * asu);
+        } else {
+            dBm = Integer.MAX_VALUE;
+        }
+        if (DBG) log("getDbm=" + dBm);
+        return dBm;
+    }
+
+    /**
+     * Get the LTE signal level as an asu value between 0..97, 99 is unknown
+     * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
+     *
+     * @hide
+     */
+    @Override
+    public int getAsuLevel() {
+        // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
+        // asu = 0 (-113dB or less) is very weak
+        // signal, its better to show 0 bars to the user in such cases.
+        // asu = 99 is a special case, where the signal strength is unknown.
+        int level = mSignalStrength;
+        if (DBG) log("getAsuLevel=" + level);
+        return level;
+    }
+
+    @Override
+    public int hashCode() {
+        int primeNum = 31;
+        return (mSignalStrength * primeNum) + (mBitErrorRate * primeNum);
+    }
+
+    @Override
+    public boolean equals (Object o) {
+        CellSignalStrengthGsm s;
+
+        try {
+            s = (CellSignalStrengthGsm) o;
+        } catch (ClassCastException ex) {
+            return false;
+        }
+
+        if (o == null) {
+            return false;
+        }
+
+        return mSignalStrength == s.mSignalStrength && mBitErrorRate == s.mBitErrorRate;
+    }
+
+    /**
+     * @return string representation.
+     */
+    @Override
+    public String toString() {
+        return "CellSignalStrengthGsm:"
+                + " ss=" + mSignalStrength
+                + " ber=" + mBitErrorRate;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        if (DBG) log("writeToParcel(Parcel, int): " + toString());
+        dest.writeInt(CellSignalStrength.TYPE_GSM);
+        dest.writeInt(mSignalStrength);
+        dest.writeInt(mBitErrorRate);
+    }
+
+    /**
+     * Construct a SignalStrength object from the given parcel
+     * where the token is already been processed.
+     */
+    private CellSignalStrengthGsm(Parcel in) {
+        mSignalStrength = in.readInt();
+        mBitErrorRate = in.readInt();
+        if (DBG) log("CellSignalStrengthGsm(Parcel): " + toString());
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @SuppressWarnings("hiding")
+    public static final Parcelable.Creator<CellSignalStrengthGsm> CREATOR =
+            new Parcelable.Creator<CellSignalStrengthGsm>() {
+        @Override
+        public CellSignalStrengthGsm createFromParcel(Parcel in) {
+            if (in.readInt() != CellSignalStrength.TYPE_GSM) {
+                throw new RuntimeException("Expecting TYPE_GSM");
+            }
+            return createFromParcelBody(in);
+        }
+
+        @Override
+        public CellSignalStrengthGsm[] newArray(int size) {
+            return new CellSignalStrengthGsm[size];
+        }
+    };
+
+    /** @hide */
+    public static CellSignalStrengthGsm createFromParcelBody(Parcel in) {
+        return new CellSignalStrengthGsm(in);
+    }
+
+    /**
+     * log
+     */
+    private static void log(String s) {
+        Log.w(LOG_TAG, s);
+    }
+}
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
new file mode 100644
index 0000000..3caea3d
--- /dev/null
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2012 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * LTE signal strength related information.
+ *
+ * @hide
+ */
+public class CellSignalStrengthLte extends CellSignalStrength implements Parcelable {
+
+    private static final String LOG_TAG = "CellSignalStrengthLte";
+    private static final boolean DBG = false;
+
+    private int mSignalStrength;
+    private int mRsrp;
+    private int mRsrq;
+    private int mRssnr;
+    private int mCqi;
+    private int mTimingAdvance;
+
+    /**
+     * Empty constructor
+     *
+     * @hide
+     */
+    public CellSignalStrengthLte() {
+        setDefaultValues();
+    }
+
+    /**
+     * Constructor
+     *
+     * @hide
+     */
+    public CellSignalStrengthLte(int signalStrength, int rsrp, int rsrq, int rssnr, int cqi,
+            int timingAdvance) {
+        initialize(signalStrength, rsrp, rsrq, rssnr, cqi, timingAdvance);
+    }
+
+    /**
+     * Copy constructors
+     *
+     * @param s Source SignalStrength
+     *
+     * @hide
+     */
+    public CellSignalStrengthLte(CellSignalStrengthLte s) {
+        copyFrom(s);
+    }
+
+    /**
+     * Initialize all the values
+     *
+     * @param lteSignalStrength
+     * @param rsrp
+     * @param rsrq
+     * @param rssnr
+     * @param cqi
+     *
+     * @hide
+     */
+    public void initialize(int lteSignalStrength, int rsrp, int rsrq, int rssnr, int cqi,
+            int timingAdvance) {
+        mSignalStrength = lteSignalStrength;
+        mRsrp = rsrp;
+        mRsrq = rsrq;
+        mRssnr = rssnr;
+        mCqi = cqi;
+        mTimingAdvance = timingAdvance;
+    }
+
+    /**
+     * @hide
+     */
+    protected void copyFrom(CellSignalStrengthLte s) {
+        mSignalStrength = s.mSignalStrength;
+        mRsrp = s.mRsrp;
+        mRsrq = s.mRsrq;
+        mRssnr = s.mRssnr;
+        mCqi = s.mCqi;
+        mTimingAdvance = s.mTimingAdvance;
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public CellSignalStrengthLte copy() {
+        return new CellSignalStrengthLte(this);
+    }
+
+    /** @hide */
+    @Override
+    public void setDefaultValues() {
+        mSignalStrength = Integer.MAX_VALUE;
+        mRsrp = Integer.MAX_VALUE;
+        mRsrq = Integer.MAX_VALUE;
+        mRssnr = Integer.MAX_VALUE;
+        mCqi = Integer.MAX_VALUE;
+        mTimingAdvance = Integer.MAX_VALUE;
+    }
+
+    /**
+     * Get LTE as level 0..4
+     *
+     * @hide
+     */
+    @Override
+    public int getLevel() {
+        int levelRsrp = 0;
+        int levelRssnr = 0;
+
+        if (mRsrp == Integer.MAX_VALUE) levelRsrp = 0;
+        else if (mRsrp >= -95) levelRsrp = SIGNAL_STRENGTH_GREAT;
+        else if (mRsrp >= -105) levelRsrp = SIGNAL_STRENGTH_GOOD;
+        else if (mRsrp >= -115) levelRsrp = SIGNAL_STRENGTH_MODERATE;
+        else levelRsrp = SIGNAL_STRENGTH_POOR;
+
+        // See RIL_LTE_SignalStrength in ril.h
+        if (mRssnr == Integer.MAX_VALUE) levelRssnr = 0;
+        else if (mRssnr >= 45) levelRssnr = SIGNAL_STRENGTH_GREAT;
+        else if (mRssnr >= 10) levelRssnr = SIGNAL_STRENGTH_GOOD;
+        else if (mRssnr >= -30) levelRssnr = SIGNAL_STRENGTH_MODERATE;
+        else levelRssnr = SIGNAL_STRENGTH_POOR;
+
+        int level;
+        if (mRsrp == Integer.MAX_VALUE)
+            level = levelRssnr;
+        else if (mRssnr == Integer.MAX_VALUE)
+            level = levelRsrp;
+        else
+            level = (levelRssnr < levelRsrp) ? levelRssnr : levelRsrp;
+
+        if (DBG) log("Lte rsrp level: " + levelRsrp
+                + " snr level: " + levelRssnr + " level: " + level);
+        return level;
+    }
+
+    /**
+     * Get LTE as dBm
+     *
+     * @hide
+     */
+    @Override
+    public int getDbm() {
+        return mRsrp;
+    }
+
+    /**
+     * Get the LTE signal level as an asu value between 0..97, 99 is unknown
+     * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
+     *
+     * @hide
+     */
+    @Override
+    public int getAsuLevel() {
+        int lteAsuLevel = 99;
+        int lteDbm = getDbm();
+        if (lteDbm <= -140) lteAsuLevel = 0;
+        else if (lteDbm >= -43) lteAsuLevel = 97;
+        else lteAsuLevel = lteDbm + 140;
+        if (DBG) log("Lte Asu level: "+lteAsuLevel);
+        return lteAsuLevel;
+    }
+
+    /**
+     * Get the timing advance value for LTE.
+     * See 3GPP xxxx
+     */
+    public int getTimingAdvance() {
+        return mTimingAdvance;
+    }
+
+    @Override
+    public int hashCode() {
+        int primeNum = 31;
+        return (mSignalStrength * primeNum) + (mRsrp * primeNum)
+                + (mRsrq * primeNum) + (mRssnr * primeNum) + (mCqi * primeNum)
+                + (mTimingAdvance * primeNum);
+    }
+
+    @Override
+    public boolean equals (Object o) {
+        CellSignalStrengthLte s;
+
+        try {
+            s = (CellSignalStrengthLte) o;
+        } catch (ClassCastException ex) {
+            return false;
+        }
+
+        if (o == null) {
+            return false;
+        }
+
+        return mSignalStrength == s.mSignalStrength
+                && mRsrp == s.mRsrp
+                && mRsrq == s.mRsrq
+                && mRssnr == s.mRssnr
+                && mCqi == s.mCqi
+                && mTimingAdvance == s.mTimingAdvance;
+    }
+
+    /**
+     * @return string representation.
+     */
+    @Override
+    public String toString() {
+        return "CellSignalStrengthLte:"
+                + " ss=" + mSignalStrength
+                + " rsrp=" + mRsrp
+                + " rsrq=" + mRsrq
+                + " rssnr=" + mRssnr
+                + " cqi=" + mCqi
+                + " ta=" + mTimingAdvance;
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        if (DBG) log("writeToParcel(Parcel, int): " + toString());
+        dest.writeInt(CellSignalStrength.TYPE_LTE);
+        dest.writeInt(mSignalStrength);
+        dest.writeInt(mRsrp);
+        dest.writeInt(mRsrq);
+        dest.writeInt(mRssnr);
+        dest.writeInt(mCqi);
+        dest.writeInt(mTimingAdvance);
+    }
+
+    /**
+     * Construct a SignalStrength object from the given parcel
+     * where the token is already been processed.
+     */
+    private CellSignalStrengthLte(Parcel in) {
+        mSignalStrength = in.readInt();
+        mRsrp = in.readInt();
+        mRsrq = in.readInt();
+        mRssnr = in.readInt();
+        mCqi = in.readInt();
+        mTimingAdvance = in.readInt();
+        if (DBG) log("CellSignalStrengthLte(Parcel): " + toString());
+    }
+
+    /** Implement the Parcelable interface */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    @SuppressWarnings("hiding")
+    public static final Parcelable.Creator<CellSignalStrengthLte> CREATOR =
+            new Parcelable.Creator<CellSignalStrengthLte>() {
+        @Override
+        public CellSignalStrengthLte createFromParcel(Parcel in) {
+            if (in.readInt() != CellSignalStrength.TYPE_LTE) {
+                throw new RuntimeException("Expecting TYPE_LTE");
+            }
+            return createFromParcelBody(in);
+        }
+
+        @Override
+        public CellSignalStrengthLte[] newArray(int size) {
+            return new CellSignalStrengthLte[size];
+        }
+    };
+
+    /** @hide */
+    public static CellSignalStrengthLte createFromParcelBody(Parcel in) {
+        return new CellSignalStrengthLte(in);
+    }
+
+    /**
+     * log
+     */
+    private static void log(String s) {
+        Log.w(LOG_TAG, s);
+    }
+}
diff --git a/telephony/java/android/telephony/GsmCellIdentity.java b/telephony/java/android/telephony/GsmCellIdentity.java
deleted file mode 100644
index 159cb52..0000000
--- a/telephony/java/android/telephony/GsmCellIdentity.java
+++ /dev/null
@@ -1,148 +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.telephony;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * CellIdentity to represent a unique GSM or UMTS cell
- *
- * @hide pending API review
- */
-public final class GsmCellIdentity extends CellIdentity implements Parcelable {
-
-    // 3-digit Mobile Country Code, 0..999
-    private final int mMcc;
-    // 2 or 3-digit Mobile Network Code, 0..999
-    private final int mMnc;
-    // 16-bit Location Area Code, 0..65535
-    private final int mLac;
-    // 16-bit GSM Cell Identity described in TS 27.007, 0..65535
-    // 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455
-    private final int mCid;
-    // 9-bit UMTS Primary Scrambling Code described in TS 25.331, 0..511
-    private final int mPsc;
-
-    /**
-     * public constructor
-     * @param mcc 3-digit Mobile Country Code, 0..999
-     * @param mnc 2 or 3-digit Mobile Network Code, 0..999
-     * @param lac 16-bit Location Area Code, 0..65535
-     * @param cid 16-bit GSM Cell Identity or 28-bit UMTS Cell Identity
-     * @param psc 9-bit UMTS Primary Scrambling Code
-     * @param attr is comma separated “key=value” attribute pairs.
-     */
-    public GsmCellIdentity (int mcc, int mnc,
-            int lac, int cid, int psc, String attr) {
-        super(CELLID_TYPE_GSM, attr);
-        mMcc = mcc;
-        mMnc = mnc;
-        mLac = lac;
-        mCid = cid;
-        mPsc = psc;
-    }
-
-    private GsmCellIdentity(Parcel in) {
-        super(in);
-        mMcc = in.readInt();
-        mMnc = in.readInt();
-        mLac = in.readInt();
-        mCid = in.readInt();
-        mPsc = in.readInt();
-    }
-
-    GsmCellIdentity(GsmCellIdentity cid) {
-        super(cid);
-        mMcc = cid.mMcc;
-        mMnc = cid.mMnc;
-        mLac = cid.mLac;
-        mCid = cid.mCid;
-        mPsc = cid.mPsc;
-    }
-
-    /**
-     * @return 3-digit Mobile Country Code, 0..999
-     */
-    public int getMcc() {
-        return mMcc;
-    }
-
-    /**
-     * @return 2 or 3-digit Mobile Network Code, 0..999
-     */
-    public int getMnc() {
-        return mMnc;
-    }
-
-    /**
-     * @return 16-bit Location Area Code, 0..65535
-     */
-    public int getLac() {
-        return mLac;
-    }
-
-    /**
-     * @return CID
-     * Either 16-bit GSM Cell Identity described
-     * in TS 27.007, 0..65535
-     * or 28-bit UMTS Cell Identity described
-     * in TS 25.331, 0..268435455
-     */
-    public int getCid() {
-        return mCid;
-    }
-
-    /**
-     * @return 9-bit UMTS Primary Scrambling Code described in
-     * TS 25.331, 0..511
-     */
-    public int getPsc() {
-        return mPsc;
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        super.writeToParcel(dest, flags);
-        dest.writeInt(mMcc);
-        dest.writeInt(mMnc);
-        dest.writeInt(mLac);
-        dest.writeInt(mCid);
-        dest.writeInt(mPsc);
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    public static final Creator<GsmCellIdentity> CREATOR =
-            new Creator<GsmCellIdentity>() {
-        @Override
-        public GsmCellIdentity createFromParcel(Parcel in) {
-            return new GsmCellIdentity(in);
-        }
-
-        @Override
-        public GsmCellIdentity[] newArray(int size) {
-            return new GsmCellIdentity[size];
-        }
-    };
-}
diff --git a/telephony/java/android/telephony/LteCellIdentity.java b/telephony/java/android/telephony/LteCellIdentity.java
deleted file mode 100644
index 396922e..0000000
--- a/telephony/java/android/telephony/LteCellIdentity.java
+++ /dev/null
@@ -1,142 +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.telephony;
-
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/**
- * CellIdentity is to represent a unique LTE cell
- *
- * @hide pending API review
- */
-public final class LteCellIdentity extends CellIdentity implements Parcelable {
-
-    // 3-digit Mobile Country Code, 0..999
-    private final int mMcc;
-    // 2 or 3-digit Mobile Network Code, 0..999
-    private final int mMnc;
-    // 28-bit cell identity
-    private final int mCi;
-    // physical cell id 0..503
-    private final int mPci;
-    // 16-bit tracking area code
-    private final int mTac;
-
-    /**
-     *
-     * @param mcc 3-digit Mobile Country Code, 0..999
-     * @param mnc 2 or 3-digit Mobile Network Code, 0..999
-     * @param ci 28-bit Cell Identity
-     * @param pci Physical Cell Id 0..503
-     * @param tac 16-bit Tracking Area Code
-     * @param attr is comma separated “key=value” attribute pairs.
-     */
-    public LteCellIdentity (int mcc, int mnc,
-            int ci, int pci, int tac, String attr) {
-        super(CELLID_TYPE_CDMA, attr);
-        mMcc = mcc;
-        mMnc = mnc;
-        mCi = ci;
-        mPci = pci;
-        mTac = tac;
-    }
-
-    private LteCellIdentity(Parcel in) {
-        super(in);
-        mMcc = in.readInt();
-        mMnc = in.readInt();
-        mCi = in.readInt();
-        mPci = in.readInt();
-        mTac = in.readInt();
-    }
-
-    LteCellIdentity(LteCellIdentity cid) {
-        super(cid);
-        mMcc = cid.mMcc;
-        mMnc = cid.mMnc;
-        mCi = cid.mCi;
-        mPci = cid.mPci;
-        mTac = cid.mTac;
-    }
-
-    /**
-     * @return 3-digit Mobile Country Code, 0..999
-     */
-    public int getMcc() {
-        return mMcc;
-    }
-
-    /**
-     * @return 2 or 3-digit Mobile Network Code, 0..999
-     */
-    public int getMnc() {
-        return mMnc;
-    }
-
-    /**
-     * @return 28-bit Cell Identity
-     */
-    public int getCi() {
-        return mCi;
-    }
-
-    /**
-     * @return Physical Cell Id 0..503
-     */
-    public int getPci() {
-        return mPci;
-    }
-
-    /**
-     * @return 16-bit Tracking Area Code
-     */
-    public int getTac() {
-        return mTac;
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        super.writeToParcel(dest, flags);
-        dest.writeInt(mMcc);
-        dest.writeInt(mMnc);
-        dest.writeInt(mCi);
-        dest.writeInt(mPci);
-        dest.writeInt(mTac);
-    }
-
-    /** Implement the Parcelable interface {@hide} */
-    public static final Creator<LteCellIdentity> CREATOR =
-            new Creator<LteCellIdentity>() {
-        @Override
-        public LteCellIdentity createFromParcel(Parcel in) {
-            return new LteCellIdentity(in);
-        }
-
-        @Override
-        public LteCellIdentity[] newArray(int size) {
-            return new LteCellIdentity[size];
-        }
-    };
-}
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index def6939..63d81e9 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -27,6 +27,8 @@
 
 import com.android.internal.telephony.IPhoneStateListener;
 
+import java.util.List;
+
 /**
  * A listener class for monitoring changes in specific telephony states
  * on the device, including service state, signal strength, message
@@ -160,7 +162,8 @@
      * Listen for changes to observed cell info.
      *
      * @see #onCellInfoChanged
-     * @hide pending API review
+     *
+     * @hide
      */
     public static final int LISTEN_CELL_INFO = 0x00000400;
 
@@ -284,17 +287,13 @@
     }
 
     /**
-     * Callback invoked when a observed cell info gets changed.
+     * Callback invoked when a observed cell info has changed,
+     * or new cells have been added or removed.
+     * @param cellInfo is the list of currently visible cells.
      *
-     * A notification should be sent when:
-     *     1. a cell is newly-observed.
-     *     2. a observed cell is not visible.
-     *     3. any of the cell info of a observed cell has changed.
-     *
-     * @hide pending API review
+     * @hide
      */
-    public void onCellInfoChanged(CellInfo cellInfo) {
-        // default implementation empty
+    public void onCellInfoChanged(List<CellInfo> cellInfo) {
     }
 
     /**
@@ -346,8 +345,8 @@
             Message.obtain(mHandler, LISTEN_OTASP_CHANGED, otaspMode, 0).sendToTarget();
         }
 
-        public void onCellInfoChanged(CellInfo cellInfo) {
-            Message.obtain(mHandler, LISTEN_CELL_INFO, 0, 0).sendToTarget();
+        public void onCellInfoChanged(List<CellInfo> cellInfo) {
+            Message.obtain(mHandler, LISTEN_CELL_INFO, 0, 0, cellInfo).sendToTarget();
         }
     };
 
@@ -387,7 +386,7 @@
                     PhoneStateListener.this.onOtaspChanged(msg.arg1);
                     break;
                 case LISTEN_CELL_INFO:
-                    PhoneStateListener.this.onCellInfoChanged((CellInfo)msg.obj);
+                    PhoneStateListener.this.onCellInfoChanged((List<CellInfo>)msg.obj);
             }
         }
     };
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 1049669..d80425c 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -1,6 +1,5 @@
 /*
- * Copyright (C) 2009 Qualcomm Innovation Center, Inc.  All Rights Reserved.
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2012 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.
@@ -28,7 +27,7 @@
 public class SignalStrength implements Parcelable {
 
     private static final String LOG_TAG = "SignalStrength";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
 
     /** @hide */
     public static final int SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0;
@@ -114,19 +113,9 @@
             int evdoDbm, int evdoEcio, int evdoSnr,
             int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
             boolean gsm) {
-        mGsmSignalStrength = gsmSignalStrength;
-        mGsmBitErrorRate = gsmBitErrorRate;
-        mCdmaDbm = cdmaDbm;
-        mCdmaEcio = cdmaEcio;
-        mEvdoDbm = evdoDbm;
-        mEvdoEcio = evdoEcio;
-        mEvdoSnr = evdoSnr;
-        mLteSignalStrength = lteSignalStrength;
-        mLteRsrp = lteRsrp;
-        mLteRsrq = lteRsrq;
-        mLteRssnr = lteRssnr;
-        mLteCqi = lteCqi;
-        isGsm = gsm;
+        initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
+                evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
+                lteRsrq, lteRssnr, lteCqi, gsm);
     }
 
     /**
@@ -138,7 +127,7 @@
             int cdmaDbm, int cdmaEcio,
             int evdoDbm, int evdoEcio, int evdoSnr,
             boolean gsm) {
-        this(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
+        initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
                 evdoDbm, evdoEcio, evdoSnr, -1, -1,
                 -1, INVALID_SNR, -1, gsm);
     }
@@ -155,6 +144,69 @@
     }
 
     /**
+     * Initialize gsm/cdma values, sets lte values to defaults.
+     *
+     * @param gsmSignalStrength
+     * @param gsmBitErrorRate
+     * @param cdmaDbm
+     * @param cdmaEcio
+     * @param evdoDbm
+     * @param evdoEcio
+     * @param evdoSnr
+     * @param gsm
+     *
+     * @hide
+     */
+    public void initialize(int gsmSignalStrength, int gsmBitErrorRate,
+            int cdmaDbm, int cdmaEcio,
+            int evdoDbm, int evdoEcio, int evdoSnr,
+            boolean gsm) {
+        initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
+                evdoDbm, evdoEcio, evdoSnr, -1, -1,
+                -1, INVALID_SNR, -1, gsm);
+    }
+
+    /**
+     * Initialize all the values
+     *
+     * @param gsmSignalStrength
+     * @param gsmBitErrorRate
+     * @param cdmaDbm
+     * @param cdmaEcio
+     * @param evdoDbm
+     * @param evdoEcio
+     * @param evdoSnr
+     * @param lteSignalStrength
+     * @param lteRsrp
+     * @param lteRsrq
+     * @param lteRssnr
+     * @param lteCqi
+     * @param gsm
+     *
+     * @hide
+     */
+    public void initialize(int gsmSignalStrength, int gsmBitErrorRate,
+            int cdmaDbm, int cdmaEcio,
+            int evdoDbm, int evdoEcio, int evdoSnr,
+            int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
+            boolean gsm) {
+        mGsmSignalStrength = gsmSignalStrength;
+        mGsmBitErrorRate = gsmBitErrorRate;
+        mCdmaDbm = cdmaDbm;
+        mCdmaEcio = cdmaEcio;
+        mEvdoDbm = evdoDbm;
+        mEvdoEcio = evdoEcio;
+        mEvdoSnr = evdoSnr;
+        mLteSignalStrength = lteSignalStrength;
+        mLteRsrp = lteRsrp;
+        mLteRsrq = lteRsrq;
+        mLteRssnr = lteRssnr;
+        mLteCqi = lteCqi;
+        isGsm = gsm;
+        if (DBG) log("initialize: " + toString());
+    }
+
+    /**
      * @hide
      */
     protected void copyFrom(SignalStrength s) {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index fa4b7cd..2b0fcd8 100755
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1272,7 +1272,7 @@
      * <p>Requires Permission:
      * (@link android.Manifest.permission#ACCESS_COARSE_UPDATES}
      *
-     * @hide pending API review
+     * @hide
      */
     public List<CellInfo> getAllCellInfo() {
         try {
diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
index d6a1edd..3a04ceb 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -34,6 +34,6 @@
     void onDataActivity(int direction);
     void onSignalStrengthsChanged(in SignalStrength signalStrength);
     void onOtaspChanged(in int otaspMode);
-    void onCellInfoChanged(in CellInfo cellInfo);
+    void onCellInfoChanged(in List<CellInfo> cellInfo);
 }
 
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 3c9a99b..59c8472 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -40,5 +40,5 @@
     void notifyDataConnectionFailed(String reason, String apnType);
     void notifyCellLocation(in Bundle cellLocation);
     void notifyOtaspChanged(in int otaspMode);
-    void notifyCellInfo(in CellInfo cellInfo);
+    void notifyCellInfo(in List<CellInfo> cellInfo);
 }
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
index 36f13b1..f0ce458 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/RSTestCore.java
@@ -67,6 +67,7 @@
         unitTests.add(new UT_primitives(this, mRes, mCtx));
         unitTests.add(new UT_constant(this, mRes, mCtx));
         unitTests.add(new UT_vector(this, mRes, mCtx));
+        unitTests.add(new UT_unsigned(this, mRes, mCtx));
         unitTests.add(new UT_array_init(this, mRes, mCtx));
         unitTests.add(new UT_array_alloc(this, mRes, mCtx));
         unitTests.add(new UT_clamp(this, mRes, mCtx));
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_agree.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_agree.java
index 9d94ba5..ca49344 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_agree.java
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_math_agree.java
@@ -299,40 +299,6 @@
         float[] rand_f2_1 = randvec_float(2);
         float[] rand_f3_1 = randvec_float(3);
         float[] rand_f4_1 = randvec_float(4);
-        byte rand_sc1_0 = (byte)rand.nextInt(0x1 << 8);
-        byte[] rand_sc2_0 = randvec_char(2);
-        byte[] rand_sc3_0 = randvec_char(3);
-        byte[] rand_sc4_0 = randvec_char(4);
-        byte rand_sc1_1 = (byte)rand.nextInt(0x1 << 8);
-        byte[] rand_sc2_1 = randvec_char(2);
-        byte[] rand_sc3_1 = randvec_char(3);
-        byte[] rand_sc4_1 = randvec_char(4);
-        short rand_ss1_0 = (short)rand.nextInt(0x1 << 16);
-        short[] rand_ss2_0 = randvec_short(2);
-        short[] rand_ss3_0 = randvec_short(3);
-        short[] rand_ss4_0 = randvec_short(4);
-        short rand_ss1_1 = (short)rand.nextInt(0x1 << 16);
-        short[] rand_ss2_1 = randvec_short(2);
-        short[] rand_ss3_1 = randvec_short(3);
-        short[] rand_ss4_1 = randvec_short(4);
-        int rand_si1_0 = rand.nextInt();
-        int[] rand_si2_0 = randvec_int(2);
-        int[] rand_si3_0 = randvec_int(3);
-        int[] rand_si4_0 = randvec_int(4);
-        int rand_si1_1 = rand.nextInt();
-        int[] rand_si2_1 = randvec_int(2);
-        int[] rand_si3_1 = randvec_int(3);
-        int[] rand_si4_1 = randvec_int(4);
-        long rand_sl1_0 = rand.nextLong();
-        long[] rand_sl2_0 = randvec_long(2);
-        long[] rand_sl3_0 = randvec_long(3);
-        long[] rand_sl4_0 = randvec_long(4);
-        long rand_sl1_1 = rand.nextLong();
-        long[] rand_sl2_1 = randvec_long(2);
-        long[] rand_sl3_1 = randvec_long(3);
-        long[] rand_sl4_1 = randvec_long(4);
-        // FIXME:  generate unsigned input vectors once bug 6764163 is fixed
-        /*
         short rand_uc1_0 = (short)rand.nextInt(0x1 << 8);
         short[] rand_uc2_0 = randvec_uchar(2);
         short[] rand_uc3_0 = randvec_uchar(3);
@@ -341,6 +307,14 @@
         short[] rand_uc2_1 = randvec_uchar(2);
         short[] rand_uc3_1 = randvec_uchar(3);
         short[] rand_uc4_1 = randvec_uchar(4);
+        short rand_ss1_0 = (short)rand.nextInt(0x1 << 16);
+        short[] rand_ss2_0 = randvec_short(2);
+        short[] rand_ss3_0 = randvec_short(3);
+        short[] rand_ss4_0 = randvec_short(4);
+        short rand_ss1_1 = (short)rand.nextInt(0x1 << 16);
+        short[] rand_ss2_1 = randvec_short(2);
+        short[] rand_ss3_1 = randvec_short(3);
+        short[] rand_ss4_1 = randvec_short(4);
         int rand_us1_0 = rand.nextInt(0x1 << 16);
         int[] rand_us2_0 = randvec_ushort(2);
         int[] rand_us3_0 = randvec_ushort(3);
@@ -349,6 +323,14 @@
         int[] rand_us2_1 = randvec_ushort(2);
         int[] rand_us3_1 = randvec_ushort(3);
         int[] rand_us4_1 = randvec_ushort(4);
+        int rand_si1_0 = rand.nextInt();
+        int[] rand_si2_0 = randvec_int(2);
+        int[] rand_si3_0 = randvec_int(3);
+        int[] rand_si4_0 = randvec_int(4);
+        int rand_si1_1 = rand.nextInt();
+        int[] rand_si2_1 = randvec_int(2);
+        int[] rand_si3_1 = randvec_int(3);
+        int[] rand_si4_1 = randvec_int(4);
         long rand_ui1_0 = (long)rand.nextInt() - (long)Integer.MIN_VALUE;
         long[] rand_ui2_0 = randvec_uint(2);
         long[] rand_ui3_0 = randvec_uint(3);
@@ -357,6 +339,24 @@
         long[] rand_ui2_1 = randvec_uint(2);
         long[] rand_ui3_1 = randvec_uint(3);
         long[] rand_ui4_1 = randvec_uint(4);
+        long rand_sl1_0 = rand.nextLong();
+        long[] rand_sl2_0 = randvec_long(2);
+        long[] rand_sl3_0 = randvec_long(3);
+        long[] rand_sl4_0 = randvec_long(4);
+        long rand_sl1_1 = rand.nextLong();
+        long[] rand_sl2_1 = randvec_long(2);
+        long[] rand_sl3_1 = randvec_long(3);
+        long[] rand_sl4_1 = randvec_long(4);
+        // FIXME:  generate signed char vectors once bug 6865598 is fixed
+        /*
+        byte rand_sc1_0 = (byte)rand.nextInt(0x1 << 8);
+        byte[] rand_sc2_0 = randvec_char(2);
+        byte[] rand_sc3_0 = randvec_char(3);
+        byte[] rand_sc4_0 = randvec_char(4);
+        byte rand_sc1_1 = (byte)rand.nextInt(0x1 << 8);
+        byte[] rand_sc2_1 = randvec_char(2);
+        byte[] rand_sc3_1 = randvec_char(3);
+        byte[] rand_sc4_1 = randvec_char(4);
         */
         // TODO:  generate unsigned long vectors
 
@@ -369,10 +369,10 @@
         s.set_rand_f2_1(pack_f2(rand_f2_1));
         s.set_rand_f3_1(pack_f3(rand_f3_1));
         s.set_rand_f4_1(pack_f4(rand_f4_1));
-        s.set_rand_sc1_1(rand_sc1_1);
-        s.set_rand_sc2_1(pack_b2(rand_sc2_1));
-        s.set_rand_sc3_1(pack_b3(rand_sc3_1));
-        s.set_rand_sc4_1(pack_b4(rand_sc4_1));
+        s.set_rand_uc1_1(rand_uc1_1);
+        s.set_rand_uc2_1(pack_s2(rand_uc2_1));
+        s.set_rand_uc3_1(pack_s3(rand_uc3_1));
+        s.set_rand_uc4_1(pack_s4(rand_uc4_1));
         s.set_rand_ss1_0(rand_ss1_0);
         s.set_rand_ss2_0(pack_s2(rand_ss2_0));
         s.set_rand_ss3_0(pack_s3(rand_ss3_0));
@@ -381,31 +381,6 @@
         s.set_rand_ss2_1(pack_s2(rand_ss2_1));
         s.set_rand_ss3_1(pack_s3(rand_ss3_1));
         s.set_rand_ss4_1(pack_s4(rand_ss4_1));
-        s.set_rand_si1_0(rand_si1_0);
-        s.set_rand_si2_0(pack_i2(rand_si2_0));
-        s.set_rand_si3_0(pack_i3(rand_si3_0));
-        s.set_rand_si4_0(pack_i4(rand_si4_0));
-        s.set_rand_si1_1(rand_si1_1);
-        s.set_rand_si2_1(pack_i2(rand_si2_1));
-        s.set_rand_si3_1(pack_i3(rand_si3_1));
-        s.set_rand_si4_1(pack_i4(rand_si4_1));
-        s.set_rand_sl1_0(rand_sl1_0);
-        s.set_rand_sl2_0(pack_l2(rand_sl2_0));
-        s.set_rand_sl3_0(pack_l3(rand_sl3_0));
-        s.set_rand_sl4_0(pack_l4(rand_sl4_0));
-        s.set_rand_sl1_1(rand_sl1_1);
-        s.set_rand_sl2_1(pack_l2(rand_sl2_1));
-        s.set_rand_sl3_1(pack_l3(rand_sl3_1));
-        s.set_rand_sl4_1(pack_l4(rand_sl4_1));
-        // FIXME:  set signed char input vectors once bug is fixed
-        /*
-        s.set_rand_sc1_0(rand_sc1_0);
-        s.set_rand_sc2_0(pack_b2(rand_sc2_0));
-        s.set_rand_sc3_0(pack_b3(rand_sc3_0));
-        s.set_rand_sc4_0(pack_b4(rand_sc4_0));
-        */
-        // FIXME:  set unsigned input vectors once bug 6764163 is fixed
-        /*
         s.set_rand_us1_0(rand_us1_0);
         s.set_rand_us2_0(pack_i2(rand_us2_0));
         s.set_rand_us3_0(pack_i3(rand_us3_0));
@@ -414,14 +389,14 @@
         s.set_rand_us2_1(pack_i2(rand_us2_1));
         s.set_rand_us3_1(pack_i3(rand_us3_1));
         s.set_rand_us4_1(pack_i4(rand_us4_1));
-        s.set_rand_uc1_0(rand_uc1_0);
-        s.set_rand_uc2_0(pack_s2(rand_uc2_0));
-        s.set_rand_uc3_0(pack_s3(rand_uc3_0));
-        s.set_rand_uc4_0(pack_s4(rand_uc4_0));
-        s.set_rand_uc1_1(rand_uc1_1);
-        s.set_rand_uc2_1(pack_s2(rand_uc2_1));
-        s.set_rand_uc3_1(pack_s3(rand_uc3_1));
-        s.set_rand_uc4_1(pack_s4(rand_uc4_1));
+        s.set_rand_si1_0(rand_si1_0);
+        s.set_rand_si2_0(pack_i2(rand_si2_0));
+        s.set_rand_si3_0(pack_i3(rand_si3_0));
+        s.set_rand_si4_0(pack_i4(rand_si4_0));
+        s.set_rand_si1_1(rand_si1_1);
+        s.set_rand_si2_1(pack_i2(rand_si2_1));
+        s.set_rand_si3_1(pack_i3(rand_si3_1));
+        s.set_rand_si4_1(pack_i4(rand_si4_1));
         s.set_rand_ui1_0(rand_ui1_0);
         s.set_rand_ui2_0(pack_l2(rand_ui2_0));
         s.set_rand_ui3_0(pack_l3(rand_ui3_0));
@@ -430,6 +405,28 @@
         s.set_rand_ui2_1(pack_l2(rand_ui2_1));
         s.set_rand_ui3_1(pack_l3(rand_ui3_1));
         s.set_rand_ui4_1(pack_l4(rand_ui4_1));
+        s.set_rand_sl1_0(rand_sl1_0);
+        s.set_rand_sl2_0(pack_l2(rand_sl2_0));
+        s.set_rand_sl3_0(pack_l3(rand_sl3_0));
+        s.set_rand_sl4_0(pack_l4(rand_sl4_0));
+        s.set_rand_sl1_1(rand_sl1_1);
+        s.set_rand_sl2_1(pack_l2(rand_sl2_1));
+        s.set_rand_sl3_1(pack_l3(rand_sl3_1));
+        s.set_rand_sl4_1(pack_l4(rand_sl4_1));
+        s.set_rand_uc1_0(rand_uc1_0);
+        s.set_rand_uc2_0(pack_s2(rand_uc2_0));
+        s.set_rand_uc3_0(pack_s3(rand_uc3_0));
+        s.set_rand_uc4_0(pack_s4(rand_uc4_0));
+        // FIXME:  set char input vectors once bug 6865598 is fixed
+        /*
+        s.set_rand_sc1_0(rand_sc1_0);
+        s.set_rand_sc2_0(pack_b2(rand_sc2_0));
+        s.set_rand_sc3_0(pack_b3(rand_sc3_0));
+        s.set_rand_sc4_0(pack_b4(rand_sc4_0));
+        s.set_rand_sc1_1(rand_sc1_1);
+        s.set_rand_sc2_1(pack_b2(rand_sc2_1));
+        s.set_rand_sc3_1(pack_b3(rand_sc3_1));
+        s.set_rand_sc4_1(pack_b4(rand_sc4_1));
         */
         // TODO:  set unsigned long vectors
 
@@ -438,40 +435,37 @@
         s.set_min_rand_f2_f2(pack_f2(min(rand_f2_0, rand_f2_1)));
         s.set_min_rand_f3_f3(pack_f3(min(rand_f3_0, rand_f3_1)));
         s.set_min_rand_f4_f4(pack_f4(min(rand_f4_0, rand_f4_1)));
+        s.set_min_rand_uc1_uc1(min(rand_uc1_0, rand_uc1_1));
+        s.set_min_rand_uc2_uc2(pack_s2(min(rand_uc2_0, rand_uc2_1)));
+        s.set_min_rand_uc3_uc3(pack_s3(min(rand_uc3_0, rand_uc3_1)));
+        s.set_min_rand_uc4_uc4(pack_s4(min(rand_uc4_0, rand_uc4_1)));
         s.set_min_rand_ss1_ss1(min(rand_ss1_0, rand_ss1_1));
         s.set_min_rand_ss2_ss2(pack_s2(min(rand_ss2_0, rand_ss2_1)));
         s.set_min_rand_ss3_ss3(pack_s3(min(rand_ss3_0, rand_ss3_1)));
         s.set_min_rand_ss4_ss4(pack_s4(min(rand_ss4_0, rand_ss4_1)));
+        s.set_min_rand_us1_us1(min(rand_us1_0, rand_us1_1));
+        s.set_min_rand_us2_us2(pack_i2(min(rand_us2_0, rand_us2_1)));
+        s.set_min_rand_us3_us3(pack_i3(min(rand_us3_0, rand_us3_1)));
+        s.set_min_rand_us4_us4(pack_i4(min(rand_us4_0, rand_us4_1)));
         s.set_min_rand_si1_si1(min(rand_si1_0, rand_si1_1));
         s.set_min_rand_si2_si2(pack_i2(min(rand_si2_0, rand_si2_1)));
         s.set_min_rand_si3_si3(pack_i3(min(rand_si3_0, rand_si3_1)));
         s.set_min_rand_si4_si4(pack_i4(min(rand_si4_0, rand_si4_1)));
+        s.set_min_rand_ui1_ui1(min(rand_ui1_0, rand_ui1_1));
+        s.set_min_rand_ui2_ui2(pack_l2(min(rand_ui2_0, rand_ui2_1)));
+        s.set_min_rand_ui3_ui3(pack_l3(min(rand_ui3_0, rand_ui3_1)));
+        s.set_min_rand_ui4_ui4(pack_l4(min(rand_ui4_0, rand_ui4_1)));
         s.set_min_rand_sl1_sl1(min(rand_sl1_0, rand_sl1_1));
         s.set_min_rand_sl2_sl2(pack_l2(min(rand_sl2_0, rand_sl2_1)));
         s.set_min_rand_sl3_sl3(pack_l3(min(rand_sl3_0, rand_sl3_1)));
         s.set_min_rand_sl4_sl4(pack_l4(min(rand_sl4_0, rand_sl4_1)));
-        // FIXME:  set signed char min reference vectors once bug is fixed
+        // FIXME:  set char min reference vectors once bug 6865598 is fixed
         /*
         s.set_min_rand_sc1_sc1(min(rand_sc1_0, rand_sc1_1));
         s.set_min_rand_sc2_sc2(pack_b2(min(rand_sc2_0, rand_sc2_1)));
         s.set_min_rand_sc3_sc3(pack_b3(min(rand_sc3_0, rand_sc3_1)));
         s.set_min_rand_sc4_sc4(pack_b4(min(rand_sc4_0, rand_sc4_1)));
         */
-        // FIXME:  set unsigned min reference vectors once bug 6764163 is fixed
-        /*
-        s.set_min_rand_uc1_uc1(min(rand_uc1_0, rand_uc1_1));
-        s.set_min_rand_uc2_uc2(pack_s3(min(rand_uc2_0, rand_uc2_1)));
-        s.set_min_rand_uc3_uc3(pack_s3(min(rand_uc3_0, rand_uc3_1)));
-        s.set_min_rand_uc4_uc4(pack_s4(min(rand_uc4_0, rand_uc4_1)));
-        s.set_min_rand_us1_us1(min(rand_us1_0, rand_us1_1));
-        s.set_min_rand_us2_us2(pack_i2(min(rand_us2_0, rand_us2_1)));
-        s.set_min_rand_us3_us3(pack_i3(min(rand_us3_0, rand_us3_1)));
-        s.set_min_rand_us4_us4(pack_i4(min(rand_us4_0, rand_us4_1)));
-        s.set_min_rand_ui1_ui1(min(rand_ui1_0, rand_ui1_1));
-        s.set_min_rand_ui2_ui2(pack_l2(min(rand_ui2_0, rand_ui2_1)));
-        s.set_min_rand_ui3_ui3(pack_l3(min(rand_ui3_0, rand_ui3_1)));
-        s.set_min_rand_ui4_ui4(pack_l4(min(rand_ui4_0, rand_ui4_1)));
-        */
         // TODO:  set results for unsigned long min
 
         // Set results for max
@@ -479,40 +473,38 @@
         s.set_max_rand_f2_f2(pack_f2(max(rand_f2_0, rand_f2_1)));
         s.set_max_rand_f3_f3(pack_f3(max(rand_f3_0, rand_f3_1)));
         s.set_max_rand_f4_f4(pack_f4(max(rand_f4_0, rand_f4_1)));
+        s.set_max_rand_uc1_uc1(max(rand_uc1_0, rand_uc1_1));
+        s.set_max_rand_uc2_uc2(pack_s2(max(rand_uc2_0, rand_uc2_1)));
+        s.set_max_rand_uc3_uc3(pack_s3(max(rand_uc3_0, rand_uc3_1)));
+        s.set_max_rand_uc4_uc4(pack_s4(max(rand_uc4_0, rand_uc4_1)));
         s.set_max_rand_ss1_ss1(max(rand_ss1_0, rand_ss1_1));
         s.set_max_rand_ss2_ss2(pack_s2(max(rand_ss2_0, rand_ss2_1)));
         s.set_max_rand_ss3_ss3(pack_s3(max(rand_ss3_0, rand_ss3_1)));
         s.set_max_rand_ss4_ss4(pack_s4(max(rand_ss4_0, rand_ss4_1)));
+        s.set_max_rand_us1_us1(max(rand_us1_0, rand_us1_1));
+        s.set_max_rand_us2_us2(pack_i2(max(rand_us2_0, rand_us2_1)));
+        s.set_max_rand_us3_us3(pack_i3(max(rand_us3_0, rand_us3_1)));
+        s.set_max_rand_us4_us4(pack_i4(max(rand_us4_0, rand_us4_1)));
         s.set_max_rand_si1_si1(max(rand_si1_0, rand_si1_1));
         s.set_max_rand_si2_si2(pack_i2(max(rand_si2_0, rand_si2_1)));
         s.set_max_rand_si3_si3(pack_i3(max(rand_si3_0, rand_si3_1)));
         s.set_max_rand_si4_si4(pack_i4(max(rand_si4_0, rand_si4_1)));
+        s.set_max_rand_ui1_ui1(max(rand_ui1_0, rand_ui1_1));
+        s.set_max_rand_ui2_ui2(pack_l2(max(rand_ui2_0, rand_ui2_1)));
+        s.set_max_rand_ui3_ui3(pack_l3(max(rand_ui3_0, rand_ui3_1)));
+        s.set_max_rand_ui4_ui4(pack_l4(max(rand_ui4_0, rand_ui4_1)));
         s.set_max_rand_sl1_sl1(max(rand_sl1_0, rand_sl1_1));
         s.set_max_rand_sl2_sl2(pack_l2(max(rand_sl2_0, rand_sl2_1)));
         s.set_max_rand_sl3_sl3(pack_l3(max(rand_sl3_0, rand_sl3_1)));
         s.set_max_rand_sl4_sl4(pack_l4(max(rand_sl4_0, rand_sl4_1)));
-        // FIXME:  set signed char max reference vectors once bug is fixed
+        // FIXME:  set signed char max reference vectors once bug 6865598 is fixed
         /*
         s.set_max_rand_sc1_sc1(max(rand_sc1_0, rand_sc1_1));
         s.set_max_rand_sc2_sc2(pack_b2(max(rand_sc2_0, rand_sc2_1)));
         s.set_max_rand_sc3_sc3(pack_b3(max(rand_sc3_0, rand_sc3_1)));
         s.set_max_rand_sc4_sc4(pack_b4(max(rand_sc4_0, rand_sc4_1)));
         */
-        // FIXME:  set unsigned max reference vectors once bug 6764163 is fixed
-        /*
-        s.set_max_rand_uc1_uc1(max(rand_uc1_0, rand_uc1_1));
-        s.set_max_rand_uc2_uc2(pack_s3(max(rand_uc2_0, rand_uc2_1)));
-        s.set_max_rand_uc3_uc3(pack_s3(max(rand_uc3_0, rand_uc3_1)));
-        s.set_max_rand_uc4_uc4(pack_s4(max(rand_uc4_0, rand_uc4_1)));
-        s.set_max_rand_us1_us1(max(rand_us1_0, rand_us1_1));
-        s.set_max_rand_us2_us2(pack_i2(max(rand_us2_0, rand_us2_1)));
-        s.set_max_rand_us3_us3(pack_i3(max(rand_us3_0, rand_us3_1)));
-        s.set_max_rand_us4_us4(pack_i4(max(rand_us4_0, rand_us4_1)));
-        s.set_max_rand_ui1_ui1(max(rand_ui1_0, rand_ui1_1));
-        s.set_max_rand_ui2_ui2(pack_l2(max(rand_ui2_0, rand_ui2_1)));
-        s.set_max_rand_ui3_ui3(pack_l3(max(rand_ui3_0, rand_ui3_1)));
-        s.set_max_rand_ui4_ui4(pack_l4(max(rand_ui4_0, rand_ui4_1)));
-        */
+
         // TODO:  set results for unsigned long max
 
         // Set results for fmin
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_unsigned.java b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_unsigned.java
new file mode 100644
index 0000000..2164766
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/UT_unsigned.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2012 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.rs.test;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class UT_unsigned extends UnitTest {
+    private Resources mRes;
+
+    protected UT_unsigned(RSTestCore rstc, Resources res, Context ctx) {
+        super(rstc, "Unsigned", ctx);
+        mRes = res;
+    }
+
+    private boolean initializeGlobals(ScriptC_unsigned s) {
+        short pUC = s.get_uc();
+        if (pUC != 5) {
+            return false;
+        }
+        s.set_uc((short)129);
+
+        long pUI = s.get_ui();
+        if (pUI != 37) {
+            return false;
+        }
+        s.set_ui(0x7fffffff);
+
+        return true;
+    }
+
+    public void run() {
+        RenderScript pRS = RenderScript.create(mCtx);
+        ScriptC_unsigned s = new ScriptC_unsigned(pRS, mRes, R.raw.unsigned);
+        pRS.setMessageHandler(mRsMessage);
+        if (!initializeGlobals(s)) {
+            failTest();
+        } else {
+            s.invoke_unsigned_test();
+            pRS.finish();
+            waitForMessage();
+        }
+        pRS.destroy();
+    }
+}
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/math_agree.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/math_agree.rs
index ac3a3fa..1adb036 100644
--- a/tests/RenderScriptTests/tests/src/com/android/rs/test/math_agree.rs
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/math_agree.rs
@@ -337,15 +337,16 @@
 TEST_UL4_UL4(func)
 
 #define TEST_VEC_VEC_ALL(func)  \
-TEST_FN_FN_ALL(func)              \
-TEST_SS_SS_ALL(func)            \
-TEST_SI_SI_ALL(func)
-// FIXME:  Add tests back in once bug 6764163 is fixed
-#if 0
-TEST_SC_SC_ALL(func)            \
-TEST_US_US_ALL(func)            \
+TEST_FN_FN_ALL(func)            \
 TEST_UC_UC_ALL(func)            \
+TEST_SS_SS_ALL(func)            \
+TEST_US_US_ALL(func)            \
+TEST_SI_SI_ALL(func)            \
 TEST_UI_UI_ALL(func)
+
+// FIXME:  Add char tests back in once bug 6865598 is fixed
+#if 0
+TEST_SC_SC_ALL(func)
 #endif
 // TODO:  add long types to ALL macro
 #if 0
diff --git a/tests/RenderScriptTests/tests/src/com/android/rs/test/unsigned.rs b/tests/RenderScriptTests/tests/src/com/android/rs/test/unsigned.rs
new file mode 100644
index 0000000..2c056f4
--- /dev/null
+++ b/tests/RenderScriptTests/tests/src/com/android/rs/test/unsigned.rs
@@ -0,0 +1,36 @@
+#include "shared.rsh"
+
+// Testing unsigned types for Bug 6764163
+unsigned int ui = 37;
+unsigned char uc = 5;
+
+static bool test_unsigned() {
+    bool failed = false;
+
+    rsDebug("ui", ui);
+    rsDebug("uc", uc);
+    _RS_ASSERT(ui == 0x7fffffff);
+    _RS_ASSERT(uc == 129);
+
+    if (failed) {
+        rsDebug("test_unsigned FAILED", -1);
+    }
+    else {
+        rsDebug("test_unsigned PASSED", 0);
+    }
+
+    return failed;
+}
+
+void unsigned_test() {
+    bool failed = false;
+    failed |= test_unsigned();
+
+    if (failed) {
+        rsSendToClientBlocking(RS_MSG_TEST_FAILED);
+    }
+    else {
+        rsSendToClientBlocking(RS_MSG_TEST_PASSED);
+    }
+}
+
diff --git a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java
index 8868c65..6ccdcb6 100644
--- a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java
@@ -31,57 +31,4 @@
  */
 public class Display_Delegate {
 
-    // ---- Overridden methods ----
-
-    @LayoutlibDelegate
-    public static IWindowManager getWindowManager() {
-        return RenderAction.getCurrentContext().getIWindowManager();
-    }
-
-    // ---- Native methods ----
-
-    @LayoutlibDelegate
-    /*package*/ static int getDisplayCount() {
-        return 1;
-    }
-
-    @LayoutlibDelegate
-    /** @hide special for when we are faking the screen size. */
-    /*package*/ static int getRawWidthNative(Display theDisplay) {
-        // same as real since we're not faking compatibility mode.
-        return RenderAction.getCurrentContext().getIWindowManager().getMetrics().widthPixels;
-    }
-
-    @LayoutlibDelegate
-    /** @hide special for when we are faking the screen size. */
-    /*package*/ static int getRawHeightNative(Display theDisplay) {
-        // same as real since we're not faking compatibility mode.
-        return RenderAction.getCurrentContext().getIWindowManager().getMetrics().heightPixels;
-    }
-
-    @LayoutlibDelegate
-    /*package*/ static int getOrientation(Display theDisplay) {
-        try {
-            // always dynamically query for the current window manager
-            return getWindowManager().getRotation();
-        } catch (RemoteException e) {
-            // this will never been thrown since this is not a true RPC.
-        }
-
-        return Surface.ROTATION_0;
-    }
-
-    @LayoutlibDelegate
-    /*package*/ static void nativeClassInit() {
-        // not needed for now.
-    }
-
-    @LayoutlibDelegate
-    /*package*/ static void init(Display theDisplay, int display) {
-        // always dynamically query for the current window manager
-        BridgeWindowManager wm = RenderAction.getCurrentContext().getIWindowManager();
-        theDisplay.mDensity = wm.getMetrics().density;
-        theDisplay.mDpiX = wm.getMetrics().xdpi;
-        theDisplay.mDpiY = wm.getMetrics().ydpi;
-    }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
index 3e56b60..2619dd8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java
@@ -29,6 +29,7 @@
 import android.os.RemoteException;
 import android.util.DisplayMetrics;
 import android.view.Display;
+import android.view.DisplayInfo;
 import android.view.Display_Delegate;
 import android.view.Gravity;
 import android.view.IApplicationToken;
@@ -69,23 +70,6 @@
         return mRotation;
     }
 
-    @Override
-    public int getMaximumSizeDimension() throws RemoteException {
-        return 0;
-    }
-
-    @Override
-    public void getCurrentSizeRange(Point smallestSize, Point largestSize) {
-    }
-
-    @Override
-    public void getDisplaySize(Point arg0) throws RemoteException {
-    }
-
-    @Override
-    public void getRealDisplaySize(Point arg0) throws RemoteException {
-    }
-
     // ---- unused implementation of IWindowManager ----
 
     @Override
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 36f38f9..6e58a2d 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -23,13 +23,17 @@
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.WorkSource;
 import android.os.Messenger;
+import android.util.Log;
 import android.util.SparseArray;
 
+import java.util.concurrent.CountDownLatch;
+
 import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Protocol;
 
@@ -58,6 +62,7 @@
  */
 public class WifiManager {
 
+    private static final String TAG = "WifiManager";
     // Supplicant error codes:
     /**
      * The error code if there was a problem authenticating.
@@ -481,9 +486,6 @@
     /** @hide */
     public static final int DATA_ACTIVITY_INOUT        = 0x03;
 
-    IWifiManager mService;
-    Handler mHandler;
-
     /* Maximum number of active locks we allow.
      * This limit was added to prevent apps from creating a ridiculous number
      * of locks and crashing the system by overflowing the global ref table.
@@ -493,19 +495,33 @@
     /* Number of currently active WifiLocks and MulticastLocks */
     private int mActiveLockCount;
 
+    private Context mContext;
+    IWifiManager mService;
+
+    private static final int INVALID_KEY = 0;
+    private int mListenerKey = 1;
+    private final SparseArray mListenerMap = new SparseArray();
+    private final Object mListenerMapLock = new Object();
+
+    private AsyncChannel mAsyncChannel = new AsyncChannel();
+    private ServiceHandler mHandler;
+    private Messenger mWifiServiceMessenger;
+    private final CountDownLatch mConnected = new CountDownLatch(1);
+
     /**
      * Create a new WifiManager instance.
      * Applications will almost always want to use
      * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
      * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}.
+     * @param context the application context
      * @param service the Binder interface
-     * @param handler target for messages
      * @hide - hide this because it takes in a parameter of type IWifiManager, which
      * is a system private class.
      */
-    public WifiManager(IWifiManager service, Handler handler) {
+    public WifiManager(Context context, IWifiManager service) {
+        mContext = context;
         mService = service;
-        mHandler = handler;
+        init();
     }
 
     /**
@@ -1168,15 +1184,6 @@
     /** WPS timed out {@hide} */
     public static final int WPS_TIMED_OUT               = 7;
 
-    /** Interface for callback invocation when framework channel is lost {@hide} */
-    public interface ChannelListener {
-        /**
-         * The channel to the framework has been disconnected.
-         * Application could try re-initializing using {@link #initialize}
-         */
-        public void onChannelDisconnected();
-    }
-
     /** Interface for callback invocation on an application action {@hide} */
     public interface ActionListener {
         /** The operation succeeded */
@@ -1205,132 +1212,120 @@
         public void onFailure(int reason);
     }
 
-    /**
-     * A channel that connects the application to the Wifi framework.
-     * Most operations require a Channel as an argument. An instance of Channel is obtained
-     * by doing a call on {@link #initialize}
-     * @hide
-     */
-    public static class Channel {
-        Channel(Looper looper, ChannelListener l) {
-            mAsyncChannel = new AsyncChannel();
-            mHandler = new WifiHandler(looper);
-            mChannelListener = l;
-        }
-        private ChannelListener mChannelListener;
-        private SparseArray<Object> mListenerMap = new SparseArray<Object>();
-        private Object mListenerMapLock = new Object();
-        private int mListenerKey = 0;
-        private static final int INVALID_KEY = -1;
-
-        AsyncChannel mAsyncChannel;
-        WifiHandler mHandler;
-        class WifiHandler extends Handler {
-            WifiHandler(Looper looper) {
-                super(looper);
-            }
-
-            @Override
-            public void handleMessage(Message message) {
-                Object listener = removeListener(message.arg2);
-                switch (message.what) {
-                    case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
-                        if (mChannelListener != null) {
-                            mChannelListener.onChannelDisconnected();
-                            mChannelListener = null;
-                        }
-                        break;
-                        /* ActionListeners grouped together */
-                    case WifiManager.CONNECT_NETWORK_FAILED:
-                    case WifiManager.FORGET_NETWORK_FAILED:
-                    case WifiManager.SAVE_NETWORK_FAILED:
-                    case WifiManager.CANCEL_WPS_FAILED:
-                    case WifiManager.DISABLE_NETWORK_FAILED:
-                        if (listener != null) {
-                            ((ActionListener) listener).onFailure(message.arg1);
-                        }
-                        break;
-                        /* ActionListeners grouped together */
-                    case WifiManager.CONNECT_NETWORK_SUCCEEDED:
-                    case WifiManager.FORGET_NETWORK_SUCCEEDED:
-                    case WifiManager.SAVE_NETWORK_SUCCEEDED:
-                    case WifiManager.CANCEL_WPS_SUCCEDED:
-                    case WifiManager.DISABLE_NETWORK_SUCCEEDED:
-                        if (listener != null) {
-                            ((ActionListener) listener).onSuccess();
-                        }
-                        break;
-                    case WifiManager.START_WPS_SUCCEEDED:
-                        if (listener != null) {
-                            WpsResult result = (WpsResult) message.obj;
-                            ((WpsListener) listener).onStartSuccess(result.pin);
-                            //Listener needs to stay until completion or failure
-                            synchronized(mListenerMapLock) {
-                                mListenerMap.put(message.arg2, listener);
-                            }
-                        }
-                        break;
-                    case WifiManager.WPS_COMPLETED:
-                        if (listener != null) {
-                            ((WpsListener) listener).onCompletion();
-                        }
-                        break;
-                    case WifiManager.WPS_FAILED:
-                        if (listener != null) {
-                            ((WpsListener) listener).onFailure(message.arg1);
-                        }
-                        break;
-                    default:
-                        //ignore
-                        break;
-                }
-            }
+    private class ServiceHandler extends Handler {
+        ServiceHandler(Looper looper) {
+            super(looper);
         }
 
-        int putListener(Object listener) {
-            if (listener == null) return INVALID_KEY;
-            int key;
-            synchronized (mListenerMapLock) {
-                do {
-                    key = mListenerKey++;
-                } while (key == INVALID_KEY);
-                mListenerMap.put(key, listener);
-            }
-            return key;
-        }
-
-        Object removeListener(int key) {
-            if (key == INVALID_KEY) return null;
-            synchronized (mListenerMapLock) {
-                Object listener = mListenerMap.get(key);
-                mListenerMap.remove(key);
-                return listener;
+        @Override
+        public void handleMessage(Message message) {
+            Object listener = removeListener(message.arg2);
+            switch (message.what) {
+                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
+                    if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
+                        mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
+                    } else {
+                        Log.e(TAG, "Failed to set up channel connection");
+                        // This will cause all further async API calls on the WifiManager
+                        // to fail and throw an exception
+                        mAsyncChannel = null;
+                    }
+                    mConnected.countDown();
+                    break;
+                case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
+                    // Ignore
+                    break;
+                case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
+                    Log.e(TAG, "Channel connection lost");
+                    // This will cause all further async API calls on the WifiManager
+                    // to fail and throw an exception
+                    mAsyncChannel = null;
+                    break;
+                    /* ActionListeners grouped together */
+                case WifiManager.CONNECT_NETWORK_FAILED:
+                case WifiManager.FORGET_NETWORK_FAILED:
+                case WifiManager.SAVE_NETWORK_FAILED:
+                case WifiManager.CANCEL_WPS_FAILED:
+                case WifiManager.DISABLE_NETWORK_FAILED:
+                    if (listener != null) {
+                        ((ActionListener) listener).onFailure(message.arg1);
+                    }
+                    break;
+                    /* ActionListeners grouped together */
+                case WifiManager.CONNECT_NETWORK_SUCCEEDED:
+                case WifiManager.FORGET_NETWORK_SUCCEEDED:
+                case WifiManager.SAVE_NETWORK_SUCCEEDED:
+                case WifiManager.CANCEL_WPS_SUCCEDED:
+                case WifiManager.DISABLE_NETWORK_SUCCEEDED:
+                    if (listener != null) {
+                        ((ActionListener) listener).onSuccess();
+                    }
+                    break;
+                case WifiManager.START_WPS_SUCCEEDED:
+                    if (listener != null) {
+                        WpsResult result = (WpsResult) message.obj;
+                        ((WpsListener) listener).onStartSuccess(result.pin);
+                        //Listener needs to stay until completion or failure
+                        synchronized(mListenerMapLock) {
+                            mListenerMap.put(message.arg2, listener);
+                        }
+                    }
+                    break;
+                case WifiManager.WPS_COMPLETED:
+                    if (listener != null) {
+                        ((WpsListener) listener).onCompletion();
+                    }
+                    break;
+                case WifiManager.WPS_FAILED:
+                    if (listener != null) {
+                        ((WpsListener) listener).onFailure(message.arg1);
+                    }
+                    break;
+                default:
+                    //ignore
+                    break;
             }
         }
     }
 
-    /**
-     * Registers the application with the Wi-Fi framework. This function
-     * must be the first to be called before any Wi-Fi operations are performed.
-     *
-     * @param srcContext is the context of the source
-     * @param srcLooper is the Looper on which the callbacks are receivied
-     * @param listener for callback at loss of framework communication. Can be null.
-     * @return Channel instance that is necessary for performing any further Wi-Fi operations.
-     *         A null is returned upon failure to initialize.
-     * @hide
-     */
-    public Channel initialize(Context srcContext, Looper srcLooper, ChannelListener listener) {
-        Messenger messenger = getWifiServiceMessenger();
-        if (messenger == null) return null;
-
-        Channel c = new Channel(srcLooper, listener);
-        if (c.mAsyncChannel.connectSync(srcContext, c.mHandler, messenger)
-                == AsyncChannel.STATUS_SUCCESSFUL) {
-            return c;
-        } else {
-            return null;
+    private int putListener(Object listener) {
+        if (listener == null) return INVALID_KEY;
+        int key;
+        synchronized (mListenerMapLock) {
+            do {
+                key = mListenerKey++;
+            } while (key == INVALID_KEY);
+            mListenerMap.put(key, listener);
         }
+        return key;
+    }
+
+    private Object removeListener(int key) {
+        if (key == INVALID_KEY) return null;
+        synchronized (mListenerMapLock) {
+            Object listener = mListenerMap.get(key);
+            mListenerMap.remove(key);
+            return listener;
+        }
+    }
+
+    private void init() {
+        mWifiServiceMessenger = getWifiServiceMessenger();
+        if (mWifiServiceMessenger == null) throw new RuntimeException("Failed to initialize");
+        HandlerThread t = new HandlerThread("WifiManager");
+        t.start();
+        mHandler = new ServiceHandler(t.getLooper());
+        mAsyncChannel.connect(mContext, mHandler, mWifiServiceMessenger);
+        try {
+            mConnected.await();
+        } catch (InterruptedException e) {
+            Log.e(TAG, "interrupted wait at init");
+        }
+    }
+
+    private void validateChannel() {
+        if (mAsyncChannel == null) throw new IllegalStateException(
+                "Bad WifiManager instance state, re-initialize");
     }
 
     /**
@@ -1341,20 +1336,21 @@
      * sequence of addNetwork(), enableNetwork(), saveConfiguration() and
      * reconnect()
      *
-     * @param c is the channel created at {@link #initialize}
      * @param config the set of variables that describe the configuration,
      *            contained in a {@link WifiConfiguration} object.
      * @param listener for callbacks on success or failure. Can be null.
+     * @throws IllegalStateException if the WifiManager instance needs to be
+     * initialized again
+     *
      * @hide
      */
-    public void connect(Channel c, WifiConfiguration config, ActionListener listener) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+    public void connect(WifiConfiguration config, ActionListener listener) {
         if (config == null) throw new IllegalArgumentException("config cannot be null");
-
+        validateChannel();
         // Use INVALID_NETWORK_ID for arg1 when passing a config object
         // arg1 is used to pass network id when the network already exists
-        c.mAsyncChannel.sendMessage(CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID,
-                c.putListener(listener), config);
+        mAsyncChannel.sendMessage(CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID,
+                putListener(listener), config);
     }
 
     /**
@@ -1363,17 +1359,17 @@
      * This function is used instead of a enableNetwork(), saveConfiguration() and
      * reconnect()
      *
-     * @param c is the channel created at {@link #initialize}
      * @param networkId the network id identifiying the network in the
      *                supplicant configuration list
      * @param listener for callbacks on success or failure. Can be null.
+     * @throws IllegalStateException if the WifiManager instance needs to be
+     * initialized again
      * @hide
      */
-    public void connect(Channel c, int networkId, ActionListener listener) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+    public void connect(int networkId, ActionListener listener) {
         if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative");
-
-        c.mAsyncChannel.sendMessage(CONNECT_NETWORK, networkId, c.putListener(listener));
+        validateChannel();
+        mAsyncChannel.sendMessage(CONNECT_NETWORK, networkId, putListener(listener));
     }
 
     /**
@@ -1387,17 +1383,17 @@
      * For an existing network, it accomplishes the task of updateNetwork()
      * and saveConfiguration()
      *
-     * @param c is the channel created at {@link #initialize}
      * @param config the set of variables that describe the configuration,
      *            contained in a {@link WifiConfiguration} object.
      * @param listener for callbacks on success or failure. Can be null.
+     * @throws IllegalStateException if the WifiManager instance needs to be
+     * initialized again
      * @hide
      */
-    public void save(Channel c, WifiConfiguration config, ActionListener listener) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+    public void save(WifiConfiguration config, ActionListener listener) {
         if (config == null) throw new IllegalArgumentException("config cannot be null");
-
-        c.mAsyncChannel.sendMessage(SAVE_NETWORK, 0, c.putListener(listener), config);
+        validateChannel();
+        mAsyncChannel.sendMessage(SAVE_NETWORK, 0, putListener(listener), config);
     }
 
     /**
@@ -1406,64 +1402,62 @@
      * This function is used instead of a sequence of removeNetwork()
      * and saveConfiguration().
      *
-     * @param c is the channel created at {@link #initialize}
      * @param config the set of variables that describe the configuration,
      *            contained in a {@link WifiConfiguration} object.
      * @param listener for callbacks on success or failure. Can be null.
+     * @throws IllegalStateException if the WifiManager instance needs to be
+     * initialized again
      * @hide
      */
-    public void forget(Channel c, int netId, ActionListener listener) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+    public void forget(int netId, ActionListener listener) {
         if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
-
-        c.mAsyncChannel.sendMessage(FORGET_NETWORK, netId, c.putListener(listener));
+        validateChannel();
+        mAsyncChannel.sendMessage(FORGET_NETWORK, netId, putListener(listener));
     }
 
     /**
      * Disable network
      *
-     * @param c is the channel created at {@link #initialize}
      * @param netId is the network Id
      * @param listener for callbacks on success or failure. Can be null.
+     * @throws IllegalStateException if the WifiManager instance needs to be
+     * initialized again
      * @hide
      */
-    public void disable(Channel c, int netId, ActionListener listener) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+    public void disable(int netId, ActionListener listener) {
         if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
-
-        c.mAsyncChannel.sendMessage(DISABLE_NETWORK, netId, c.putListener(listener));
+        validateChannel();
+        mAsyncChannel.sendMessage(DISABLE_NETWORK, netId, putListener(listener));
     }
 
     /**
      * Start Wi-fi Protected Setup
      *
-     * @param c is the channel created at {@link #initialize}
      * @param config WPS configuration
      * @param listener for callbacks on success or failure. Can be null.
+     * @throws IllegalStateException if the WifiManager instance needs to be
+     * initialized again
      * @hide
      */
-    public void startWps(Channel c, WpsInfo config, WpsListener listener) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+    public void startWps(WpsInfo config, WpsListener listener) {
         if (config == null) throw new IllegalArgumentException("config cannot be null");
-
-        c.mAsyncChannel.sendMessage(START_WPS, 0, c.putListener(listener), config);
+        validateChannel();
+        mAsyncChannel.sendMessage(START_WPS, 0, putListener(listener), config);
     }
 
     /**
      * Cancel any ongoing Wi-fi Protected Setup
      *
-     * @param c is the channel created at {@link #initialize}
      * @param listener for callbacks on success or failure. Can be null.
+     * @throws IllegalStateException if the WifiManager instance needs to be
+     * initialized again
      * @hide
      */
-    public void cancelWps(Channel c, ActionListener listener) {
-        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
-
-        c.mAsyncChannel.sendMessage(CANCEL_WPS, 0, c.putListener(listener));
+    public void cancelWps(ActionListener listener) {
+        validateChannel();
+        mAsyncChannel.sendMessage(CANCEL_WPS, 0, putListener(listener));
     }
 
-
-
     /**
      * Get a reference to WifiService handler. This is used by a client to establish
      * an AsyncChannel communication with WifiService
@@ -1492,8 +1486,6 @@
         }
     }
 
-
-
     /**
      * Returns the file in which IP and proxy configuration data is stored
      * @hide