Merge "Ensure a11y long click works on notif guts." into rvc-dev

This commit is contained in:
TreeHugger Robot
2020-06-02 20:38:06 +00:00
committed by Android (Google) Code Review
9 changed files with 69 additions and 94 deletions

View File

@@ -52,7 +52,7 @@ public class AppOpsInfo extends LinearLayout implements NotificationGuts.GutsCon
private NotificationGuts mGutsContainer;
private OnClickListener mOnOk = v -> {
closeControls(v);
mGutsContainer.closeControls(v, false);
};
public AppOpsInfo(Context context, AttributeSet attrs) {
@@ -117,6 +117,7 @@ public class AppOpsInfo extends LinearLayout implements NotificationGuts.GutsCon
});
TextView ok = findViewById(R.id.ok);
ok.setOnClickListener(mOnOk);
ok.setAccessibilityDelegate(mGutsContainer.getAccessibilityDelegate());
}
private String getPrompt() {
@@ -160,19 +161,6 @@ public class AppOpsInfo extends LinearLayout implements NotificationGuts.GutsCon
}
}
private void closeControls(View v) {
mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, false);
int[] parentLoc = new int[2];
int[] targetLoc = new int[2];
mGutsContainer.getLocationOnScreen(parentLoc);
v.getLocationOnScreen(targetLoc);
final int centerX = v.getWidth() / 2;
final int centerY = v.getHeight() / 2;
final int x = targetLoc[0] - parentLoc[0] + centerX;
final int y = targetLoc[1] - parentLoc[1] + centerY;
mGutsContainer.closeControls(x, y, false, false);
}
@Override
public void setGutsParent(NotificationGuts guts) {
mGutsContainer = guts;
@@ -200,6 +188,7 @@ public class AppOpsInfo extends LinearLayout implements NotificationGuts.GutsCon
@Override
public boolean handleCloseControls(boolean save, boolean force) {
mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, false);
return false;
}

View File

