Merge "Add better a11y support in QS" into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
d99c2e88e3
@@ -15,7 +15,6 @@
|
|||||||
package com.android.systemui.plugins.qs;
|
package com.android.systemui.plugins.qs;
|
||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
|
||||||
|
|
||||||
import com.android.systemui.plugins.FragmentBase;
|
import com.android.systemui.plugins.FragmentBase;
|
||||||
import com.android.systemui.plugins.annotations.DependsOn;
|
import com.android.systemui.plugins.annotations.DependsOn;
|
||||||
@@ -34,7 +33,7 @@ public interface QS extends FragmentBase {
|
|||||||
|
|
||||||
String ACTION = "com.android.systemui.action.PLUGIN_QS";
|
String ACTION = "com.android.systemui.action.PLUGIN_QS";
|
||||||
|
|
||||||
int VERSION = 13;
|
int VERSION = 14;
|
||||||
|
|
||||||
String TAG = "QS";
|
String TAG = "QS";
|
||||||
|
|
||||||
@@ -68,7 +67,12 @@ public interface QS extends FragmentBase {
|
|||||||
void setHeaderListening(boolean listening);
|
void setHeaderListening(boolean listening);
|
||||||
void notifyCustomizeChanged();
|
void notifyCustomizeChanged();
|
||||||
void setContainerController(QSContainerController controller);
|
void setContainerController(QSContainerController controller);
|
||||||
void setExpandClickListener(OnClickListener onClickListener);
|
|
||||||
|
/**
|
||||||
|
* Provide an action to collapse if expanded or expand if collapsed.
|
||||||
|
* @param action
|
||||||
|
*/
|
||||||
|
void setCollapseExpandAction(Runnable action);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the height difference between the QSPanel container and the QuickQSPanel container
|
* Returns the height difference between the QSPanel container and the QuickQSPanel container
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import com.android.systemui.plugins.qs.QSTile.State;
|
|||||||
@DependsOn(target = QSIconView.class)
|
@DependsOn(target = QSIconView.class)
|
||||||
@DependsOn(target = QSTile.class)
|
@DependsOn(target = QSTile.class)
|
||||||
public abstract class QSTileView extends LinearLayout {
|
public abstract class QSTileView extends LinearLayout {
|
||||||
public static final int VERSION = 2;
|
public static final int VERSION = 3;
|
||||||
|
|
||||||
public QSTileView(Context context) {
|
public QSTileView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
@@ -71,4 +71,7 @@ public abstract class QSTileView extends LinearLayout {
|
|||||||
public View getSecondaryLabel() {
|
public View getSecondaryLabel() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Sets the index of this tile in its layout */
|
||||||
|
public abstract void setPosition(int position);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,8 @@
|
|||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_marginStart="@dimen/qs_label_container_margin"
|
android:layout_marginStart="@dimen/qs_label_container_margin"
|
||||||
android:layout_marginEnd="0dp"
|
android:layout_marginEnd="0dp"
|
||||||
|
android:focusable="false"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
android:layout_gravity="center_vertical | start">
|
android:layout_gravity="center_vertical | start">
|
||||||
|
|
||||||
<com.android.systemui.util.SafeMarqueeTextView
|
<com.android.systemui.util.SafeMarqueeTextView
|
||||||
@@ -35,6 +37,8 @@
|
|||||||
android:ellipsize="marquee"
|
android:ellipsize="marquee"
|
||||||
android:marqueeRepeatLimit="1"
|
android:marqueeRepeatLimit="1"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
|
android:focusable="false"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
android:textAppearance="@style/TextAppearance.QS.TileLabel"/>
|
android:textAppearance="@style/TextAppearance.QS.TileLabel"/>
|
||||||
|
|
||||||
<com.android.systemui.util.SafeMarqueeTextView
|
<com.android.systemui.util.SafeMarqueeTextView
|
||||||
@@ -47,6 +51,8 @@
|
|||||||
android:marqueeRepeatLimit="1"
|
android:marqueeRepeatLimit="1"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
|
android:focusable="false"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
android:textAppearance="@style/TextAppearance.QS.TileLabel.Secondary"
|
android:textAppearance="@style/TextAppearance.QS.TileLabel.Secondary"
|
||||||
android:textColor="?android:attr/textColorSecondary"/>
|
android:textColor="?android:attr/textColorSecondary"/>
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import android.util.Log;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.view.accessibility.AccessibilityNodeInfo;
|
||||||
import android.view.animation.Interpolator;
|
import android.view.animation.Interpolator;
|
||||||
import android.view.animation.OvershootInterpolator;
|
import android.view.animation.OvershootInterpolator;
|
||||||
import android.widget.Scroller;
|
import android.widget.Scroller;
|
||||||
@@ -552,6 +553,51 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
|
|||||||
postInvalidateOnAnimation();
|
postInvalidateOnAnimation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int sanitizePageAction(int action) {
|
||||||
|
int pageLeftId = AccessibilityNodeInfo.AccessibilityAction.ACTION_PAGE_LEFT.getId();
|
||||||
|
int pageRightId = AccessibilityNodeInfo.AccessibilityAction.ACTION_PAGE_RIGHT.getId();
|
||||||
|
if (action == pageLeftId || action == pageRightId) {
|
||||||
|
if (!isLayoutRtl()) {
|
||||||
|
if (action == pageLeftId) {
|
||||||
|
return AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD;
|
||||||
|
} else {
|
||||||
|
return AccessibilityNodeInfo.ACTION_SCROLL_FORWARD;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (action == pageLeftId) {
|
||||||
|
return AccessibilityNodeInfo.ACTION_SCROLL_FORWARD;
|
||||||
|
} else {
|
||||||
|
return AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean performAccessibilityAction(int action, Bundle arguments) {
|
||||||
|
action = sanitizePageAction(action);
|
||||||
|
boolean performed = super.performAccessibilityAction(action, arguments);
|
||||||
|
if (performed && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
|
||||||
|
|| action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD)) {
|
||||||
|
requestAccessibilityFocus();
|
||||||
|
}
|
||||||
|
return performed;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
|
||||||
|
super.onInitializeAccessibilityNodeInfoInternal(info);
|
||||||
|
// getCurrentItem does not respect RTL, so it works well together with page actions that
|
||||||
|
// use left/right positioning.
|
||||||
|
if (getCurrentItem() != 0) {
|
||||||
|
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_PAGE_LEFT);
|
||||||
|
}
|
||||||
|
if (getCurrentItem() != mPages.size() - 1) {
|
||||||
|
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_PAGE_RIGHT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static Animator setupBounceAnimator(View view, int ordinal) {
|
private static Animator setupBounceAnimator(View view, int ordinal) {
|
||||||
view.setAlpha(0f);
|
view.setAlpha(0f);
|
||||||
view.setScaleX(0f);
|
view.setScaleX(0f);
|
||||||
|
|||||||
@@ -48,10 +48,5 @@ public interface QSFooter {
|
|||||||
*/
|
*/
|
||||||
void setKeyguardShowing(boolean keyguardShowing);
|
void setKeyguardShowing(boolean keyguardShowing);
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the {@link android.view.View.OnClickListener to be used on elements that expend QS.
|
|
||||||
*/
|
|
||||||
void setExpandClickListener(View.OnClickListener onClickListener);
|
|
||||||
|
|
||||||
default void disable(int state1, int state2, boolean animate) {}
|
default void disable(int state1, int state2, boolean animate) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,13 +23,11 @@ import android.content.res.Configuration;
|
|||||||
import android.database.ContentObserver;
|
import android.database.ContentObserver;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.accessibility.AccessibilityNodeInfo;
|
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
@@ -168,23 +166,6 @@ public class QSFooterView extends FrameLayout {
|
|||||||
super.onDetachedFromWindow();
|
super.onDetachedFromWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean performAccessibilityAction(int action, Bundle arguments) {
|
|
||||||
if (action == AccessibilityNodeInfo.ACTION_EXPAND) {
|
|
||||||
if (mExpandClickListener != null) {
|
|
||||||
mExpandClickListener.onClick(null);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.performAccessibilityAction(action, arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
|
|
||||||
super.onInitializeAccessibilityNodeInfo(info);
|
|
||||||
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND);
|
|
||||||
}
|
|
||||||
|
|
||||||
void disable(int state2) {
|
void disable(int state2) {
|
||||||
final boolean disabled = (state2 & DISABLE2_QUICK_SETTINGS) != 0;
|
final boolean disabled = (state2 & DISABLE2_QUICK_SETTINGS) != 0;
|
||||||
if (disabled == mQsDisabled) return;
|
if (disabled == mQsDisabled) return;
|
||||||
|
|||||||
@@ -114,12 +114,6 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
|
|||||||
mView.setKeyguardShowing();
|
mView.setKeyguardShowing();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** */
|
|
||||||
@Override
|
|
||||||
public void setExpandClickListener(View.OnClickListener onClickListener) {
|
|
||||||
mView.setExpandClickListener(onClickListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disable(int state1, int state2, boolean animate) {
|
public void disable(int state1, int state2, boolean animate) {
|
||||||
mView.disable(state2);
|
mView.disable(state2);
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import android.util.Log;
|
|||||||
import android.view.ContextThemeWrapper;
|
import android.view.ContextThemeWrapper;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.ViewTreeObserver;
|
import android.view.ViewTreeObserver;
|
||||||
|
|
||||||
@@ -717,8 +716,9 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setExpandClickListener(OnClickListener onClickListener) {
|
public void setCollapseExpandAction(Runnable action) {
|
||||||
mFooter.setExpandClickListener(onClickListener);
|
mQSPanelController.setCollapseExpandAction(action);
|
||||||
|
mQuickQSPanelController.setCollapseExpandAction(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import android.view.Gravity;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.view.accessibility.AccessibilityNodeInfo;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
@@ -62,6 +63,8 @@ public class QSPanel extends LinearLayout implements Tunable {
|
|||||||
private final int mMediaTopMargin;
|
private final int mMediaTopMargin;
|
||||||
private final int mMediaTotalBottomMargin;
|
private final int mMediaTotalBottomMargin;
|
||||||
|
|
||||||
|
private Runnable mCollapseExpandAction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The index where the content starts that needs to be moved between parents
|
* The index where the content starts that needs to be moved between parents
|
||||||
*/
|
*/
|
||||||
@@ -678,6 +681,28 @@ public class QSPanel extends LinearLayout implements Tunable {
|
|||||||
mShouldMoveMediaOnExpansion = shouldMoveMediaOnExpansion;
|
mShouldMoveMediaOnExpansion = shouldMoveMediaOnExpansion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
|
||||||
|
super.onInitializeAccessibilityNodeInfo(info);
|
||||||
|
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_COLLAPSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean performAccessibilityAction(int action, Bundle arguments) {
|
||||||
|
if (action == AccessibilityNodeInfo.ACTION_EXPAND
|
||||||
|
|| action == AccessibilityNodeInfo.ACTION_COLLAPSE) {
|
||||||
|
if (mCollapseExpandAction != null) {
|
||||||
|
mCollapseExpandAction.run();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.performAccessibilityAction(action, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCollapseExpandAction(Runnable action) {
|
||||||
|
mCollapseExpandAction = action;
|
||||||
|
}
|
||||||
|
|
||||||
private class H extends Handler {
|
private class H extends Handler {
|
||||||
private static final int ANNOUNCE_FOR_ACCESSIBILITY = 1;
|
private static final int ANNOUNCE_FOR_ACCESSIBILITY = 1;
|
||||||
|
|
||||||
|
|||||||
@@ -424,6 +424,14 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr
|
|||||||
return mView.getBrightnessView();
|
return mView.getBrightnessView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a listener to collapse/expand QS.
|
||||||
|
* @param action
|
||||||
|
*/
|
||||||
|
public void setCollapseExpandAction(Runnable action) {
|
||||||
|
mView.setCollapseExpandAction(action);
|
||||||
|
}
|
||||||
|
|
||||||
/** Sets whether we are currently on lock screen. */
|
/** Sets whether we are currently on lock screen. */
|
||||||
public void setIsOnKeyguard(boolean isOnKeyguard) {
|
public void setIsOnKeyguard(boolean isOnKeyguard) {
|
||||||
boolean isOnSplitShadeLockscreen = mShouldUseSplitNotificationShade && isOnKeyguard;
|
boolean isOnSplitShadeLockscreen = mShouldUseSplitNotificationShade && isOnKeyguard;
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import android.content.Context;
|
|||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.accessibility.AccessibilityNodeInfo;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
import com.android.internal.logging.UiEventLogger;
|
import com.android.internal.logging.UiEventLogger;
|
||||||
@@ -167,6 +168,14 @@ public class QuickQSPanel extends QSPanel {
|
|||||||
return QSEvent.QQS_TILE_VISIBLE;
|
return QSEvent.QQS_TILE_VISIBLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
|
||||||
|
super.onInitializeAccessibilityNodeInfo(info);
|
||||||
|
// Remove the collapse action from QSPanel
|
||||||
|
info.removeAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_COLLAPSE);
|
||||||
|
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND);
|
||||||
|
}
|
||||||
|
|
||||||
static class QQSSideLabelTileLayout extends SideLabelTileLayout {
|
static class QQSSideLabelTileLayout extends SideLabelTileLayout {
|
||||||
|
|
||||||
private boolean mLastSelected;
|
private boolean mLastSelected;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import android.provider.Settings;
|
|||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.view.accessibility.AccessibilityNodeInfo;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
@@ -240,6 +241,7 @@ public class TileLayout extends ViewGroup implements QSTileLayout {
|
|||||||
} else {
|
} else {
|
||||||
record.tileView.setLeftTopRightBottom(left, top, right, bottom);
|
record.tileView.setLeftTopRightBottom(left, top, right, bottom);
|
||||||
}
|
}
|
||||||
|
record.tileView.setPosition(i);
|
||||||
mLastTileBottom = bottom;
|
mLastTileBottom = bottom;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -296,4 +298,11 @@ public class TileLayout extends ViewGroup implements QSTileLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
|
||||||
|
super.onInitializeAccessibilityNodeInfoInternal(info);
|
||||||
|
info.setCollectionInfo(
|
||||||
|
new AccessibilityNodeInfo.CollectionInfo(mRecords.size(), 1, false));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,6 +69,12 @@ open class QSTileViewImpl @JvmOverloads constructor(
|
|||||||
internal const val TILE_STATE_RES_PREFIX = "tile_states_"
|
internal const val TILE_STATE_RES_PREFIX = "tile_states_"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var _position: Int = INVALID
|
||||||
|
|
||||||
|
override fun setPosition(position: Int) {
|
||||||
|
_position = position
|
||||||
|
}
|
||||||
|
|
||||||
override var heightOverride: Int = HeightOverrideable.NO_OVERRIDE
|
override var heightOverride: Int = HeightOverrideable.NO_OVERRIDE
|
||||||
set(value) {
|
set(value) {
|
||||||
if (field == value) return
|
if (field == value) return
|
||||||
@@ -404,6 +410,10 @@ open class QSTileViewImpl @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (_position != INVALID) {
|
||||||
|
info.collectionItemInfo =
|
||||||
|
AccessibilityNodeInfo.CollectionItemInfo(_position, 1, 0, 1, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
|
|
||||||
private final DozeParameters mDozeParameters;
|
private final DozeParameters mDozeParameters;
|
||||||
private final OnHeightChangedListener mOnHeightChangedListener = new OnHeightChangedListener();
|
private final OnHeightChangedListener mOnHeightChangedListener = new OnHeightChangedListener();
|
||||||
private final OnClickListener mOnClickListener = new OnClickListener();
|
private final Runnable mCollapseExpandAction = new CollapseExpandAction();
|
||||||
private final OnOverscrollTopChangedListener
|
private final OnOverscrollTopChangedListener
|
||||||
mOnOverscrollTopChangedListener =
|
mOnOverscrollTopChangedListener =
|
||||||
new OnOverscrollTopChangedListener();
|
new OnOverscrollTopChangedListener();
|
||||||
@@ -3573,7 +3573,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
public void onFragmentViewCreated(String tag, Fragment fragment) {
|
public void onFragmentViewCreated(String tag, Fragment fragment) {
|
||||||
mQs = (QS) fragment;
|
mQs = (QS) fragment;
|
||||||
mQs.setPanelView(mHeightListener);
|
mQs.setPanelView(mHeightListener);
|
||||||
mQs.setExpandClickListener(mOnClickListener);
|
mQs.setCollapseExpandAction(mCollapseExpandAction);
|
||||||
mQs.setHeaderClickable(isQsExpansionEnabled());
|
mQs.setHeaderClickable(isQsExpansionEnabled());
|
||||||
mQs.setOverscrolling(mStackScrollerOverscrolling);
|
mQs.setOverscrolling(mStackScrollerOverscrolling);
|
||||||
mQs.setInSplitShade(mShouldUseSplitNotificationShade);
|
mQs.setInSplitShade(mShouldUseSplitNotificationShade);
|
||||||
@@ -4216,9 +4216,9 @@ public class NotificationPanelViewController extends PanelViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class OnClickListener implements View.OnClickListener {
|
private class CollapseExpandAction implements Runnable {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void run() {
|
||||||
onQsExpansionStarted();
|
onQsExpansionStarted();
|
||||||
if (mQsExpanded) {
|
if (mQsExpanded) {
|
||||||
flingSettings(0 /* vel */, FLING_COLLAPSE, null /* onFinishRunnable */,
|
flingSettings(0 /* vel */, FLING_COLLAPSE, null /* onFinishRunnable */,
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import static org.mockito.ArgumentMatchers.anyInt;
|
|||||||
import static org.mockito.Mockito.doAnswer;
|
import static org.mockito.Mockito.doAnswer;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
@@ -304,6 +305,16 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
|
|||||||
assertThat(mQsFragmentView.getY()).isEqualTo(-qsAbsoluteBottom);
|
assertThat(mQsFragmentView.getY()).isEqualTo(-qsAbsoluteBottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setCollapseExpandAction_passedToControllers() {
|
||||||
|
Runnable action = () -> {};
|
||||||
|
QSFragment fragment = resumeAndGetFragment();
|
||||||
|
fragment.setCollapseExpandAction(action);
|
||||||
|
|
||||||
|
verify(mQSPanelController).setCollapseExpandAction(action);
|
||||||
|
verify(mQuickQSPanelController).setCollapseExpandAction(action);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Fragment instantiate(Context context, String className, Bundle arguments) {
|
protected Fragment instantiate(Context context, String className, Bundle arguments) {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
|
|||||||
@@ -21,24 +21,19 @@ import android.testing.TestableLooper
|
|||||||
import android.testing.TestableLooper.RunWithLooper
|
import android.testing.TestableLooper.RunWithLooper
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.view.accessibility.AccessibilityNodeInfo
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
import com.android.systemui.R
|
import com.android.systemui.R
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
import com.android.systemui.plugins.qs.QSTileView
|
|
||||||
import com.android.systemui.qs.QSPanelControllerBase.TileRecord
|
|
||||||
import com.android.systemui.qs.logging.QSLogger
|
|
||||||
import com.android.systemui.qs.tileimpl.QSTileImpl
|
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.mockito.ArgumentMatchers.any
|
import org.mockito.Mockito.mock
|
||||||
import org.mockito.ArgumentMatchers.anyBoolean
|
import org.mockito.Mockito.verify
|
||||||
import org.mockito.Mock
|
|
||||||
import org.mockito.MockitoAnnotations
|
import org.mockito.MockitoAnnotations
|
||||||
import org.mockito.Mockito.`when` as whenever
|
|
||||||
|
|
||||||
@RunWith(AndroidTestingRunner::class)
|
@RunWith(AndroidTestingRunner::class)
|
||||||
@RunWithLooper
|
@RunWithLooper
|
||||||
@@ -47,22 +42,8 @@ class QSPanelTest : SysuiTestCase() {
|
|||||||
private lateinit var mTestableLooper: TestableLooper
|
private lateinit var mTestableLooper: TestableLooper
|
||||||
private lateinit var mQsPanel: QSPanel
|
private lateinit var mQsPanel: QSPanel
|
||||||
|
|
||||||
@Mock
|
|
||||||
private lateinit var mHost: QSTileHost
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private lateinit var dndTile: QSTileImpl<*>
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private lateinit var mDndTileRecord: TileRecord
|
|
||||||
|
|
||||||
@Mock
|
|
||||||
private lateinit var mQSLogger: QSLogger
|
|
||||||
private lateinit var mParentView: ViewGroup
|
private lateinit var mParentView: ViewGroup
|
||||||
|
|
||||||
@Mock
|
|
||||||
private lateinit var mQSTileView: QSTileView
|
|
||||||
|
|
||||||
private lateinit var mFooter: View
|
private lateinit var mFooter: View
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@@ -71,8 +52,6 @@ class QSPanelTest : SysuiTestCase() {
|
|||||||
MockitoAnnotations.initMocks(this)
|
MockitoAnnotations.initMocks(this)
|
||||||
mTestableLooper = TestableLooper.get(this)
|
mTestableLooper = TestableLooper.get(this)
|
||||||
|
|
||||||
mDndTileRecord.tile = dndTile
|
|
||||||
mDndTileRecord.tileView = mQSTileView
|
|
||||||
mTestableLooper.runWithLooper {
|
mTestableLooper.runWithLooper {
|
||||||
mQsPanel = QSPanel(mContext, null)
|
mQsPanel = QSPanel(mContext, null)
|
||||||
mQsPanel.initialize()
|
mQsPanel.initialize()
|
||||||
@@ -86,11 +65,6 @@ class QSPanelTest : SysuiTestCase() {
|
|||||||
mParentView = FrameLayout(mContext).apply {
|
mParentView = FrameLayout(mContext).apply {
|
||||||
addView(mQsPanel)
|
addView(mQsPanel)
|
||||||
}
|
}
|
||||||
|
|
||||||
whenever(dndTile.tileSpec).thenReturn("dnd")
|
|
||||||
whenever(mHost.tiles).thenReturn(emptyList())
|
|
||||||
whenever(mHost.createTileView(any(), any(), anyBoolean())).thenReturn(mQSTileView)
|
|
||||||
mQsPanel.addTile(mDndTileRecord)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,6 +111,24 @@ class QSPanelTest : SysuiTestCase() {
|
|||||||
assertThat(mQsPanel.indexOfChild(mQsPanel.mSecurityFooter)).isEqualTo(-1)
|
assertThat(mQsPanel.indexOfChild(mQsPanel.mSecurityFooter)).isEqualTo(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testHasCollapseAccessibilityAction() {
|
||||||
|
val info = AccessibilityNodeInfo(mQsPanel)
|
||||||
|
mQsPanel.onInitializeAccessibilityNodeInfo(info)
|
||||||
|
|
||||||
|
assertThat(info.actions and AccessibilityNodeInfo.ACTION_COLLAPSE).isNotEqualTo(0)
|
||||||
|
assertThat(info.actions and AccessibilityNodeInfo.ACTION_EXPAND).isEqualTo(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testCollapseActionCallsRunnable() {
|
||||||
|
val mockRunnable = mock(Runnable::class.java)
|
||||||
|
mQsPanel.setCollapseExpandAction(mockRunnable)
|
||||||
|
|
||||||
|
mQsPanel.performAccessibilityAction(AccessibilityNodeInfo.ACTION_COLLAPSE, null)
|
||||||
|
verify(mockRunnable).run()
|
||||||
|
}
|
||||||
|
|
||||||
private fun getNewOrientationConfig(@Configuration.Orientation newOrientation: Int) =
|
private fun getNewOrientationConfig(@Configuration.Orientation newOrientation: Int) =
|
||||||
context.resources.configuration.apply { orientation = newOrientation }
|
context.resources.configuration.apply { orientation = newOrientation }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package com.android.systemui.qs
|
||||||
|
|
||||||
|
import android.testing.AndroidTestingRunner
|
||||||
|
import android.testing.TestableLooper
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.view.accessibility.AccessibilityNodeInfo
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.google.common.truth.Truth
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.Mockito
|
||||||
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
|
@RunWith(AndroidTestingRunner::class)
|
||||||
|
@TestableLooper.RunWithLooper
|
||||||
|
@SmallTest
|
||||||
|
class QuickQSPanelTest : SysuiTestCase() {
|
||||||
|
|
||||||
|
private lateinit var testableLooper: TestableLooper
|
||||||
|
private lateinit var quickQSPanel: QuickQSPanel
|
||||||
|
|
||||||
|
private lateinit var parentView: ViewGroup
|
||||||
|
|
||||||
|
@Before
|
||||||
|
@Throws(Exception::class)
|
||||||
|
fun setup() {
|
||||||
|
MockitoAnnotations.initMocks(this)
|
||||||
|
testableLooper = TestableLooper.get(this)
|
||||||
|
|
||||||
|
testableLooper.runWithLooper {
|
||||||
|
quickQSPanel = QuickQSPanel(mContext, null)
|
||||||
|
quickQSPanel.initialize()
|
||||||
|
|
||||||
|
quickQSPanel.onFinishInflate()
|
||||||
|
quickQSPanel.setSecurityFooter(View(mContext), false)
|
||||||
|
quickQSPanel.setHeaderContainer(LinearLayout(mContext))
|
||||||
|
// Provides a parent with non-zero size for QSPanel
|
||||||
|
parentView = FrameLayout(mContext).apply {
|
||||||
|
addView(quickQSPanel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testHasExpandAccessibilityAction() {
|
||||||
|
val info = AccessibilityNodeInfo(quickQSPanel)
|
||||||
|
quickQSPanel.onInitializeAccessibilityNodeInfo(info)
|
||||||
|
|
||||||
|
Truth.assertThat(info.actions and AccessibilityNodeInfo.ACTION_EXPAND).isNotEqualTo(0)
|
||||||
|
Truth.assertThat(info.actions and AccessibilityNodeInfo.ACTION_COLLAPSE).isEqualTo(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testExpandActionCallsRunnable() {
|
||||||
|
val mockRunnable = Mockito.mock(Runnable::class.java)
|
||||||
|
quickQSPanel.setCollapseExpandAction(mockRunnable)
|
||||||
|
|
||||||
|
quickQSPanel.performAccessibilityAction(AccessibilityNodeInfo.ACTION_EXPAND, null)
|
||||||
|
Mockito.verify(mockRunnable).run()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,6 +28,7 @@ import static org.mockito.Mockito.times;
|
|||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import android.test.suitebuilder.annotation.SmallTest;
|
import android.test.suitebuilder.annotation.SmallTest;
|
||||||
|
import android.view.accessibility.AccessibilityNodeInfo;
|
||||||
|
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
@@ -170,4 +171,36 @@ public class TileLayoutTest extends SysuiTestCase {
|
|||||||
mTileLayout.measure(mLayoutSizeForOneTile, mLayoutSizeForOneTile);
|
mTileLayout.measure(mLayoutSizeForOneTile, mLayoutSizeForOneTile);
|
||||||
assertEquals(0, mTileLayout.getMeasuredHeight());
|
assertEquals(0, mTileLayout.getMeasuredHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCollectionInfo() {
|
||||||
|
QSPanelControllerBase.TileRecord tileRecord1 = createTileRecord();
|
||||||
|
QSPanelControllerBase.TileRecord tileRecord2 = createTileRecord();
|
||||||
|
AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(mTileLayout);
|
||||||
|
mTileLayout.addTile(tileRecord1);
|
||||||
|
|
||||||
|
mTileLayout.onInitializeAccessibilityNodeInfo(info);
|
||||||
|
AccessibilityNodeInfo.CollectionInfo collectionInfo = info.getCollectionInfo();
|
||||||
|
assertEquals(1, collectionInfo.getRowCount());
|
||||||
|
assertEquals(1, collectionInfo.getColumnCount()); // always use one column
|
||||||
|
|
||||||
|
mTileLayout.addTile(tileRecord2);
|
||||||
|
mTileLayout.onInitializeAccessibilityNodeInfo(info);
|
||||||
|
collectionInfo = info.getCollectionInfo();
|
||||||
|
assertEquals(2, collectionInfo.getRowCount());
|
||||||
|
assertEquals(1, collectionInfo.getColumnCount()); // always use one column
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetPositionOnTiles() {
|
||||||
|
QSPanelControllerBase.TileRecord tileRecord1 = createTileRecord();
|
||||||
|
QSPanelControllerBase.TileRecord tileRecord2 = createTileRecord();
|
||||||
|
mTileLayout.addTile(tileRecord1);
|
||||||
|
mTileLayout.addTile(tileRecord2);
|
||||||
|
mTileLayout.measure(mLayoutSizeForOneTile * 2, mLayoutSizeForOneTile * 2);
|
||||||
|
mTileLayout.layout(0, 0, mLayoutSizeForOneTile * 2, mLayoutSizeForOneTile * 2);
|
||||||
|
|
||||||
|
verify(tileRecord1.tileView).setPosition(0);
|
||||||
|
verify(tileRecord2.tileView).setPosition(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import android.testing.AndroidTestingRunner
|
|||||||
import android.testing.TestableLooper
|
import android.testing.TestableLooper
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.accessibility.AccessibilityNodeInfo
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
import com.android.systemui.R
|
import com.android.systemui.R
|
||||||
@@ -257,6 +258,28 @@ class QSTileViewImplTest : SysuiTestCase() {
|
|||||||
assertThat((tileView.secondaryLabel as TextView).text).isEqualTo(onString)
|
assertThat((tileView.secondaryLabel as TextView).text).isEqualTo(onString)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testCollectionItemInfoHasPosition() {
|
||||||
|
val position = 5
|
||||||
|
tileView.setPosition(position)
|
||||||
|
|
||||||
|
val info = AccessibilityNodeInfo(tileView)
|
||||||
|
tileView.onInitializeAccessibilityNodeInfo(info)
|
||||||
|
|
||||||
|
assertThat(info.collectionItemInfo.rowIndex).isEqualTo(position)
|
||||||
|
assertThat(info.collectionItemInfo.rowSpan).isEqualTo(1)
|
||||||
|
assertThat(info.collectionItemInfo.columnIndex).isEqualTo(0)
|
||||||
|
assertThat(info.collectionItemInfo.columnSpan).isEqualTo(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testCollectionItemInfoNoPosition() {
|
||||||
|
val info = AccessibilityNodeInfo(tileView)
|
||||||
|
tileView.onInitializeAccessibilityNodeInfo(info)
|
||||||
|
|
||||||
|
assertThat(info.collectionItemInfo).isNull()
|
||||||
|
}
|
||||||
|
|
||||||
class FakeTileView(
|
class FakeTileView(
|
||||||
context: Context,
|
context: Context,
|
||||||
icon: QSIconView,
|
icon: QSIconView,
|
||||||
|
|||||||
Reference in New Issue
Block a user