Merge "Fix back presses dismissing bubbles when IME is up" into qt-dev

This commit is contained in:
Mady Mellor
2019-04-18 18:21:22 +00:00
committed by Android (Google) Code Review
8 changed files with 120 additions and 14 deletions

View File

@@ -107,6 +107,7 @@ package android.app {
ctor public ActivityView(android.content.Context, android.util.AttributeSet);
ctor public ActivityView(android.content.Context, android.util.AttributeSet, int);
ctor public ActivityView(android.content.Context, android.util.AttributeSet, int, boolean);
method public int getVirtualDisplayId();
method public void onLayout(boolean, int, int, int, int);
method public void onLocationChanged();
method public void performBackPress();

View File

@@ -19,6 +19,7 @@ package android.app;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
import static android.view.Display.INVALID_DISPLAY;
import android.annotation.NonNull;
import android.annotation.TestApi;
@@ -376,6 +377,16 @@ public class ActivityView extends ViewGroup {
mSurfaceView.setVisibility(visibility);
}
/**
* @return the display id of the virtual display.
*/
public int getVirtualDisplayId() {
if (mVirtualDisplay != null) {
return mVirtualDisplay.getDisplay().getDisplayId();
}
return INVALID_DISPLAY;
}
/**
* Injects a pair of down/up key events with keycode {@link KeyEvent#KEYCODE_BACK} to the
* virtual display.

View File

@@ -16,6 +16,8 @@
package com.android.systemui.bubbles;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
@@ -535,6 +537,21 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
return mTempRect;
}
/**
* The display id of the expanded view, if the stack is expanded and not occluded by the
* status bar, otherwise returns {@link Display#INVALID_DISPLAY}.
*/
public int getExpandedDisplayId(Context context) {
boolean defaultDisplay = context.getDisplay() != null
&& context.getDisplay().getDisplayId() == DEFAULT_DISPLAY;
Bubble b = mStackView.getExpandedBubble();
if (defaultDisplay && b != null && isStackExpanded()
&& !mStatusBarWindowController.getPanelExpanded()) {
return b.expandedView.getVirtualDisplayId();
}
return INVALID_DISPLAY;
}
@VisibleForTesting
BubbleStackView getStackView() {
return mStackView;

View File

@@ -20,6 +20,7 @@ import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
import static android.util.StatsLogInternal.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_MISSING;
import static android.util.StatsLogInternal.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__ACTIVITY_INFO_NOT_RESIZABLE;
import static android.util.StatsLogInternal.BUBBLE_DEVELOPER_ERROR_REPORTED__ERROR__DOCUMENT_LAUNCH_NOT_ALWAYS;
import static android.view.Display.INVALID_DISPLAY;
import android.animation.LayoutTransition;
import android.animation.ObjectAnimator;
@@ -598,6 +599,16 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
return mBubbleIntent != null && mActivityView != null;
}
/**
* @return the display id of the virtual display.
*/
public int getVirtualDisplayId() {
if (usingActivityView()) {
return mActivityView.getVirtualDisplayId();
}
return INVALID_DISPLAY;
}
private void applyRowState(ExpandableNotificationRow view) {
view.reset();
view.setHeadsUp(false);

View File

@@ -15,6 +15,8 @@
*/
package com.android.systemui.statusbar.phone;
import static android.view.Display.INVALID_DISPLAY;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.content.res.Resources;
@@ -46,7 +48,9 @@ import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver;
import com.android.systemui.shared.system.QuickStepContract;
@@ -363,6 +367,13 @@ public class EdgeBackGestureHandler implements DisplayListener {
0 /* metaState */, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */,
KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
InputDevice.SOURCE_KEYBOARD);
// Bubble controller will give us a valid display id if it should get the back event
BubbleController bubbleController = Dependency.get(BubbleController.class);
int bubbleDisplayId = bubbleController.getExpandedDisplayId(mContext);
if (code == KeyEvent.KEYCODE_BACK && bubbleDisplayId != INVALID_DISPLAY) {
ev.setDisplayId(bubbleDisplayId);
}
InputManager.getInstance().injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
}
}

View File

@@ -523,12 +523,19 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
}
/**
* The bubble is shown in expanded state for the status bar.
* Whether the bubble is shown in expanded state for the status bar.
*/
public boolean getBubbleExpanded() {
return mCurrentState.bubbleExpanded;
}
/**
* Whether the status bar panel is expanded or not.
*/
public boolean getPanelExpanded() {
return mCurrentState.panelExpanded;
}
public void setStateListener(OtherwisedCollapsedListener listener) {
mListener = listener;
}

