Merge "Assume a PTS of 0 if absent, don't bail on fragmented PES packets not having PTS" into ics-mr0
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index d65e6df..9bd4a3b 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -1464,6 +1464,8 @@
         private static final String KEY_MAX_NUM_DETECTED_FACES_SW = "max-num-detected-faces-sw";
         private static final String KEY_RECORDING_HINT = "recording-hint";
         private static final String KEY_VIDEO_SNAPSHOT_SUPPORTED = "video-snapshot-supported";
+        private static final String KEY_VIDEO_STABILIZATION = "video-stabilization";
+        private static final String KEY_VIDEO_STABILIZATION_SUPPORTED = "video-stabilization-supported";
 
         // Parameter key suffix for supported values.
         private static final String SUPPORTED_VALUES_SUFFIX = "-values";
@@ -2443,7 +2445,7 @@
          *
          * @param value new white balance.
          * @see #getWhiteBalance()
-         * @see #setAutoWhiteBalanceLock()
+         * @see #setAutoWhiteBalanceLock(boolean)
          */
         public void setWhiteBalance(String value) {
             set(KEY_WHITE_BALANCE, value);
@@ -3208,6 +3210,59 @@
             return TRUE.equals(str);
         }
 
+        /**
+         * <p>Enables and disables video stabilization. Use
+         * {@link #isVideoStabilizationSupported} to determine if calling this
+         * method is valid.</p>
+         *
+         * <p>Video stabilization reduces the shaking due to the motion of the
+         * camera in both the preview stream and in recorded videos, including
+         * data received from the preview callback. It does not reduce motion
+         * blur in images captured with
+         * {@link Camera#takePicture takePicture}.</p>
+         *
+         * <p>Video stabilization can be enabled and disabled while preview or
+         * recording is active, but toggling it may cause a jump in the video
+         * stream that may be undesirable in a recorded video.</p>
+         *
+         * @param toggle Set to true to enable video stabilization, and false to
+         * disable video stabilization.
+         * @see #isVideoStabilizationSupported()
+         * @see #getVideoStabilization()
+         * @hide
+         */
+        public void setVideoStabilization(boolean toggle) {
+            set(KEY_VIDEO_STABILIZATION, toggle ? TRUE : FALSE);
+        }
+
+        /**
+         * Get the current state of video stabilization. See
+         * {@link #setVideoStabilization} for details of video stabilization.
+         *
+         * @return true if video stabilization is enabled
+         * @see #isVideoStabilizationSupported()
+         * @see #setVideoStabilization(boolean)
+         * @hide
+         */
+        public boolean getVideoStabilization() {
+            String str = get(KEY_VIDEO_STABILIZATION);
+            return TRUE.equals(str);
+        }
+
+        /**
+         * Returns true if video stabilization is supported. See
+         * {@link #setVideoStabilization} for details of video stabilization.
+         *
+         * @return true if video stabilization is supported
+         * @see #setVideoStabilization(boolean)
+         * @see #getVideoStabilization()
+         * @hide
+         */
+        public boolean isVideoStabilizationSupported() {
+            String str = get(KEY_VIDEO_STABILIZATION_SUPPORTED);
+            return TRUE.equals(str);
+        }
+
         // Splits a comma delimited string to an ArrayList of String.
         // Return null if the passing string is null or the size is 0.
         private ArrayList<String> split(String str) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 41daf70..041e8a4 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -2476,6 +2476,7 @@
 
         if (gravity != mGravity) {
             invalidate();
+            mLayoutAlignment = null;
         }
 
         mGravity = gravity;
