Merge "Fix issue #2461567: Home screen redraw messed up"
diff --git a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
index 251ecbc..e961116 100644
--- a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
+++ b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
@@ -16,12 +16,15 @@
 
 package com.android.internal.service.wallpaper;
 
+import com.android.internal.view.WindowManagerPolicyThread;
+
 import android.app.WallpaperManager;
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.graphics.Region.Op;
 import android.graphics.drawable.Drawable;
 import android.os.HandlerThread;
+import android.os.Looper;
 import android.os.Process;
 import android.service.wallpaper.WallpaperService;
 import android.util.Log;
@@ -43,9 +46,14 @@
     public void onCreate() {
         super.onCreate();
         mWallpaperManager = (WallpaperManager) getSystemService(WALLPAPER_SERVICE);
-        mThread = new HandlerThread("Wallpaper", Process.THREAD_PRIORITY_FOREGROUND);
-        mThread.start();
-        setCallbackLooper(mThread.getLooper());
+        Looper looper = WindowManagerPolicyThread.getLooper();
+        if (looper != null) {
+            setCallbackLooper(looper);
+        } else {
+            mThread = new HandlerThread("Wallpaper", Process.THREAD_PRIORITY_FOREGROUND);
+            mThread.start();
+            setCallbackLooper(mThread.getLooper());
+        }
     }
 
     public Engine onCreateEngine() {
@@ -55,7 +63,9 @@
     @Override
     public void onDestroy() {
         super.onDestroy();
-        mThread.quit();
+        if (mThread != null) {
+            mThread.quit();
+        }
     }
 
     class DrawableEngine extends Engine {
diff --git a/core/java/com/android/internal/view/WindowManagerPolicyThread.java b/core/java/com/android/internal/view/WindowManagerPolicyThread.java
new file mode 100644
index 0000000..6078683
--- /dev/null
+++ b/core/java/com/android/internal/view/WindowManagerPolicyThread.java
@@ -0,0 +1,25 @@
+package com.android.internal.view;
+
+import android.os.Looper;
+
+/**
+ * Static storage of the thread running the window manager policy, to
+ * share with others.
+ */
+public class WindowManagerPolicyThread {
+    static Thread mThread;
+    static Looper mLooper;
+    
+    public static void set(Thread thread, Looper looper) {
+        mThread = thread;
+        mLooper = looper;
+    }
+    
+    public static Thread getThread() {
+        return mThread;
+    }
+    
+    public static Looper getLooper() {
+        return mLooper;
+    }
+}
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 989fe2a..b27736a 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -47,6 +47,7 @@
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethodClient;
 import com.android.internal.view.IInputMethodManager;
+import com.android.internal.view.WindowManagerPolicyThread;
 import com.android.server.KeyInputQueue.QueuedEvent;
 import com.android.server.am.BatteryStatsService;
 
@@ -135,6 +136,7 @@
     static final boolean DEBUG_FOCUS = false;
     static final boolean DEBUG_ANIM = false;
     static final boolean DEBUG_LAYOUT = false;
+    static final boolean DEBUG_RESIZE = false;
     static final boolean DEBUG_LAYERS = false;
     static final boolean DEBUG_INPUT = false;
     static final boolean DEBUG_INPUT_METHOD = false;
@@ -558,6 +560,8 @@
 
         public void run() {
             Looper.prepare();
+            WindowManagerPolicyThread.set(this, Looper.myLooper());
+            
             //Looper.myLooper().setMessageLogging(new LogPrinter(
             //        Log.VERBOSE, "WindowManagerPolicy", Log.LOG_ID_SYSTEM));
             android.os.Process.setThreadPriority(
@@ -6911,6 +6915,12 @@
         final Rect mLastShownFrame = new Rect();
 
         /**
+         * Set when we have changed the size of the surface, to know that
+         * we must tell them application to resize (and thus redraw itself).
+         */
+        boolean mSurfaceResized;
+        
+        /**
          * Insets that determine the actually visible area
          */
         final Rect mVisibleInsets = new Rect();
@@ -10066,6 +10076,20 @@
                 final int attrFlags = attrs.flags;
 
                 if (w.mSurface != null) {
+                    // XXX NOTE: The logic here could be improved.  We have
+                    // the decision about whether to resize a window separated
+                    // from whether to hide the surface.  This can cause us to
+                    // resize a surface even if we are going to hide it.  You
+                    // can see this by (1) holding device in landscape mode on
+                    // home screen; (2) tapping browser icon (device will rotate
+                    // to landscape; (3) tap home.  The wallpaper will be resized
+                    // in step 2 but then immediately hidden, causing us to
+                    // have to resize and then redraw it again in step 3.  It
+                    // would be nice to figure out how to avoid this, but it is
+                    // difficult because we do need to resize surfaces in some
+                    // cases while they are hidden such as when first showing a
+                    // window.
+                    
                     w.computeShownFrameLocked();
                     if (localLOGV) Slog.v(
                             TAG, "Placing surface #" + i + " " + w.mSurface
@@ -10112,6 +10136,7 @@
                                         + w.mShownFrame.top + " SIZE "
                                         + w.mShownFrame.width() + "x"
                                         + w.mShownFrame.height(), null);
+                                w.mSurfaceResized = true;
                                 w.mSurface.setSize(width, height);
                                 w.mSurface.setPosition(w.mShownFrame.left,
                                         w.mShownFrame.top);
@@ -10144,6 +10169,7 @@
                         if (!w.mLastFrame.equals(w.mFrame)
                                 || w.mContentInsetsChanged
                                 || w.mVisibleInsetsChanged
+                                || w.mSurfaceResized
                                 || configChanged) {
                             w.mLastFrame.set(w.mFrame);
                             w.mLastContentInsets.set(w.mContentInsets);
@@ -10180,7 +10206,7 @@
                                     w.mAppToken.allDrawn = false;
                                 }
                             }
-                            if (DEBUG_ORIENTATION) Slog.v(TAG,
+                            if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
                                     "Resizing window " + w + " to " + w.mFrame);
                             mResizingWindows.add(w);
                         } else if (w.mOrientationChanging) {
@@ -10479,14 +10505,14 @@
                 i--;
                 WindowState win = mResizingWindows.get(i);
                 try {
-                    if (DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to "
-                            + win + ": " + win.mFrame);
+                    if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
+                            "Reporting new frame to " + win + ": " + win.mFrame);
                     boolean configChanged =
                         win.mConfiguration != mCurConfiguration
                         && (win.mConfiguration == null
                                 || mCurConfiguration.diff(win.mConfiguration) != 0);
                     win.mConfiguration = mCurConfiguration;
-                    if (DEBUG_ORIENTATION && configChanged) {
+                    if ((DEBUG_RESIZE || DEBUG_ORIENTATION) && configChanged) {
                         Slog.i(TAG, "Sending new config to window " + win + ": "
                                 + win.mFrame.width() + "x" + win.mFrame.height()
                                 + " / " + win.mConfiguration);
@@ -10497,6 +10523,7 @@
                             configChanged ? win.mConfiguration : null);
                     win.mContentInsetsChanged = false;
                     win.mVisibleInsetsChanged = false;
+                    win.mSurfaceResized = false;
                 } catch (RemoteException e) {
                     win.mOrientationChanging = false;
                 }