@@ -1122,9 +1122,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
public void setGutsView(MenuItem item) {
if (mGuts != null && item.getGutsView() instanceof NotificationGuts.GutsContent) {
((NotificationGuts.GutsContent) item.getGutsView()).setGutsParent(mGuts);
mGuts.setGutsContent((NotificationGuts.GutsContent) item.getGutsView());
if (getGuts() != null && item.getGutsView() instanceof NotificationGuts.GutsContent) {
getGuts().setGutsContent((NotificationGuts.GutsContent) item.getGutsView());
}
}

View File

@@ -137,13 +137,13 @@ public class NotificationConversationInfo extends LinearLayout implements
mSelectedAction = ACTION_HOME;
mShortcutManager.requestPinShortcut(mShortcutInfo, null);
mShadeController.animateCollapsePanels();
closeControls(v, true);
mGutsContainer.closeControls(v, true);
};
private OnClickListener mOnSnoozeClick = v -> {
mSelectedAction = ACTION_SNOOZE;
mOnSnoozeClickListener.onClick(v, 1);
closeControls(v, true);
mGutsContainer.closeControls(v, true);
};
*/
@@ -164,7 +164,7 @@ public class NotificationConversationInfo extends LinearLayout implements
private OnClickListener mOnDone = v -> {
mPressedApply = true;
closeControls(v, true);
mGutsContainer.closeControls(v, true);
};
public NotificationConversationInfo(Context context, AttributeSet attrs) {
@@ -258,6 +258,7 @@ public class NotificationConversationInfo extends LinearLayout implements
View done = findViewById(R.id.done);
done.setOnClickListener(mOnDone);
done.setAccessibilityDelegate(mGutsContainer.getAccessibilityDelegate());
}
private void bindActions() {
@@ -543,25 +544,6 @@ public class NotificationConversationInfo extends LinearLayout implements
controller.show();
}
/**
* Closes the controls and commits the updated importance values (indirectly).
*
* <p><b>Note,</b> this will only get called once the view is dismissing. This means that the
* user does not have the ability to undo the action anymore.
*/
@VisibleForTesting
void closeControls(View v, boolean save) {
int[] parentLoc = new int[2];
int[] targetLoc = new int[2];
mGutsContainer.getLocationOnScreen(parentLoc);
v.getLocationOnScreen(targetLoc);
final int centerX = v.getWidth() / 2;
final int centerY = v.getHeight() / 2;
final int x = targetLoc[0] - parentLoc[0] + centerX;
final int y = targetLoc[1] - parentLoc[1] + centerY;
mGutsContainer.closeControls(x, y, save, false /* force */);
}
@Override
public void setGutsParent(NotificationGuts guts) {
mGutsContainer = guts;

View File

@@ -22,12 +22,14 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import androidx.annotation.Nullable;
@@ -59,6 +61,31 @@ public class NotificationGuts extends FrameLayout {
private GutsContent mGutsContent;
private View.AccessibilityDelegate mGutsContentAccessibilityDelegate =
new View.AccessibilityDelegate() {
@Override
public void onInitializeAccessibilityNodeInfo(
View host, AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(host, info);
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK);
}
@Override
public boolean performAccessibilityAction(View host, int action, Bundle args) {
if (super.performAccessibilityAction(host, action, args)) {
return true;
}
switch (action) {
case AccessibilityNodeInfo.ACTION_LONG_CLICK:
closeControls(host, false);
return true;
}
return false;
}
};
public interface GutsContent {
public void setGutsParent(NotificationGuts listener);
@@ -110,6 +137,11 @@ public class NotificationGuts extends FrameLayout {
* view on the lockscreen
*/
boolean needsFalsingProtection();
/**
* Equivalent to {@link View#setAccessibilityDelegate(AccessibilityDelegate)}
*/
void setAccessibilityDelegate(AccessibilityDelegate gutsContentAccessibilityDelegate);
}
public interface OnGutsClosedListener {
@@ -146,6 +178,8 @@ public class NotificationGuts extends FrameLayout {
}
public void setGutsContent(GutsContent content) {
content.setGutsParent(this);
content.setAccessibilityDelegate(mGutsContentAccessibilityDelegate);
mGutsContent = content;
removeAllViews();
addView(mGutsContent.getContentView());
@@ -235,6 +269,22 @@ public class NotificationGuts extends FrameLayout {
}
}
/**
* Closes any exposed guts/views.
*/
public void closeControls(View eventSource, boolean save) {
int[] parentLoc = new int[2];
int[] targetLoc = new int[2];
getLocationOnScreen(parentLoc);
eventSource.getLocationOnScreen(targetLoc);
final int centerX = eventSource.getWidth() / 2;
final int centerY = eventSource.getHeight() / 2;
final int x = targetLoc[0] - parentLoc[0] + centerX;
final int y = targetLoc[1] - parentLoc[1] + centerY;
closeControls(x, y, save, false);
}
/**
* Closes any exposed guts/views.
*
@@ -243,7 +293,7 @@ public class NotificationGuts extends FrameLayout {
* @param save whether the state should be saved
* @param force whether the guts should be force-closed regardless of state.
*/
public void closeControls(int x, int y, boolean save, boolean force) {
private void closeControls(int x, int y, boolean save, boolean force) {
// First try to dismiss any blocking helper.
boolean wasBlockingHelperDismissed =
Dependency.get(NotificationBlockingHelperManager.class)

View File

@@ -141,7 +141,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
// used by standard ui
private OnClickListener mOnDismissSettings = v -> {
mPressedApply = true;
closeControls(v, true);
mGutsContainer.closeControls(v, true);
};
public NotificationInfo(Context context, AttributeSet attrs) {
@@ -250,7 +250,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
View done = findViewById(R.id.done);
done.setOnClickListener(mOnDismissSettings);
done.setAccessibilityDelegate(mGutsContainer.getAccessibilityDelegate());
View silent = findViewById(R.id.silence);
View alert = findViewById(R.id.alert);
@@ -330,7 +330,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
mUniqueChannelsInRow, mPkgIcon, mOnSettingsClickListener);
mChannelEditorDialogController.setOnFinishListener(() -> {
mPresentingChannelEditorDialog = false;
closeControls(this, false);
mGutsContainer.closeControls(this, false);
});
mChannelEditorDialogController.show();
}
@@ -528,25 +528,6 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
return intent;
}
/**
* Closes the controls and commits the updated importance values (indirectly).
*
* <p><b>Note,</b> this will only get called once the view is dismissing. This means that the
* user does not have the ability to undo the action anymore.
*/
@VisibleForTesting
void closeControls(View v, boolean save) {
int[] parentLoc = new int[2];
int[] targetLoc = new int[2];
mGutsContainer.getLocationOnScreen(parentLoc);
v.getLocationOnScreen(targetLoc);
final int centerX = v.getWidth() / 2;
final int centerY = v.getHeight() / 2;
final int x = targetLoc[0] - parentLoc[0] + centerX;
final int y = targetLoc[1] - parentLoc[1] + centerY;
mGutsContainer.closeControls(x, y, save, false /* force */);
}
@Override
public void setGutsParent(NotificationGuts guts) {
mGutsContainer = guts;

View File

@@ -380,16 +380,8 @@ public class NotificationSnooze extends LinearLayout
private void undoSnooze(View v) {
mSelectedOption = null;
int[] parentLoc = new int[2];
int[] targetLoc = new int[2];
mGutsContainer.getLocationOnScreen(parentLoc);
v.getLocationOnScreen(targetLoc);
final int centerX = v.getWidth() / 2;
final int centerY = v.getHeight() / 2;
final int x = targetLoc[0] - parentLoc[0] + centerX;
final int y = targetLoc[1] - parentLoc[1] + centerY;
showSnoozeOptions(false);
mGutsContainer.closeControls(x, y, false /* save */, false /* force */);
mGutsContainer.closeControls(v, false);
}
@Override

View File

@@ -89,7 +89,7 @@ public class PartialConversationInfo extends LinearLayout implements
private OnClickListener mOnDone = v -> {
mPressedApply = true;
closeControls(v, true);
mGutsContainer.closeControls(v, true);
};
public PartialConversationInfo(Context context, AttributeSet attrs) {
@@ -132,6 +132,7 @@ public class PartialConversationInfo extends LinearLayout implements
View done = findViewById(R.id.done);
done.setOnClickListener(mOnDone);
done.setAccessibilityDelegate(mGutsContainer.getAccessibilityDelegate());
}
private void bindActions() {
@@ -172,7 +173,7 @@ public class PartialConversationInfo extends LinearLayout implements
mUniqueChannelsInRow, mPkgIcon, mOnSettingsClickListener);
mChannelEditorDialogController.setOnFinishListener(() -> {
mPresentingChannelEditorDialog = false;
closeControls(this, false);
mGutsContainer.closeControls(this, false);
});
mChannelEditorDialogController.show();
}
@@ -317,25 +318,6 @@ public class PartialConversationInfo extends LinearLayout implements
}
}
/**
* Closes the controls and commits the updated importance values (indirectly).
*
* <p><b>Note,</b> this will only get called once the view is dismissing. This means that the
* user does not have the ability to undo the action anymore.
*/
@VisibleForTesting
void closeControls(View v, boolean save) {
int[] parentLoc = new int[2];
int[] targetLoc = new int[2];
mGutsContainer.getLocationOnScreen(parentLoc);
v.getLocationOnScreen(targetLoc);
final int centerX = v.getWidth() / 2;
final int centerY = v.getHeight() / 2;
final int x = targetLoc[0] - parentLoc[0] + centerX;
final int y = targetLoc[1] - parentLoc[1] + centerY;
mGutsContainer.closeControls(x, y, save, false /* force */);
}
@Override
public void setGutsParent(NotificationGuts guts) {
mGutsContainer = guts;

View File

@@ -144,7 +144,7 @@ public class AppOpsInfoTest extends SysuiTestCase {
final View okButton = mAppOpsInfo.findViewById(R.id.ok);
okButton.performClick();
assertEquals(1, latch.getCount());
verify(mGutsParent, times(1)).closeControls(anyInt(), anyInt(), anyBoolean(), anyBoolean());
verify(mGutsParent, times(1)).closeControls(eq(okButton), anyBoolean());
}
@Test

View File

@@ -173,7 +173,7 @@ public class NotificationConversationInfoTest extends SysuiTestCase {
doAnswer((Answer<Object>) invocation -> {
mNotificationInfo.handleCloseControls(true, false);
return null;
}).when(mNotificationGuts).closeControls(anyInt(), anyInt(), eq(true), eq(false));
}).when(mNotificationGuts).closeControls(any(View.class), eq(true));
// Our view is never attached to a window so the View#post methods in NotificationInfo never
// get called. Setting this will skip the post and do the action immediately.
mNotificationInfo.mSkipPost = true;