diff --git a/core/java/com/android/internal/app/PlatLogoActivity.java b/core/java/com/android/internal/app/PlatLogoActivity.java
index 9fbbb3d..a0e125a 100644
--- a/core/java/com/android/internal/app/PlatLogoActivity.java
+++ b/core/java/com/android/internal/app/PlatLogoActivity.java
@@ -17,32 +17,79 @@
 package com.android.internal.app;
 
 import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.Vibrator;
 import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
 import android.widget.ImageView;
 import android.widget.Toast;
 
 public class PlatLogoActivity extends Activity {
     Toast mToast;
+    ImageView mContent;
+    Vibrator mZzz = new Vibrator();
+    int mCount;
+    final Handler mHandler = new Handler();
+
+    Runnable mSuperLongPress = new Runnable() {
+        public void run() {
+            mCount++;
+            mZzz.vibrate(50 * mCount);
+            final float scale = 1f + 0.25f * mCount * mCount;
+            mContent.setScaleX(scale);
+            mContent.setScaleY(scale);
+
+            if (mCount <= 3) {
+                mHandler.postDelayed(mSuperLongPress, ViewConfiguration.getLongPressTimeout());
+            } else {
+                try {
+                    startActivity(new Intent(Intent.ACTION_MAIN)
+                        .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                            | Intent.FLAG_ACTIVITY_CLEAR_TASK
+                            | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
+                        .setClassName("com.android.systemui","com.android.systemui.Nyandroid"));
+                } catch (ActivityNotFoundException ex) {
+                    android.util.Log.e("PlatLogoActivity", "Couldn't find platlogo screensaver.");
+                }
+                finish();
+            }
+        }
+    };
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         
-        mToast = Toast.makeText(this, "REZZZZZZZ...", Toast.LENGTH_SHORT);
+        mToast = Toast.makeText(this, "Android 4.0: Ice Cream Sandwich", Toast.LENGTH_SHORT);
 
-        ImageView content = new ImageView(this);
-        content.setImageResource(com.android.internal.R.drawable.platlogo);
-        content.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
+        mContent = new ImageView(this);
+        mContent.setImageResource(com.android.internal.R.drawable.platlogo);
+        mContent.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
+
+        mContent.setOnTouchListener(new View.OnTouchListener() {
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                final int action = event.getAction();
+                if (action == MotionEvent.ACTION_DOWN) {
+                    mContent.setPressed(true);
+                    mHandler.removeCallbacks(mSuperLongPress);
+                    mCount = 0;
+                    mHandler.postDelayed(mSuperLongPress, 2*ViewConfiguration.getLongPressTimeout());
+                } else if (action == MotionEvent.ACTION_UP) {
+                    if (mContent.isPressed()) {
+                        mContent.setPressed(false);
+                        mHandler.removeCallbacks(mSuperLongPress);
+                        mToast.show();
+                    }
+                }
+                return true;
+            }
+        });
         
-        setContentView(content);
-    }
-
-    @Override
-    public boolean dispatchTouchEvent(MotionEvent ev) {
-        if (ev.getAction() == MotionEvent.ACTION_UP) {
-            mToast.show();
-        }
-        return super.dispatchTouchEvent(ev);
+        setContentView(mContent);
     }
 }
diff --git a/core/java/com/android/internal/view/menu/IconMenuPresenter.java b/core/java/com/android/internal/view/menu/IconMenuPresenter.java
index 3b1decd..2439b5d 100644
--- a/core/java/com/android/internal/view/menu/IconMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/IconMenuPresenter.java
@@ -22,7 +22,6 @@
 import android.os.Parcelable;
 import android.util.SparseArray;
 import android.view.ContextThemeWrapper;
