OSDN Git Service

Fix potential deadlock between LockScreen and WindowManagerService
authorSangkyu Lee <sk82.lee@lge.com>
Wed, 16 Jan 2013 05:53:17 +0000 (14:53 +0900)
committerSangkyu Lee <sk82.lee@lge.com>
Tue, 2 Apr 2013 05:31:19 +0000 (14:31 +0900)
If LockScreen is enhanced using SurfaceView/GLSurfaceView,
deadlock problem between LockScreen and WindowManagerService
can occur because of IWindow.resized() callback.
And it must lead to watchdog and reset.

IWindow.resized() callback is one-way function so calling resized()
callback of a remote IWindow object is never blocked.
However, calling resized() callback of a local IWindow object
(LockScreen is running on the same system_server process)
is always blocked until resized() callback returns.
Because resized() callback of SurfaceView/GLSurfaceView can lead to
WindowManagerService.relayoutWindow() call, deadlock can occur
between relayoutWindow() and performLayoutAndPlaceSurfacesLockedInner().
(Both functions need locking mWindowMap)

So this patch simulate one-way call when calling resized() callback
of a local IWindow object.

Change-Id: I2a6a5c74ed22d8e6b7a3bea3424ff2879d227105
Signed-off-by: Sangkyu Lee <sk82.lee@lge.com>
services/java/com/android/server/wm/WindowManagerService.java

index 194c750..d6dfff4 100644 (file)
@@ -9461,9 +9461,31 @@ public class WindowManagerService extends IWindowManager.Stub
                 if (DEBUG_ORIENTATION &&
                         winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING) Slog.i(
                         TAG, "Resizing " + win + " WITH DRAW PENDING");
-                win.mClient.resized(win.mFrame, win.mLastContentInsets, win.mLastVisibleInsets,
-                        winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING,
-                        configChanged ? win.mConfiguration : null);
+                final boolean reportDraw
+                        = winAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING;
+                final Configuration newConfig = configChanged ? win.mConfiguration : null;
+                if (win.mClient instanceof IWindow.Stub) {
+                    // Simulate one-way call if win.mClient is a local object.
+                    final IWindow client = win.mClient;
+                    final Rect frame = win.mFrame;
+                    final Rect contentInsets = win.mLastContentInsets;
+                    final Rect visibleInsets = win.mLastVisibleInsets;
+                    mH.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            try {
+                                client.resized(frame, contentInsets, visibleInsets,
+                                               reportDraw, newConfig);
+                            } catch (RemoteException e) {
+                                // Actually, it's not a remote call.
+                                // RemoteException mustn't be raised.
+                            }
+                        }
+                    });
+                } else {
+                    win.mClient.resized(win.mFrame, win.mLastContentInsets, win.mLastVisibleInsets,
+                                        reportDraw, newConfig);
+                }
                 win.mContentInsetsChanged = false;
                 win.mVisibleInsetsChanged = false;
                 winAnimator.mSurfaceResized = false;