View File

@@ -48,10 +48,12 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.ImageView;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.shared.system.NavigationBarCompat;
@@ -73,6 +75,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
private final KeyButtonRipple mRipple;
private final OverviewProxyService mOverviewProxyService;
private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
private final InputManager mInputManager;
private final Runnable mCheckLongPress = new Runnable() {
public void run() {
@@ -96,6 +99,11 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
}
public KeyButtonView(Context context, AttributeSet attrs, int defStyle) {
this(context, attrs, defStyle, InputManager.getInstance());
}
@VisibleForTesting
public KeyButtonView(Context context, AttributeSet attrs, int defStyle, InputManager manager) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.KeyButtonView,
@@ -117,6 +125,7 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
mRipple = new KeyButtonRipple(context, this);
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
mInputManager = manager;
setBackground(mRipple);
forceHasOverlappingRendering(false);
}
@@ -318,16 +327,23 @@ public class KeyButtonView extends ImageView implements ButtonInterface {
0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
flags | KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
InputDevice.SOURCE_KEYBOARD);
//Make KeyEvent work on multi-display environment
if (getDisplay() != null) {
final int displayId = getDisplay().getDisplayId();
if (displayId != INVALID_DISPLAY) {
ev.setDisplayId(displayId);
}
int displayId = INVALID_DISPLAY;
// Make KeyEvent work on multi-display environment
if (getDisplay() != null) {
displayId = getDisplay().getDisplayId();
}
InputManager.getInstance().injectInputEvent(ev,
InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
// Bubble controller will give us a valid display id if it should get the back event
BubbleController bubbleController = Dependency.get(BubbleController.class);
int bubbleDisplayId = bubbleController.getExpandedDisplayId(mContext);
if (mCode == KeyEvent.KEYCODE_BACK && bubbleDisplayId != INVALID_DISPLAY) {
displayId = bubbleDisplayId;
}
if (displayId != INVALID_DISPLAY) {
ev.setDisplayId(displayId);
}
mInputManager.injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
}
@Override

View File

@@ -18,8 +18,16 @@ import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_FLAGS;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_NAV_ACTION;
import static org.mockito.ArgumentMatchers.argThat;
import static junit.framework.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.hardware.input.InputManager;
import android.metrics.LogMaker;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -31,12 +39,15 @@ import androidx.test.filters.SmallTest;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.bubbles.BubbleController;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
import org.mockito.Mockito;
import org.mockito.Captor;
import org.mockito.MockitoAnnotations;
import java.util.Objects;
@@ -47,12 +58,19 @@ public class KeyButtonViewTest extends SysuiTestCase {
private KeyButtonView mKeyButtonView;
private MetricsLogger mMetricsLogger;
private BubbleController mBubbleController;
private InputManager mInputManager = mock(InputManager.class);
@Captor
private ArgumentCaptor<KeyEvent> mInputEventCaptor;
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
TestableLooper.get(this).runWithLooper(() ->
mKeyButtonView = new KeyButtonView(mContext, null));
mBubbleController = mDependency.injectMockDependency(BubbleController.class);
TestableLooper.get(this).runWithLooper(() -> {
mKeyButtonView = new KeyButtonView(mContext, null, 0, mInputManager);
});
}
@Test
@@ -63,7 +81,7 @@ public class KeyButtonViewTest extends SysuiTestCase {
mKeyButtonView.setCode(code);
mKeyButtonView.sendEvent(action, flags);
Mockito.verify(mMetricsLogger).write(argThat(new ArgumentMatcher<LogMaker>() {
verify(mMetricsLogger).write(argThat(new ArgumentMatcher<LogMaker>() {
public String mReason;
@Override
@@ -91,4 +109,18 @@ public class KeyButtonViewTest extends SysuiTestCase {
}));
}
@Test
public void testBubbleEvents_bubbleExpanded() {
when(mBubbleController.getExpandedDisplayId(mContext)).thenReturn(3);
int action = KeyEvent.ACTION_DOWN;
int flags = 0;
int code = KeyEvent.KEYCODE_BACK;
mKeyButtonView.setCode(code);
mKeyButtonView.sendEvent(action, flags);
verify(mInputManager, times(1)).injectInputEvent(mInputEventCaptor.capture(),
anyInt());
assertEquals(3, mInputEventCaptor.getValue().getDisplayId());
}
}