-import android.view.LayoutInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
@@ -44,15 +43,14 @@
     private static final String OPEN_SUBMENU_KEY = "android:menu:icon:submenu";
 
     public IconMenuPresenter(Context context) {
-        super(context, com.android.internal.R.layout.icon_menu_layout,
+        super(new ContextThemeWrapper(context, com.android.internal.R.style.Theme_IconMenu),
+                com.android.internal.R.layout.icon_menu_layout,
                 com.android.internal.R.layout.icon_menu_item_layout);
     }
 
     @Override
     public void initForMenu(Context context, MenuBuilder menu) {
-        mContext = new ContextThemeWrapper(context, com.android.internal.R.style.Theme_IconMenu);
-        mInflater = LayoutInflater.from(mContext);
-        mMenu = menu;
+        super.initForMenu(context, menu);
         mMaxItems = -1;
     }
 
diff --git a/core/res/res/drawable-nodpi/platlogo.png b/core/res/res/drawable-nodpi/platlogo.png
index e619ed5..8aa3b9e 100644
--- a/core/res/res/drawable-nodpi/platlogo.png
+++ b/core/res/res/drawable-nodpi/platlogo.png
Binary files differ
diff --git a/docs/html/sdk/oem-usb.jd b/docs/html/sdk/oem-usb.jd
index ad3be4a..88bf008 100644
--- a/docs/html/sdk/oem-usb.jd
+++ b/docs/html/sdk/oem-usb.jd
@@ -55,6 +55,14 @@
 </tr>
   <tr>
     <td>
+      Fujitsu
+    </td>
+    <td><a
+href="http://www.fmworld.net/product/phone/sp/android/develop/">http://www.fmworld.net/product/phone/sp/android/develop/</a>
+    </td>
+  </tr>
+  <tr>
+    <td>
       Fujitsu Toshiba
     </td>
     <td><a
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index a520a6a..cd2c0a3 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -504,6 +504,25 @@
     // Example value: "true" or "false". Read only.
     static const char KEY_VIDEO_SNAPSHOT_SUPPORTED[];
 
+    // The state of the video stabilization. If set to true, both the
+    // preview stream and the recorded video stream are stabilized by
+    // the camera. Only valid to set if KEY_VIDEO_STABILIZATION_SUPPORTED is
+    // set to true.
+    //
+    // The value of this key can be changed any time the camera is
+    // open. If preview or recording is active, it is acceptable for
+    // there to be a slight video glitch when video stabilization is
+    // toggled on and off.
+    //
+    // This only stabilizes video streams (between-frames stabilization), and
+    // has no effect on still image capture.
+    static const char KEY_VIDEO_STABILIZATION[];
+
+    // Returns true if video stabilization is supported. That is, applications
+    // can set KEY_VIDEO_STABILIZATION to true and have a stabilized preview
+    // stream and record stabilized videos.
+    static const char KEY_VIDEO_STABILIZATION_SUPPORTED[];
+
     // Value for KEY_ZOOM_SUPPORTED or KEY_SMOOTH_ZOOM_SUPPORTED.
     static const char TRUE[];
     static const char FALSE[];
diff --git a/include/surfaceflinger/ISurfaceComposer.h b/include/surfaceflinger/ISurfaceComposer.h
index e0f4cf9..ea022a6 100644
--- a/include/surfaceflinger/ISurfaceComposer.h
+++ b/include/surfaceflinger/ISurfaceComposer.h
@@ -80,6 +80,7 @@
         eOrientation90          = 1,
         eOrientation180         = 2,
         eOrientation270         = 3,
+        eOrientationUnchanged   = 4,
         eOrientationSwapMask    = 0x01
     };
     
@@ -101,15 +102,8 @@
     virtual sp<IMemoryHeap> getCblk() const = 0;
 
     /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */
