From a4c520694fee942a6a166bbb6687dcd0ea0e3509 Mon Sep 17 00:00:00 2001 From: Arthur Hung Date: Tue, 19 Feb 2019 11:31:44 +0800 Subject: [PATCH] Fix View#performHapticFeedback() can block UI thread Currently, IWindowSession#performHapticFeedback() would first lookup the WindowState via IWindow token. That would also hold the WMS lock, so if some function like relayout window is still hold WMS lock, it may block the function. Use uid and package name from Session that they already restored. Bug: 62330939 Test: Open app with autofill edit, type with IME. Change-Id: I359c106d213b87aa8afee48b0f1ad70011970eab --- config/boot-image-profile.txt | 4 +-- config/hiddenapi-greylist.txt | 2 +- core/java/android/view/IWindowSession.aidl | 2 +- core/java/android/view/ViewRootImpl.java | 2 +- services/art-profile | 6 ++-- .../android/server/policy/PhoneWindowManager.java | 40 ++++++++++------------ .../android/server/policy/WindowManagerPolicy.java | 4 +-- .../core/java/com/android/server/wm/Session.java | 16 ++++----- .../android/server/wm/TestWindowManagerPolicy.java | 4 +-- 9 files changed, 36 insertions(+), 44 deletions(-) diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt index 0a26bfb49bf7..d2535c9ba8ee 100644 --- a/config/boot-image-profile.txt +++ b/config/boot-image-profile.txt @@ -32983,7 +32983,7 @@ HSPLandroid/view/IWindowSession$Stub$Proxy;->getDisplayFrame(Landroid/view/IWind HSPLandroid/view/IWindowSession$Stub$Proxy;->getInTouchMode()Z HSPLandroid/view/IWindowSession$Stub$Proxy;->getWindowId(Landroid/os/IBinder;)Landroid/view/IWindowId; HSPLandroid/view/IWindowSession$Stub$Proxy;->onRectangleOnScreenRequested(Landroid/os/IBinder;Landroid/graphics/Rect;)V -HSPLandroid/view/IWindowSession$Stub$Proxy;->performHapticFeedback(Landroid/view/IWindow;IZ)Z +HSPLandroid/view/IWindowSession$Stub$Proxy;->performHapticFeedback(IZ)Z HSPLandroid/view/IWindowSession$Stub$Proxy;->pokeDrawLock(Landroid/os/IBinder;)V HSPLandroid/view/IWindowSession$Stub$Proxy;->relayout(Landroid/view/IWindow;ILandroid/view/WindowManager$LayoutParams;IIIIJLandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/view/DisplayCutout$ParcelableWrapper;Landroid/util/MergedConfiguration;Landroid/view/Surface;)I HSPLandroid/view/IWindowSession$Stub$Proxy;->remove(Landroid/view/IWindow;)V @@ -33007,7 +33007,7 @@ HSPLandroid/view/IWindowSession;->getWindowId(Landroid/os/IBinder;)Landroid/view HSPLandroid/view/IWindowSession;->onRectangleOnScreenRequested(Landroid/os/IBinder;Landroid/graphics/Rect;)V HSPLandroid/view/IWindowSession;->outOfMemory(Landroid/view/IWindow;)Z HSPLandroid/view/IWindowSession;->performDrag(Landroid/view/IWindow;ILandroid/view/SurfaceControl;IFFFFLandroid/content/ClipData;)Landroid/os/IBinder; -HSPLandroid/view/IWindowSession;->performHapticFeedback(Landroid/view/IWindow;IZ)Z +HSPLandroid/view/IWindowSession;->performHapticFeedback(IZ)Z HSPLandroid/view/IWindowSession;->pokeDrawLock(Landroid/os/IBinder;)V HSPLandroid/view/IWindowSession;->prepareToReplaceWindows(Landroid/os/IBinder;Z)V HSPLandroid/view/IWindowSession;->relayout(Landroid/view/IWindow;ILandroid/view/WindowManager$LayoutParams;IIIIJLandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/view/DisplayCutout$ParcelableWrapper;Landroid/util/MergedConfiguration;Landroid/view/Surface;)I diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt index 7f7972a5ce1d..fa4d65c958d5 100644 --- a/config/hiddenapi-greylist.txt +++ b/config/hiddenapi-greylist.txt @@ -1524,7 +1524,7 @@ Landroid/view/IWindowSession$Stub;->asInterface(Landroid/os/IBinder;)Landroid/vi Landroid/view/IWindowSession;->finishDrawing(Landroid/view/IWindow;)V Landroid/view/IWindowSession;->getInTouchMode()Z Landroid/view/IWindowSession;->performDrag(Landroid/view/IWindow;ILandroid/view/SurfaceControl;IFFFFLandroid/content/ClipData;)Landroid/os/IBinder; -Landroid/view/IWindowSession;->performHapticFeedback(Landroid/view/IWindow;IZ)Z +Landroid/view/IWindowSession;->performHapticFeedback(IZ)Z Landroid/view/IWindowSession;->remove(Landroid/view/IWindow;)V Landroid/view/IWindowSession;->setInTouchMode(Z)V Landroid/view/IWindowSession;->setTransparentRegion(Landroid/view/IWindow;Landroid/graphics/Region;)V diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index 658f06ad21f9..240aad5a0c56 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -148,7 +148,7 @@ interface IWindowSession { void setInTouchMode(boolean showFocus); boolean getInTouchMode(); - boolean performHapticFeedback(IWindow window, int effectId, boolean always); + boolean performHapticFeedback(int effectId, boolean always); /** * Initiate the drag operation itself diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 89c67032f8c2..be6b56c209a5 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -6996,7 +6996,7 @@ public final class ViewRootImpl implements ViewParent, @Override public boolean performHapticFeedback(int effectId, boolean always) { try { - return mWindowSession.performHapticFeedback(mWindow, effectId, always); + return mWindowSession.performHapticFeedback(effectId, always); } catch (RemoteException e) { return false; } diff --git a/services/art-profile b/services/art-profile index e7503806edfe..7892fcb79822 100644 --- a/services/art-profile +++ b/services/art-profile @@ -2942,7 +2942,7 @@ HSPLcom/android/server/policy/WindowManagerPolicy;->onConfigurationChanged()V HSPLcom/android/server/policy/WindowManagerPolicy;->onKeyguardOccludedChangedLw(Z)V HSPLcom/android/server/policy/WindowManagerPolicy;->onLockTaskStateChangedLw(I)V HSPLcom/android/server/policy/WindowManagerPolicy;->onSystemUiStarted()V -HSPLcom/android/server/policy/WindowManagerPolicy;->performHapticFeedbackLw(Lcom/android/server/policy/WindowManagerPolicy$WindowState;IZ)Z +HSPLcom/android/server/policy/WindowManagerPolicy;->performHapticFeedback(ILjava/lang/String;IZ)Z HSPLcom/android/server/policy/WindowManagerPolicy;->prepareAddWindowLw(Lcom/android/server/policy/WindowManagerPolicy$WindowState;Landroid/view/WindowManager$LayoutParams;)I HSPLcom/android/server/policy/WindowManagerPolicy;->registerShortcutKey(JLcom/android/internal/policy/IShortcutService;)V HSPLcom/android/server/policy/WindowManagerPolicy;->removeWindowLw(Lcom/android/server/policy/WindowManagerPolicy$WindowState;)V @@ -15736,7 +15736,7 @@ PLcom/android/server/policy/PhoneWindowManager;->onConfigurationChanged()V PLcom/android/server/policy/PhoneWindowManager;->onKeyguardOccludedChangedLw(Z)V PLcom/android/server/policy/PhoneWindowManager;->onOverlayChangedLw()V PLcom/android/server/policy/PhoneWindowManager;->onSystemUiStarted()V -PLcom/android/server/policy/PhoneWindowManager;->performHapticFeedbackLw(Lcom/android/server/policy/WindowManagerPolicy$WindowState;IZ)Z +PLcom/android/server/policy/PhoneWindowManager;->performHapticFeedback(ILjava/lang/String;IZ)Z PLcom/android/server/policy/PhoneWindowManager;->powerPress(JZI)V PLcom/android/server/policy/PhoneWindowManager;->prepareAddWindowLw(Lcom/android/server/policy/WindowManagerPolicy$WindowState;Landroid/view/WindowManager$LayoutParams;)I PLcom/android/server/policy/PhoneWindowManager;->readCameraLensCoverState()V @@ -18331,7 +18331,7 @@ PLcom/android/server/wm/Session;->getWindowId(Landroid/os/IBinder;)Landroid/view PLcom/android/server/wm/Session;->killSessionLocked()V PLcom/android/server/wm/Session;->onRectangleOnScreenRequested(Landroid/os/IBinder;Landroid/graphics/Rect;)V PLcom/android/server/wm/Session;->onWindowSurfaceVisibilityChanged(Lcom/android/server/wm/WindowSurfaceController;ZI)V -PLcom/android/server/wm/Session;->performHapticFeedback(Landroid/view/IWindow;IZ)Z +PLcom/android/server/wm/Session;->performHapticFeedback(IZ)Z PLcom/android/server/wm/Session;->relayout(Landroid/view/IWindow;ILandroid/view/WindowManager$LayoutParams;IIIIJLandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/view/DisplayCutout$ParcelableWrapper;Landroid/util/MergedConfiguration;Landroid/view/Surface;)I PLcom/android/server/wm/Session;->remove(Landroid/view/IWindow;)V PLcom/android/server/wm/Session;->sendWallpaperCommand(Landroid/os/IBinder;Ljava/lang/String;IIILandroid/os/Bundle;Z)Landroid/os/Bundle; diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index c87a81db16e4..d3a329ea72ca 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -808,7 +808,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { public void onWakeUp() { synchronized (mLock) { if (shouldEnableWakeGestureLp()) { - performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false, + performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, false, "Wake Up"); wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture, PowerManager.WAKE_REASON_GESTURE, "android.policy:GESTURE"); @@ -1212,21 +1212,21 @@ public class PhoneWindowManager implements WindowManagerPolicy { break; case LONG_PRESS_POWER_GLOBAL_ACTIONS: mPowerKeyHandled = true; - performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false, + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false, "Power - Long Press - Global Actions"); showGlobalActionsInternal(); break; case LONG_PRESS_POWER_SHUT_OFF: case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM: mPowerKeyHandled = true; - performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false, + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false, "Power - Long Press - Shut Off"); sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF); break; case LONG_PRESS_POWER_GO_TO_VOICE_ASSIST: mPowerKeyHandled = true; - performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false, + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false, "Power - Long Press - Go To Voice Assist"); final boolean keyguardActive = mKeyguardDelegate == null ? false @@ -1249,7 +1249,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { break; case VERY_LONG_PRESS_POWER_GLOBAL_ACTIONS: mPowerKeyHandled = true; - performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false, + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false, "Power - Very Long Press - Show Global Actions"); showGlobalActionsInternal(); break; @@ -1400,7 +1400,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public void run() { mEndCallKeyHandled = true; - performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false, + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false, "End Call - Long Press - Show Global Actions"); showGlobalActionsInternal(); } @@ -1667,7 +1667,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { return; } mHomeConsumed = true; - performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false, + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false, "Home - Long Press"); switch (mLongPressOnHomeBehavior) { case LONG_PRESS_HOME_ALL_APPS: @@ -3276,7 +3276,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } private void launchAssistLongPressAction() { - performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false, + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false, "Assist - Long Press"); sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST); @@ -4038,7 +4038,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } if (useHapticFeedback) { - performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false, + performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, false, "Virtual Key - Press"); } @@ -4759,7 +4759,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { public void setSafeMode(boolean safeMode) { mSafeMode = safeMode; if (safeMode) { - performHapticFeedbackLw(null, HapticFeedbackConstants.SAFE_MODE_ENABLED, true, + performHapticFeedback(HapticFeedbackConstants.SAFE_MODE_ENABLED, true, "Safe Mode Enabled"); } } @@ -5236,9 +5236,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { Settings.Global.THEATER_MODE_ON, 0) == 1; } + private boolean performHapticFeedback(int effectId, boolean always, String reason) { + return performHapticFeedback(Process.myUid(), mContext.getOpPackageName(), + effectId, always, reason); + } + @Override - public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always, - String reason) { + public boolean performHapticFeedback(int uid, String packageName, int effectId, + boolean always, String reason) { if (!mVibrator.hasVibrator()) { return false; } @@ -5253,16 +5258,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { return false; } - int owningUid; - String owningPackage; - if (win != null) { - owningUid = win.getOwningUid(); - owningPackage = win.getOwningPackage(); - } else { - owningUid = android.os.Process.myUid(); - owningPackage = mContext.getOpPackageName(); - } - mVibrator.vibrate(owningUid, owningPackage, effect, reason, VIBRATION_ATTRIBUTES); + mVibrator.vibrate(uid, packageName, effect, reason, VIBRATION_ATTRIBUTES); return true; } diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index d7e4b6cff4d8..c741513a949f 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -1300,8 +1300,8 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { /** * Call from application to perform haptic feedback on its window. */ - public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always, - String reason); + public boolean performHapticFeedback(int uid, String packageName, int effectId, + boolean always, String reason); /** * Called when we have started keeping the screen on because a window diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 58cf73a9a2bd..dc8c7b79feef 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -245,17 +245,13 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { } @Override - public boolean performHapticFeedback(IWindow window, int effectId, - boolean always) { - synchronized (mService.mGlobalLock) { - long ident = Binder.clearCallingIdentity(); - try { - return mService.mPolicy.performHapticFeedbackLw( - mService.windowForClientLocked(this, window, true), + public boolean performHapticFeedback(int effectId, boolean always) { + long ident = Binder.clearCallingIdentity(); + try { + return mService.mPolicy.performHapticFeedback(mUid, mPackageName, effectId, always, null); - } finally { - Binder.restoreCallingIdentity(ident); - } + } finally { + Binder.restoreCallingIdentity(ident); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java index 849772a4a26d..c3561f4bf6ab 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java @@ -313,8 +313,8 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { } @Override - public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always, - String reason) { + public boolean performHapticFeedback(int uid, String packageName, int effectId, + boolean always, String reason) { return false; } -- 2.11.0