-    virtual void setTransactionState(const Vector<ComposerState>& state) = 0;
-
-    /* [un]freeze display. requires ACCESS_SURFACE_FLINGER permission */
-    virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags) = 0;
-    virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags) = 0;
-
-    /* Set display orientation. requires ACCESS_SURFACE_FLINGER permission
-     * No flags are currently defined.  Set flags to 0. */
-    virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags) = 0;
+    virtual void setTransactionState(const Vector<ComposerState>& state,
+            int orientation) = 0;
 
     /* signal that we're done booting.
      * Requires ACCESS_SURFACE_FLINGER permission
diff --git a/include/surfaceflinger/SurfaceComposerClient.h b/include/surfaceflinger/SurfaceComposerClient.h
index ace0735..14e5b23 100644
--- a/include/surfaceflinger/SurfaceComposerClient.h
+++ b/include/surfaceflinger/SurfaceComposerClient.h
@@ -195,4 +195,3 @@
 }; // namespace android
 
 #endif // ANDROID_SF_SURFACE_COMPOSER_CLIENT_H
-
diff --git a/libs/camera/CameraParameters.cpp b/libs/camera/CameraParameters.cpp
index 0dcab6b..c6087b4 100644
--- a/libs/camera/CameraParameters.cpp
+++ b/libs/camera/CameraParameters.cpp
@@ -88,6 +88,8 @@
 const char CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW[] = "max-num-detected-faces-sw";
 const char CameraParameters::KEY_RECORDING_HINT[] = "recording-hint";
 const char CameraParameters::KEY_VIDEO_SNAPSHOT_SUPPORTED[] = "video-snapshot-supported";
+const char CameraParameters::KEY_VIDEO_STABILIZATION[] = "video-stabilization";
+const char CameraParameters::KEY_VIDEO_STABILIZATION_SUPPORTED[] = "video-stabilization-supported";
 
 const char CameraParameters::TRUE[] = "true";
 const char CameraParameters::FALSE[] = "false";
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 030a83e..eb90147 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -78,7 +78,8 @@
         return interface_cast<IMemoryHeap>(reply.readStrongBinder());
     }
 
-    virtual void setTransactionState(const Vector<ComposerState>& state)
+    virtual void setTransactionState(const Vector<ComposerState>& state,
+            int orientation)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
@@ -88,38 +89,8 @@
         for ( ; b != e ; ++b ) {
             b->write(data);
         }
-        remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply);
-    }
-
-    virtual status_t freezeDisplay(DisplayID dpy, uint32_t flags)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-        data.writeInt32(dpy);
-        data.writeInt32(flags);
-        remote()->transact(BnSurfaceComposer::FREEZE_DISPLAY, data, &reply);
-        return reply.readInt32();
-    }
-
-    virtual status_t unfreezeDisplay(DisplayID dpy, uint32_t flags)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-        data.writeInt32(dpy);
-        data.writeInt32(flags);
-        remote()->transact(BnSurfaceComposer::UNFREEZE_DISPLAY, data, &reply);
-        return reply.readInt32();
-    }
-
-    virtual int setOrientation(DisplayID dpy, int orientation, uint32_t flags)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-        data.writeInt32(dpy);
         data.writeInt32(orientation);
-        data.writeInt32(flags);
-        remote()->transact(BnSurfaceComposer::SET_ORIENTATION, data, &reply);
-        return reply.readInt32();
+        remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply);
     }
 
     virtual void bootFinished()
@@ -232,26 +203,8 @@
                 s.read(data);
                 state.add(s);
             }
-            setTransactionState(state);
-        } break;
-        case SET_ORIENTATION: {
-            CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            DisplayID dpy = data.readInt32();
             int orientation = data.readInt32();
-            uint32_t flags = data.readInt32();
-            reply->writeInt32( setOrientation(dpy, orientation, flags) );
-        } break;
-        case FREEZE_DISPLAY: {
-            CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            DisplayID dpy = data.readInt32();
-            uint32_t flags = data.readInt32();
-            reply->writeInt32( freezeDisplay(dpy, flags) );
-        } break;
-        case UNFREEZE_DISPLAY: {
-            CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            DisplayID dpy = data.readInt32();
-            uint32_t flags = data.readInt32();
-            reply->writeInt32( unfreezeDisplay(dpy, flags) );
+            setTransactionState(state, orientation);
         } break;
         case BOOT_FINISHED: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 00a4bf6..5f3d608 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -91,8 +91,10 @@
 
     mutable Mutex               mLock;
     SortedVector<ComposerState> mStates;
+    int                         mOrientation;
 
-    Composer() : Singleton<Composer>() { }
+    Composer() : Singleton<Composer>(),
+        mOrientation(ISurfaceComposer::eOrientationUnchanged) { }
 
     void closeGlobalTransactionImpl();
 
@@ -119,6 +121,7 @@
     status_t setFreezeTint(
             const sp<SurfaceComposerClient>& client, SurfaceID id,
             uint32_t tint);
+    status_t setOrientation(int orientation);
 
     static void closeGlobalTransaction() {
         Composer::getInstance().closeGlobalTransactionImpl();
@@ -133,14 +136,18 @@
     sp<ISurfaceComposer> sm(getComposerService());
 
     Vector<ComposerState> transaction;
+    int orientation;
 
     { // scope for the lock
         Mutex::Autolock _l(mLock);
         transaction = mStates;
         mStates.clear();
+
+        orientation = mOrientation;
+        mOrientation = ISurfaceComposer::eOrientationUnchanged;
     }
 
-   sm->setTransactionState(transaction);
+   sm->setTransactionState(transaction, orientation);
 }
 
 layer_state_t* Composer::getLayerStateLocked(
@@ -260,6 +267,12 @@
     return NO_ERROR;
 }
 
+status_t Composer::setOrientation(int orientation) {
+    Mutex::Autolock _l(mLock);
+    mOrientation = orientation;
+    return NO_ERROR;
+}
+
 // ---------------------------------------------------------------------------
 
 SurfaceComposerClient::SurfaceComposerClient()
@@ -427,6 +440,12 @@
     return getComposer().setMatrix(this, id, dsdx, dtdx, dsdy, dtdy);
 }
 
+status_t SurfaceComposerClient::setOrientation(DisplayID dpy,
+        int orientation, uint32_t flags)
+{
+    return Composer::getInstance().setOrientation(orientation);
+}
+
 // ----------------------------------------------------------------------------
 
 status_t SurfaceComposerClient::getDisplayInfo(
@@ -491,21 +510,14 @@
 
 status_t SurfaceComposerClient::freezeDisplay(DisplayID dpy, uint32_t flags)
 {
-    sp<ISurfaceComposer> sm(getComposerService());
-    return sm->freezeDisplay(dpy, flags);
+    // This has been made a no-op because it can cause Gralloc buffer deadlocks.
+    return NO_ERROR;
 }
 
 status_t SurfaceComposerClient::unfreezeDisplay(DisplayID dpy, uint32_t flags)
 {
-    sp<ISurfaceComposer> sm(getComposerService());
-    return sm->unfreezeDisplay(dpy, flags);
-}
-
-int SurfaceComposerClient::setOrientation(DisplayID dpy,
-        int orientation, uint32_t flags)
-{
-    sp<ISurfaceComposer> sm(getComposerService());
-    return sm->setOrientation(dpy, orientation, flags);
+    // This has been made a no-op because it can cause Gralloc buffer deadlocks.
+    return NO_ERROR;
 }
 
 // ----------------------------------------------------------------------------
@@ -572,4 +584,3 @@
 
 // ----------------------------------------------------------------------------
 }; // namespace android
-
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index a2452c4..64c54d9 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -101,5 +101,21 @@
             android:taskAffinity="com.android.systemui.net"
             android:excludeFromRecents="true" />
 
+        <!-- started from ... somewhere -->
+        <activity
+            android:name=".Nyandroid"
+            android:exported="true"
+            android:label="Nyandroid"
+            android:icon="@drawable/nyandroid04"
+            android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
+            android:hardwareAccelerated="true"
+            android:launchMode="singleInstance"
+            android:excludeFromRecents="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.DREAM" />
+            </intent-filter>
+        </activity>
     </application>
 </manifest>
diff --git a/packages/SystemUI/res/drawable-nodpi/nyandroid00.png b/packages/SystemUI/res/drawable-nodpi/nyandroid00.png
new file mode 100644
index 0000000..6cea873
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/nyandroid00.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/nyandroid01.png b/packages/SystemUI/res/drawable-nodpi/nyandroid01.png
new file mode 100644
index 0000000..82b8a21
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/nyandroid01.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/nyandroid02.png b/packages/SystemUI/res/drawable-nodpi/nyandroid02.png
new file mode 100644
index 0000000..fde0033
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/nyandroid02.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/nyandroid03.png b/packages/SystemUI/res/drawable-nodpi/nyandroid03.png
new file mode 100644
index 0000000..54c5f46
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/nyandroid03.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/nyandroid04.png b/packages/SystemUI/res/drawable-nodpi/nyandroid04.png
new file mode 100644
index 0000000..35e5ab5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/nyandroid04.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/nyandroid05.png b/packages/SystemUI/res/drawable-nodpi/nyandroid05.png
new file mode 100644
index 0000000..d3eaace
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/nyandroid05.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/nyandroid06.png b/packages/SystemUI/res/drawable-nodpi/nyandroid06.png
new file mode 100644
index 0000000..0e0d3b1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/nyandroid06.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/nyandroid07.png b/packages/SystemUI/res/drawable-nodpi/nyandroid07.png
new file mode 100644
index 0000000..edb0b17
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/nyandroid07.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/nyandroid08.png b/packages/SystemUI/res/drawable-nodpi/nyandroid08.png
new file mode 100644
index 0000000..10fc4f6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/nyandroid08.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/nyandroid09.png b/packages/SystemUI/res/drawable-nodpi/nyandroid09.png
new file mode 100644
index 0000000..57ade54
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/nyandroid09.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/nyandroid10.png b/packages/SystemUI/res/drawable-nodpi/nyandroid10.png
new file mode 100644
index 0000000..36feb2f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/nyandroid10.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/nyandroid11.png b/packages/SystemUI/res/drawable-nodpi/nyandroid11.png
new file mode 100644
index 0000000..125935b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/nyandroid11.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/star0.png b/packages/SystemUI/res/drawable-nodpi/star0.png
new file mode 100644
index 0000000..f2ca960
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/star0.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/star1.png b/packages/SystemUI/res/drawable-nodpi/star1.png
new file mode 100644
index 0000000..69ef4da
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/star1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/star2.png b/packages/SystemUI/res/drawable-nodpi/star2.png
new file mode 100644
index 0000000..b95968a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/star2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/star3.png b/packages/SystemUI/res/drawable-nodpi/star3.png
new file mode 100644
index 0000000..ad0f589
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/star3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/star4.png b/packages/SystemUI/res/drawable-nodpi/star4.png
new file mode 100644
index 0000000..934c45b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/star4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/star5.png b/packages/SystemUI/res/drawable-nodpi/star5.png
new file mode 100644
index 0000000..46a4435
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/star5.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/nyandroid_anim.xml b/packages/SystemUI/res/drawable/nyandroid_anim.xml
new file mode 100644
index 0000000..855a0c2
--- /dev/null
+++ b/packages/SystemUI/res/drawable/nyandroid_anim.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<animation-list
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:oneshot="false">
+    <item android:drawable="@drawable/nyandroid00" android:duration="80" />
+    <item android:drawable="@drawable/nyandroid01" android:duration="80" />
+    <item android:drawable="@drawable/nyandroid02" android:duration="80" />
+    <item android:drawable="@drawable/nyandroid03" android:duration="80" />
+    <item android:drawable="@drawable/nyandroid04" android:duration="80" />
+    <item android:drawable="@drawable/nyandroid05" android:duration="80" />
+    <item android:drawable="@drawable/nyandroid06" android:duration="80" />
+    <item android:drawable="@drawable/nyandroid07" android:duration="80" />
+    <item android:drawable="@drawable/nyandroid08" android:duration="80" />
+    <item android:drawable="@drawable/nyandroid09" android:duration="80" />
+    <item android:drawable="@drawable/nyandroid10" android:duration="80" />
+    <item android:drawable="@drawable/nyandroid11" android:duration="80" />
+</animation-list>
+
diff --git a/packages/SystemUI/res/drawable/star_anim.xml b/packages/SystemUI/res/drawable/star_anim.xml
new file mode 100644
index 0000000..d7f2d8f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/star_anim.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<animation-list
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:oneshot="false">
+    <item android:drawable="@drawable/star0" android:duration="200" />
+    <item android:drawable="@drawable/star1" android:duration="200" />
+    <item android:drawable="@drawable/star2" android:duration="200" />
+    <item android:drawable="@drawable/star3" android:duration="200" />
+    <item android:drawable="@drawable/star4" android:duration="200" />
+    <item android:drawable="@drawable/star5" android:duration="200" />
+</animation-list>
+
diff --git a/packages/SystemUI/src/com/android/systemui/Nyandroid.java b/packages/SystemUI/src/com/android/systemui/Nyandroid.java
new file mode 100644
index 0000000..6f168ba
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/Nyandroid.java
@@ -0,0 +1,253 @@
+/*);
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.animation.AnimatorSet;
+import android.animation.PropertyValuesHolder;
+import android.animation.ObjectAnimator;
+import android.animation.TimeAnimator;
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.AnimationDrawable;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.os.Handler;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.Pair;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import java.util.HashMap;
+import java.util.Random;
+
+public class Nyandroid extends Activity {
+    final static boolean DEBUG = false;
+
+    public static class Board extends FrameLayout
+    {
+        public static final boolean FIXED_STARS = true;
+        public static final int NUM_CATS = 20;
+
+        static Random sRNG = new Random();
+
+        static float lerp(float a, float b, float f) {
+            return (b-a)*f + a;
+        }
+
+        static float randfrange(float a, float b) {
+            return lerp(a, b, sRNG.nextFloat());
+        }
+
+        static int randsign() {
+            return sRNG.nextBoolean() ? 1 : -1;
+        }
+
+        static <E> E pick(E[] array) {
+            if (array.length == 0) return null;
+            return array[sRNG.nextInt(array.length)];
+        }
+
+        public class FlyingCat extends ImageView {
+            public static final float VMAX = 1000.0f;
+            public static final float VMIN = 100.0f;
+
+            public float v, vr;
+
+            public float dist;
+            public float z;
+
+            public ComponentName component;
+
+            public FlyingCat(Context context, AttributeSet as) {
+                super(context, as);
+                setImageResource(R.drawable.nyandroid_anim); // @@@
+
+                if (DEBUG) setBackgroundColor(0x80FF0000);
+            }
+
+            public String toString() {
+                return String.format("<cat (%.1f, %.1f) (%d x %d)>",
+                    getX(), getY(), getWidth(), getHeight());
+            }
+
+            public void reset() {
+                final float scale = lerp(0.1f,2f,z);
+                setScaleX(scale); setScaleY(scale);
+
+                setX(-scale*getWidth()+1);
+                setY(randfrange(0, Board.this.getHeight()-scale*getHeight()));
+                v = lerp(VMIN, VMAX, z);
+
+                dist = 0;
+
+//                android.util.Log.d("Nyandroid", "reset cat: " + this);
+            }
+
+            public void update(float dt) {
+                dist += v * dt;
+                setX(getX() + v * dt);
+            }
+        }
+
+        TimeAnimator mAnim;
+
+        public Board(Context context, AttributeSet as) {
+            super(context, as);
+
+            setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
+            setBackgroundColor(0xFF003366);
+        }
+
+        private void reset() {
+//            android.util.Log.d("Nyandroid", "board reset");
+            removeAllViews();
+
+            final ViewGroup.LayoutParams wrap = new ViewGroup.LayoutParams(
+                        ViewGroup.LayoutParams.WRAP_CONTENT,
+                        ViewGroup.LayoutParams.WRAP_CONTENT);
+
+            if (FIXED_STARS) {
+                for(int i=0; i<20; i++) {
+                    ImageView fixedStar = new ImageView(getContext(), null);
+                    if (DEBUG) fixedStar.setBackgroundColor(0x8000FF80);
+                    fixedStar.setImageResource(R.drawable.star_anim); // @@@
+                    addView(fixedStar, wrap);
+                    final float scale = randfrange(0.1f, 1f);
+                    fixedStar.setScaleX(scale); fixedStar.setScaleY(scale);
+                    fixedStar.setX(randfrange(0, getWidth()));
+                    fixedStar.setY(randfrange(0, getHeight()));
+                    final AnimationDrawable anim = (AnimationDrawable) fixedStar.getDrawable();
+                    postDelayed(new Runnable() { 
+                        public void run() {
+                            anim.start();
+                        }}, (int) randfrange(0, 1000));
+                }
+            }
+
+            for(int i=0; i<NUM_CATS; i++) {
+                FlyingCat nv = new FlyingCat(getContext(), null);
+                addView(nv, wrap);
+                nv.z = ((float)i/NUM_CATS);
+                nv.z *= nv.z;
+                nv.reset();
+                nv.setX(randfrange(0,Board.this.getWidth()));
+                final AnimationDrawable anim = (AnimationDrawable) nv.getDrawable();
+                postDelayed(new Runnable() { 
+                    public void run() {
+                        anim.start();
+                    }}, (int) randfrange(0, 1000));
+            }
+
+            if (mAnim != null) {
+                mAnim.cancel();
+            }
+            mAnim = new TimeAnimator();
+            mAnim.setTimeListener(new TimeAnimator.TimeListener() {
+                public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
+                    // setRotation(totalTime * 0.01f); // not as cool as you would think
+//                    android.util.Log.d("Nyandroid", "t=" + totalTime);
+
+                    for (int i=0; i<getChildCount(); i++) {
+                        View v = getChildAt(i);
+                        if (!(v instanceof FlyingCat)) continue;
+                        FlyingCat nv = (FlyingCat) v;
+                        nv.update(deltaTime / 1000f);
+                        final float catWidth = nv.getWidth() * nv.getScaleX();
+                        final float catHeight = nv.getHeight() * nv.getScaleY();
+                        if (   nv.getX() + catWidth < -2
+                            || nv.getX() > getWidth() + 2
+                            || nv.getY() + catHeight < -2
+                            || nv.getY() > getHeight() + 2)
+                        {
+                            nv.reset();
+                        }
+                    }
+                }
+            });
+        }
+
+        @Override
+        protected void onSizeChanged (int w, int h, int oldw, int oldh) {
+            super.onSizeChanged(w,h,oldw,oldh);
+//            android.util.Log.d("Nyandroid", "resized: " + w + "x" + h);
+            post(new Runnable() { public void run() { 
+                reset();
+                mAnim.start(); 
+            } });
+        }
+
+
+        @Override
+        protected void onDetachedFromWindow() {
+            super.onDetachedFromWindow();
+            mAnim.cancel();
+        }
+
+        @Override
+        public boolean isOpaque() {
+            return true;
+        }
+    }
+
+    private Board mBoard;
+
+    @Override
+    public void onStart() {
+        super.onStart();
+
+        getWindow().addFlags(
+                  WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
+                | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+                );
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        mBoard = new Board(this, null);
+        setContentView(mBoard);
+
+        mBoard.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
+            @Override
+            public void onSystemUiVisibilityChange(int vis) {
+                if (0 == (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)) {
+                    Nyandroid.this.finish();
+                }
+            }
+        });
+    }
+
+    @Override
+    public void onUserInteraction() {
+//        android.util.Log.d("Nyandroid", "finishing on user interaction");
+        finish();
+    }
+}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 06a6e98..595c256 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -5230,32 +5230,27 @@
         startFreezingDisplayLocked(inTransaction);
         mInputManager.setDisplayOrientation(0, rotation);
 
-        // NOTE: We disable the rotation in the emulator because
-        //       it doesn't support hardware OpenGL emulation yet.
-        if (CUSTOM_SCREEN_ROTATION && mScreenRotationAnimation != null
-                && mScreenRotationAnimation.hasScreenshot()) {
-            Surface.freezeDisplay(0);
-            if (!inTransaction) {
-                if (SHOW_TRANSACTIONS) Slog.i(TAG,
-                        ">>> OPEN TRANSACTION setRotationUnchecked");
-                Surface.openTransaction();
-            }
-            try {
-                if (mScreenRotationAnimation != null) {
-                    mScreenRotationAnimation.setRotation(rotation);
-                }
-            } finally {
-                if (!inTransaction) {
-                    Surface.closeTransaction();
-                    if (SHOW_TRANSACTIONS) Slog.i(TAG,
-                            "<<< CLOSE TRANSACTION setRotationUnchecked");
-                }
-            }
-            Surface.setOrientation(0, rotation);
-            Surface.unfreezeDisplay(0);
-        } else {
-            Surface.setOrientation(0, rotation);
+        if (!inTransaction) {
+            if (SHOW_TRANSACTIONS) Slog.i(TAG,
+                    ">>> OPEN TRANSACTION setRotationUnchecked");
+            Surface.openTransaction();
         }
+        try {
+            // NOTE: We disable the rotation in the emulator because
+            //       it doesn't support hardware OpenGL emulation yet.
+            if (CUSTOM_SCREEN_ROTATION && mScreenRotationAnimation != null
+                    && mScreenRotationAnimation.hasScreenshot()) {
+                mScreenRotationAnimation.setRotation(rotation);
+            }
+            Surface.setOrientation(0, rotation);
+        } finally {
+            if (!inTransaction) {
+                Surface.closeTransaction();
+                if (SHOW_TRANSACTIONS) Slog.i(TAG,
+                        "<<< CLOSE TRANSACTION setRotationUnchecked");
+            }
+        }
+
         rebuildBlackFrame(inTransaction);
 
         for (int i=mWindows.size()-1; i>=0; i--) {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 195ad2e..1441a54 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1234,10 +1234,22 @@
 }
 
 
-void SurfaceFlinger::setTransactionState(const Vector<ComposerState>& state) {
+void SurfaceFlinger::setTransactionState(const Vector<ComposerState>& state,
+        int orientation) {
     Mutex::Autolock _l(mStateLock);
 
     uint32_t flags = 0;
+    if (mCurrentState.orientation != orientation) {
+        if (uint32_t(orientation)<=eOrientation270 || orientation==42) {
+            mCurrentState.orientation = orientation;
+            flags |= eTransactionNeeded;
+            mResizeTransationPending = true;
+        } else if (orientation != eOrientationUnchanged) {
+            LOGW("setTransactionState: ignoring unrecognized orientation: %d",
+                    orientation);
+        }
+    }
+
     const size_t count = state.size();
     for (size_t i=0 ; i<count ; i++) {
         const ComposerState& s(state[i]);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 1cb9be2..0e642c1 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -167,7 +167,8 @@
     virtual sp<IGraphicBufferAlloc>     createGraphicBufferAlloc();
     virtual sp<IMemoryHeap>             getCblk() const;
     virtual void                        bootFinished();
-    virtual void                        setTransactionState(const Vector<ComposerState>& state);
+    virtual void                        setTransactionState(const Vector<ComposerState>& state,
+                                                            int orientation);
     virtual status_t                    freezeDisplay(DisplayID dpy, uint32_t flags);
     virtual status_t                    unfreezeDisplay(DisplayID dpy, uint32_t flags);
     virtual int                         setOrientation(DisplayID dpy, int orientation, uint32_t flags);