diff options
39 files changed, 678 insertions, 906 deletions
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java index 88649392c23c..9b19fc4d3ef2 100644 --- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java +++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java @@ -110,6 +110,11 @@ public class CameraDeviceImpl extends CameraDevice private int mRepeatingRequestId = REQUEST_ID_NONE; // Latest repeating request list's types private int[] mRepeatingRequestTypes; + + // Cache failed requests to process later in case of a repeating error callback + private int mFailedRepeatingRequestId = REQUEST_ID_NONE; + private int[] mFailedRepeatingRequestTypes; + // Map stream IDs to input/output configurations private SimpleEntry<Integer, InputConfiguration> mConfiguredInput = new SimpleEntry<>(REQUEST_ID_NONE, null); @@ -1326,16 +1331,25 @@ public class CameraDeviceImpl extends CameraDevice int requestId = mRepeatingRequestId; mRepeatingRequestId = REQUEST_ID_NONE; + mFailedRepeatingRequestId = REQUEST_ID_NONE; int[] requestTypes = mRepeatingRequestTypes; mRepeatingRequestTypes = null; + mFailedRepeatingRequestTypes = null; long lastFrameNumber; try { lastFrameNumber = mRemoteDevice.cancelRequest(requestId); } catch (IllegalArgumentException e) { if (DEBUG) { - Log.v(TAG, "Repeating request was already stopped for request " + requestId); + Log.v(TAG, "Repeating request was already stopped for request " + + requestId); } + // Cache request id and request types in case of a race with + // "onRepeatingRequestError" which may no yet be scheduled on another thread + // or blocked by us. + mFailedRepeatingRequestId = requestId; + mFailedRepeatingRequestTypes = requestTypes; + // Repeating request was already stopped. Nothing more to do. return; } @@ -1965,7 +1979,17 @@ public class CameraDeviceImpl extends CameraDevice synchronized(mInterfaceLock) { // Camera is already closed or no repeating request is present. if (mRemoteDevice == null || mRepeatingRequestId == REQUEST_ID_NONE) { - return; // Camera already closed + if ((mFailedRepeatingRequestId == repeatingRequestId) && + (mFailedRepeatingRequestTypes != null) && (mRemoteDevice != null)) { + Log.v(TAG, "Resuming stop of failed repeating request with id: " + + mFailedRepeatingRequestId); + + checkEarlyTriggerSequenceCompleteLocked(mFailedRepeatingRequestId, + lastFrameNumber, mFailedRepeatingRequestTypes); + mFailedRepeatingRequestId = REQUEST_ID_NONE; + mFailedRepeatingRequestTypes = null; + } + return; } // Redirect device callback to the offline session in case we are in the middle diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 8764ccc9d5f8..a85c9b5cb5ec 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -4769,6 +4769,16 @@ public interface WindowManager extends ViewManager { return Integer.toString(inputFeature); } } + + /** + * True if the window should consume all pointer events itself, regardless of whether they + * are inside of the window. If the window is modal, its touchable region will expand to the + * size of its task. + * @hide + */ + public boolean isModal() { + return (flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0; + } } /** diff --git a/core/res/res/layout/splash_screen_view.xml b/core/res/res/layout/splash_screen_view.xml index 2b9f95227f08..304affe068a4 100644 --- a/core/res/res/layout/splash_screen_view.xml +++ b/core/res/res/layout/splash_screen_view.xml @@ -36,6 +36,7 @@ android:layout_marginBottom="60dp" android:padding="0dp" android:background="@null" + android:forceHasOverlappingRendering="false" android:contentDescription="@string/splash_screen_view_branding_description"/> </android.window.SplashScreenView>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java index 003d8a3f2fef..e7b5744dd21b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java @@ -72,6 +72,7 @@ public class SplashScreenExitAnimation implements Animator.AnimatorListener { private final int mAppRevealDuration; private final int mAnimationDuration; private final float mIconStartAlpha; + private final float mBrandingStartAlpha; private final TransactionPool mTransactionPool; private ValueAnimator mMainAnimator; @@ -94,9 +95,17 @@ public class SplashScreenExitAnimation implements Animator.AnimatorListener { || iconView.getLayoutParams().height == 0) { mIconFadeOutDuration = 0; mIconStartAlpha = 0; + mBrandingStartAlpha = 0; mAppRevealDelay = 0; } else { iconView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + // The branding view could only exists when the icon is present. + final View brandingView = view.getBrandingView(); + if (brandingView != null) { + mBrandingStartAlpha = brandingView.getAlpha(); + } else { + mBrandingStartAlpha = 0; + } mIconFadeOutDuration = context.getResources().getInteger( R.integer.starting_window_app_reveal_icon_fade_out_duration); mAppRevealDelay = context.getResources().getInteger( @@ -334,13 +343,21 @@ public class SplashScreenExitAnimation implements Animator.AnimatorListener { // ignore } - private void onAnimationProgress(float linearProgress) { - View iconView = mSplashScreenView.getIconView(); + private void onFadeOutProgress(float linearProgress) { + final float iconProgress = ICON_INTERPOLATOR.getInterpolation( + getProgress(linearProgress, 0 /* delay */, mIconFadeOutDuration)); + final View iconView = mSplashScreenView.getIconView(); + final View brandingView = mSplashScreenView.getBrandingView(); if (iconView != null) { - final float iconProgress = ICON_INTERPOLATOR.getInterpolation( - getProgress(linearProgress, 0 /* delay */, mIconFadeOutDuration)); iconView.setAlpha(mIconStartAlpha * (1 - iconProgress)); } + if (brandingView != null) { + brandingView.setAlpha(mBrandingStartAlpha * (1 - iconProgress)); + } + } + + private void onAnimationProgress(float linearProgress) { + onFadeOutProgress(linearProgress); final float revealLinearProgress = getProgress(linearProgress, mAppRevealDelay, mAppRevealDuration); diff --git a/packages/SystemUI/res/color/prv_text_color_on_accent.xml b/packages/SystemUI/res/color/prv_text_color_on_accent.xml deleted file mode 100644 index 9f44acadb420..000000000000 --- a/packages/SystemUI/res/color/prv_text_color_on_accent.xml +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - ~ Copyright (C) 2021 The Android Open Source Project - ~ - ~ Licensed under the Apache License, Version 2.0 (the "License"); - ~ you may not use this file except in compliance with the License. - ~ You may obtain a copy of the License at - ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 - ~ - ~ Unless required by applicable law or agreed to in writing, software - ~ distributed under the License is distributed on an "AS IS" BASIS, - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ~ See the License for the specific language governing permissions and - ~ limitations under the License. - --> -<selector xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" - xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:color="?androidprv:attr/textColorOnAccent" /> -</selector>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/qs_dialog_btn_filled.xml b/packages/SystemUI/res/drawable/qs_dialog_btn_filled.xml index 1a128dfe8b10..14cb1de9fa2d 100644 --- a/packages/SystemUI/res/drawable/qs_dialog_btn_filled.xml +++ b/packages/SystemUI/res/drawable/qs_dialog_btn_filled.xml @@ -16,8 +16,8 @@ --> <inset xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" - android:insetTop="@dimen/qs_dialog_button_vertical_inset" - android:insetBottom="@dimen/qs_dialog_button_vertical_inset"> + android:insetTop="@dimen/dialog_button_vertical_inset" + android:insetBottom="@dimen/dialog_button_vertical_inset"> <ripple android:color="?android:attr/colorControlHighlight"> <item android:id="@android:id/mask"> <shape android:shape="rectangle"> @@ -29,10 +29,10 @@ <shape android:shape="rectangle"> <corners android:radius="?android:attr/buttonCornerRadius"/> <solid android:color="?androidprv:attr/colorAccentPrimary"/> - <padding android:left="@dimen/qs_dialog_button_horizontal_padding" - android:top="@dimen/qs_dialog_button_vertical_padding" - android:right="@dimen/qs_dialog_button_horizontal_padding" - android:bottom="@dimen/qs_dialog_button_vertical_padding"/> + <padding android:left="@dimen/dialog_button_horizontal_padding" + android:top="@dimen/dialog_button_vertical_padding" + android:right="@dimen/dialog_button_horizontal_padding" + android:bottom="@dimen/dialog_button_vertical_padding"/> </shape> </item> </ripple> diff --git a/packages/SystemUI/res/drawable/qs_dialog_btn_outline.xml b/packages/SystemUI/res/drawable/qs_dialog_btn_outline.xml index 467c20f3ffcd..665b4564ebf1 100644 --- a/packages/SystemUI/res/drawable/qs_dialog_btn_outline.xml +++ b/packages/SystemUI/res/drawable/qs_dialog_btn_outline.xml @@ -16,8 +16,8 @@ --> <inset xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" - android:insetTop="@dimen/qs_dialog_button_vertical_inset" - android:insetBottom="@dimen/qs_dialog_button_vertical_inset"> + android:insetTop="@dimen/dialog_button_vertical_inset" + android:insetBottom="@dimen/dialog_button_vertical_inset"> <ripple android:color="?android:attr/colorControlHighlight"> <item android:id="@android:id/mask"> <shape android:shape="rectangle"> @@ -32,10 +32,10 @@ <stroke android:color="?androidprv:attr/colorAccentPrimary" android:width="1dp" /> - <padding android:left="@dimen/qs_dialog_button_horizontal_padding" - android:top="@dimen/qs_dialog_button_vertical_padding" - android:right="@dimen/qs_dialog_button_horizontal_padding" - android:bottom="@dimen/qs_dialog_button_vertical_padding"/> + <padding android:left="@dimen/dialog_button_horizontal_padding" + android:top="@dimen/dialog_button_vertical_padding" + android:right="@dimen/dialog_button_horizontal_padding" + android:bottom="@dimen/dialog_button_vertical_padding"/> </shape> </item> </ripple> diff --git a/packages/SystemUI/res/layout/alert_dialog_button_bar_systemui.xml b/packages/SystemUI/res/layout/alert_dialog_button_bar_systemui.xml new file mode 100644 index 000000000000..a3e289a42d05 --- /dev/null +++ b/packages/SystemUI/res/layout/alert_dialog_button_bar_systemui.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@*android:id/buttonPanel" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:scrollbarAlwaysDrawVerticalTrack="true" + android:scrollIndicators="top|bottom" + android:fillViewport="true" + android:paddingTop="@dimen/dialog_button_bar_top_padding" + android:paddingStart="@dimen/dialog_side_padding" + android:paddingEnd="@dimen/dialog_side_padding" + android:paddingBottom="@dimen/dialog_bottom_padding" + style="?android:attr/buttonBarStyle"> + <com.android.internal.widget.ButtonBarLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layoutDirection="locale" + android:orientation="horizontal" + android:gravity="bottom"> + + <Button + android:id="@android:id/button3" + style="?android:attr/buttonBarNeutralButtonStyle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + + <Space + android:id="@*android:id/spacer" + android:layout_width="0dp" + android:layout_height="0dp" + android:layout_weight="1" + android:visibility="invisible" /> + + <Button + android:id="@android:id/button2" + style="?android:attr/buttonBarNegativeButtonStyle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + + <Button + android:id="@android:id/button1" + style="?android:attr/buttonBarPositiveButtonStyle" + android:layout_marginStart="8dp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + </com.android.internal.widget.ButtonBarLayout> +</ScrollView>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/alert_dialog_systemui.xml b/packages/SystemUI/res/layout/alert_dialog_systemui.xml new file mode 100644 index 000000000000..f280cbd16a0f --- /dev/null +++ b/packages/SystemUI/res/layout/alert_dialog_systemui.xml @@ -0,0 +1,91 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<com.android.internal.widget.AlertDialogLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@*android:id/parentPanel" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center_horizontal|top" + android:orientation="vertical" + android:paddingTop="@dimen/dialog_top_padding" + > + + <include layout="@layout/alert_dialog_title_systemui" /> + + <FrameLayout + android:id="@*android:id/contentPanel" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="48dp" + android:paddingStart="@dimen/dialog_side_padding" + android:paddingEnd="@dimen/dialog_side_padding" + > + + <ScrollView + android:id="@*android:id/scrollView" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:clipToPadding="false"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <Space + android:id="@*android:id/textSpacerNoTitle" + android:visibility="gone" + android:layout_width="match_parent" + android:layout_height="0dp" /> + + <TextView + android:id="@*android:id/message" + android:layout_width="match_parent" + android:layout_height="wrap_content" + style="@style/TextAppearance.Dialog.Body.Message" /> + + <Space + android:id="@*android:id/textSpacerNoButtons" + android:visibility="gone" + android:layout_width="match_parent" + android:layout_height="6dp" /> + </LinearLayout> + </ScrollView> + </FrameLayout> + + <FrameLayout + android:id="@*android:id/customPanel" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="48dp" + android:paddingStart="@dimen/dialog_side_padding" + android:paddingEnd="@dimen/dialog_side_padding" + > + + <FrameLayout + android:id="@*android:id/custom" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + </FrameLayout> + + <include + android:layout_width="match_parent" + android:layout_height="wrap_content" + layout="@layout/alert_dialog_button_bar_systemui" /> + +</com.android.internal.widget.AlertDialogLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/alert_dialog_title_systemui.xml b/packages/SystemUI/res/layout/alert_dialog_title_systemui.xml new file mode 100644 index 000000000000..480ba001fae1 --- /dev/null +++ b/packages/SystemUI/res/layout/alert_dialog_title_systemui.xml @@ -0,0 +1,63 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" + android:id="@*android:id/topPanel" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:paddingStart="@dimen/dialog_side_padding" + android:paddingEnd="@dimen/dialog_side_padding" +> + + <!-- If the client uses a customTitle, it will be added here. --> + + <LinearLayout + android:id="@*android:id/title_template" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:gravity="center_horizontal|top"> + + <ImageView + android:id="@*android:id/icon" + android:layout_width="32dp" + android:layout_height="32dp" + android:layout_marginBottom="16dp" + android:scaleType="fitCenter" + android:src="@null" + android:tint="?androidprv:attr/colorAccentPrimaryVariant" + /> + + <com.android.internal.widget.DialogTitle + android:id="@*android:id/alertTitle" + android:singleLine="true" + android:ellipsize="end" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="16dp" + style="@style/TextAppearance.Dialog.Title" /> + </LinearLayout> + + <Space + android:id="@*android:id/titleDividerNoCustom" + android:visibility="gone" + android:layout_width="match_parent" + android:layout_height="0dp" /> +</LinearLayout> diff --git a/packages/SystemUI/res/layout/privacy_dialog.xml b/packages/SystemUI/res/layout/privacy_dialog.xml index ee4530cb4377..9368a6a0b7da 100644 --- a/packages/SystemUI/res/layout/privacy_dialog.xml +++ b/packages/SystemUI/res/layout/privacy_dialog.xml @@ -22,10 +22,9 @@ android:layout_height="wrap_content" android:layout_marginStart="@dimen/ongoing_appops_dialog_side_margins" android:layout_marginEnd="@dimen/ongoing_appops_dialog_side_margins" - android:layout_marginTop="8dp" android:orientation="vertical" android:paddingBottom="8dp" - android:paddingTop="12dp" + android:paddingTop="8dp" android:paddingHorizontal="@dimen/ongoing_appops_dialog_side_padding" android:background="@drawable/qs_dialog_bg" /> diff --git a/packages/SystemUI/res/layout/qs_user_detail.xml b/packages/SystemUI/res/layout/qs_user_detail.xml index 91d3a53556a7..1aec296f4f5c 100644 --- a/packages/SystemUI/res/layout/qs_user_detail.xml +++ b/packages/SystemUI/res/layout/qs_user_detail.xml @@ -22,6 +22,6 @@ xmlns:sysui="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" - sysui:verticalSpacing="4dp" + sysui:verticalSpacing="20dp" sysui:horizontalSpacing="4dp" style="@style/UserDetailView" />
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/qs_user_detail_item.xml b/packages/SystemUI/res/layout/qs_user_detail_item.xml index cc6c5d343502..91b11fcc3c26 100644 --- a/packages/SystemUI/res/layout/qs_user_detail_item.xml +++ b/packages/SystemUI/res/layout/qs_user_detail_item.xml @@ -24,8 +24,6 @@ android:layout_height="wrap_content" android:orientation="vertical" android:gravity="top|center_horizontal" - android:paddingTop="16dp" - android:minHeight="112dp" android:clipChildren="false" android:clipToPadding="false" android:focusable="true" diff --git a/packages/SystemUI/res/layout/qs_user_dialog_content.xml b/packages/SystemUI/res/layout/qs_user_dialog_content.xml index 9495ee6f3139..355df2c4448a 100644 --- a/packages/SystemUI/res/layout/qs_user_dialog_content.xml +++ b/packages/SystemUI/res/layout/qs_user_dialog_content.xml @@ -15,75 +15,19 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> - -<androidx.constraintlayout.widget.ConstraintLayout +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:sysui="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" - android:padding="24dp" - android:layout_marginStart="16dp" - android:layout_marginEnd="16dp" -> - <TextView - android:id="@+id/title" - android:layout_height="wrap_content" - android:layout_width="0dp" - android:textAlignment="center" - android:text="@string/qs_user_switch_dialog_title" - android:textAppearance="@style/TextAppearance.QSDialog.Title" - android:layout_marginBottom="32dp" - sysui:layout_constraintTop_toTopOf="parent" - sysui:layout_constraintStart_toStartOf="parent" - sysui:layout_constraintEnd_toEndOf="parent" - sysui:layout_constraintBottom_toTopOf="@id/grid" - /> - + > <com.android.systemui.qs.PseudoGridView - android:id="@+id/grid" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginBottom="28dp" - sysui:verticalSpacing="4dp" - sysui:horizontalSpacing="4dp" - sysui:fixedChildWidth="80dp" - sysui:layout_constraintTop_toBottomOf="@id/title" - sysui:layout_constraintStart_toStartOf="parent" - sysui:layout_constraintEnd_toEndOf="parent" - sysui:layout_constraintBottom_toTopOf="@id/barrier" - /> - - <androidx.constraintlayout.widget.Barrier - android:id="@+id/barrier" - android:layout_height="wrap_content" - android:layout_width="wrap_content" - sysui:barrierDirection="top" - sysui:constraint_referenced_ids="settings,done" + android:id="@+id/grid" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + sysui:verticalSpacing="20dp" + sysui:horizontalSpacing="4dp" + sysui:fixedChildWidth="80dp" /> - - <Button - android:id="@+id/settings" - android:layout_width="wrap_content" - android:layout_height="48dp" - android:text="@string/quick_settings_more_user_settings" - sysui:layout_constraintTop_toBottomOf="@id/barrier" - sysui:layout_constraintBottom_toBottomOf="parent" - sysui:layout_constraintStart_toStartOf="parent" - sysui:layout_constraintEnd_toStartOf="@id/done" - sysui:layout_constraintHorizontal_chainStyle="spread_inside" - style="@style/Widget.QSDialog.Button.BorderButton" - /> - - <Button - android:id="@+id/done" - android:layout_width="wrap_content" - android:layout_height="48dp" - android:text="@string/quick_settings_done" - sysui:layout_constraintTop_toBottomOf="@id/barrier" - sysui:layout_constraintBottom_toBottomOf="parent" - sysui:layout_constraintStart_toEndOf="@id/settings" - sysui:layout_constraintEnd_toEndOf="parent" - style="@style/Widget.QSDialog.Button" - /> - -</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file +</FrameLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/values-night/styles.xml b/packages/SystemUI/res/values-night/styles.xml index cb34218fd2fb..cb963e6ffc89 100644 --- a/packages/SystemUI/res/values-night/styles.xml +++ b/packages/SystemUI/res/values-night/styles.xml @@ -16,9 +16,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android"> - <style name="Theme.SystemUI.Dialog" parent="@android:style/Theme.DeviceDefault.Dialog"> - <item name="android:buttonCornerRadius">28dp</item> - </style> + <style name="Theme.SystemUI.DayNightDialog" parent="@android:style/Theme.DeviceDefault.Dialog"/> <style name="Theme.SystemUI.Dialog.Alert" parent="@*android:style/Theme.DeviceDefault.Dialog.Alert" /> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index e00b9410a8a7..475f70fa9fdc 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -595,6 +595,17 @@ 280 </integer> + <!-- Haptic feedback intensity for ticks used for the udfps dwell time --> + <item name="config_udfpsTickIntensity" translatable="false" format="float" + type="dimen">.5</item> + + <!-- Haptic feedback delay between ticks used for udfps dwell time --> + <integer name="config_udfpsTickDelay" translatable="false">25</integer> + + <!-- Haptic feedback tick type - if true, uses VibrationEffect.Composition.PRIMITIVE_LOW_TICK + else uses VibrationEffect.Composition.PRIMITIVE_TICK --> + <bool name="config_udfpsUseLowTick">true</bool> + <!-- package name of a built-in camera app to use to restrict implicit intent resolution when the double-press power gesture is used. Ignored if empty. --> <string translatable="false" name="config_cameraGesturePackage"></string> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 2afbe8c648be..a2fd669c69fd 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1275,10 +1275,19 @@ <dimen name="drag_and_drop_icon_size">70dp</dimen> - <dimen name="qs_dialog_button_horizontal_padding">16dp</dimen> - <dimen name="qs_dialog_button_vertical_padding">8dp</dimen> + <!-- Dimensions for unified SystemUI dialogs styling. Used by Theme.SystemUI.Dialog and + alert_dialog_systemui.xml + --> + <dimen name="dialog_button_horizontal_padding">16dp</dimen> + <dimen name="dialog_button_vertical_padding">8dp</dimen> <!-- The button will be 48dp tall, but the background needs to be 36dp tall --> - <dimen name="qs_dialog_button_vertical_inset">6dp</dimen> + <dimen name="dialog_button_vertical_inset">6dp</dimen> + <dimen name="dialog_top_padding">24dp</dimen> + <dimen name="dialog_bottom_padding">18dp</dimen> + <dimen name="dialog_side_padding">24dp</dimen> + <dimen name="dialog_button_bar_top_padding">32dp</dimen> + + <!-- ************************************************************************* --> <dimen name="keyguard_unfold_translation_x">16dp</dimen> </resources> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 2a5aebe85143..3c7b53a8e6db 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -14,8 +14,8 @@ limitations under the License. --> -<resources xmlns:android="http://schemas.android.com/apk/res/android"> - <!-- NOTE: Adding the androidprv: namespace to this file will break the studio build. --> +<resources xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> <!-- HybridNotification themes and styles --> @@ -351,11 +351,19 @@ <item name="android:windowIsFloating">true</item> </style> - <style name="Theme.SystemUI.Dialog" parent="@android:style/Theme.DeviceDefault.Light.Dialog"> + <style name="Theme.SystemUI.DayNightDialog" parent="@android:style/Theme.DeviceDefault.Light.Dialog"/> + + <style name="Theme.SystemUI.Dialog" parent="@style/Theme.SystemUI.DayNightDialog"> <item name="android:buttonCornerRadius">28dp</item> - <item name="android:buttonBarPositiveButtonStyle">@style/Widget.QSDialog.Button</item> - <item name="android:buttonBarNegativeButtonStyle">@style/Widget.QSDialog.Button.BorderButton</item> - <item name="android:buttonBarNeutralButtonStyle">@style/Widget.QSDialog.Button.BorderButton</item> + <item name="android:buttonBarPositiveButtonStyle">@style/Widget.Dialog.Button</item> + <item name="android:buttonBarNegativeButtonStyle">@style/Widget.Dialog.Button.BorderButton</item> + <item name="android:buttonBarNeutralButtonStyle">@style/Widget.Dialog.Button.BorderButton</item> + <item name="android:colorBackground">?androidprv:attr/colorSurface</item> + <item name="android:alertDialogStyle">@style/AlertDialogStyle</item> + </style> + + <style name="AlertDialogStyle" parent="@androidprv:style/AlertDialog.DeviceDefault"> + <item name="android:layout">@layout/alert_dialog_systemui</item> </style> <style name="Theme.SystemUI.Dialog.Alert" parent="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert" /> @@ -853,24 +861,37 @@ <item name="actionDividerHeight">32dp</item> </style> - <style name="TextAppearance.QSDialog.Title" parent="Theme.SystemUI.Dialog"> + <style name="TextAppearance.Dialog.Title" parent="@android:style/TextAppearance.DeviceDefault.Large"> <item name="android:textColor">?android:attr/textColorPrimary</item> <item name="android:textSize">24sp</item> <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item> <item name="android:lineHeight">32sp</item> + <item name="android:gravity">center</item> + <item name="android:textAlignment">center</item> </style> - <style name="Widget.QSDialog.Button" parent = "Theme.SystemUI.Dialog"> + <style name="TextAppearance.Dialog.Body" parent="@android:style/TextAppearance.DeviceDefault.Medium"> + <item name="android:textColor">?android:attr/textColorSecondary</item> + <item name="android:textSize">14sp</item> + <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item> + <item name="android:lineHeight">20sp</item> + </style> + + <style name="TextAppearance.Dialog.Body.Message"> + <item name="android:gravity">center</item> + <item name="android:textAlignment">center</item> + </style> + + <style name="Widget.Dialog.Button" parent = "Theme.SystemUI.Dialog"> <item name="android:background">@drawable/qs_dialog_btn_filled</item> - <item name="android:textColor">@color/prv_text_color_on_accent</item> + <item name="android:textColor">?androidprv:attr/textColorOnAccent</item> <item name="android:textSize">14sp</item> <item name="android:lineHeight">20sp</item> - <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item> + <item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item> <item name="android:stateListAnimator">@null</item> - <item name="android:layout_marginHorizontal">4dp</item> </style> - <style name="Widget.QSDialog.Button.BorderButton"> + <style name="Widget.Dialog.Button.BorderButton"> <item name="android:background">@drawable/qs_dialog_btn_outline</item> <item name="android:textColor">?android:attr/textColorPrimary</item> </style> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java index 3128ffdbc67b..675dc9b533fb 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java @@ -28,6 +28,7 @@ import android.os.Parcel; import android.os.Parcelable; import android.view.ViewDebug; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import java.io.PrintWriter; @@ -50,6 +51,7 @@ public class Task { @ViewDebug.ExportedProperty(category="recents") public int windowingMode; @ViewDebug.ExportedProperty(category="recents") + @NonNull public final Intent baseIntent; @ViewDebug.ExportedProperty(category="recents") public final int userId; @@ -83,7 +85,7 @@ public class Task { updateHashCode(); } - public TaskKey(int id, int windowingMode, Intent intent, + public TaskKey(int id, int windowingMode, @NonNull Intent intent, ComponentName sourceComponent, int userId, long lastActiveTime) { this.id = id; this.windowingMode = windowingMode; @@ -95,7 +97,7 @@ public class Task { updateHashCode(); } - public TaskKey(int id, int windowingMode, Intent intent, + public TaskKey(int id, int windowingMode, @NonNull Intent intent, ComponentName sourceComponent, int userId, long lastActiveTime, int displayId) { this.id = id; this.windowingMode = windowingMode; diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index 9ce0e94cca18..09f2af4a86da 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -163,7 +163,10 @@ public class UdfpsController implements DozeReceiver { private boolean mOnFingerDown; private boolean mAttemptedToDismissKeyguard; private Set<Callback> mCallbacks = new HashSet<>(); - private final VibrationEffect mLowTick; + + // by default, use low tick + private int mPrimitiveTick = VibrationEffect.Composition.PRIMITIVE_LOW_TICK; + private final VibrationEffect mTick; @VisibleForTesting public static final AudioAttributes VIBRATION_SONIFICATION_ATTRIBUTES = @@ -572,7 +575,7 @@ public class UdfpsController implements DozeReceiver { mConfigurationController = configurationController; mSystemClock = systemClock; mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; - mLowTick = lowTick(); + mTick = lowTick(); mSensorProps = findFirstUdfps(); // At least one UDFPS sensor exists @@ -608,22 +611,31 @@ public class UdfpsController implements DozeReceiver { } private VibrationEffect lowTick() { + boolean useLowTickDefault = mContext.getResources() + .getBoolean(R.bool.config_udfpsUseLowTick); + if (Settings.Global.getFloat( + mContext.getContentResolver(), + "tick-low", useLowTickDefault ? 1 : 0) == 0) { + mPrimitiveTick = VibrationEffect.Composition.PRIMITIVE_TICK; + } float tickIntensity = Settings.Global.getFloat( - mContext.getContentResolver(), "low-tick-intensity", .5f); - VibrationEffect.Composition composition = VibrationEffect.startComposition(); - composition.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, - tickIntensity, 0); + mContext.getContentResolver(), + "tick-intensity", + mContext.getResources().getFloat(R.dimen.config_udfpsTickIntensity)); int tickDelay = Settings.Global.getInt( - mContext.getContentResolver(), "low-tick-delay", 25); + mContext.getContentResolver(), + "tick-delay", + mContext.getResources().getInteger(R.integer.config_udfpsTickDelay)); + + VibrationEffect.Composition composition = VibrationEffect.startComposition(); + composition.addPrimitive(mPrimitiveTick, tickIntensity, 0); int primitives = 1000 / tickDelay; float[] rampUp = new float[]{.48f, .58f, .69f, .83f}; for (int i = 0; i < rampUp.length; i++) { - composition.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, - tickIntensity * rampUp[i], tickDelay); + composition.addPrimitive(mPrimitiveTick, tickIntensity * rampUp[i], tickDelay); } for (int i = rampUp.length; i < primitives; i++) { - composition.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, - tickIntensity, tickDelay); + composition.addPrimitive(mPrimitiveTick, tickIntensity, tickDelay); } return composition.compose(); } @@ -637,7 +649,7 @@ public class UdfpsController implements DozeReceiver { mVibrator.vibrate( Process.myUid(), mContext.getOpPackageName(), - mLowTick, + mTick, "udfps-onStart-tick", VIBRATION_SONIFICATION_ATTRIBUTES); } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt index 47ef5e4c62fd..d54b1514abf7 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt @@ -400,7 +400,7 @@ class MediaCarouselController @Inject constructor( } updatePageIndicator() mediaCarouselScrollHandler.onPlayersChanged() - mediaCarousel.requiresRemeasuring = true + mediaFrame.requiresRemeasuring = true // Check postcondition: mediaContent should have the same number of children as there are // elements in mediaPlayers. if (MediaPlayerData.players().size != mediaContent.childCount) { @@ -439,7 +439,7 @@ class MediaCarouselController @Inject constructor( updatePlayerToState(newRecs, noAnimation = true) reorderAllPlayers(curVisibleMediaKey) updatePageIndicator() - mediaCarousel.requiresRemeasuring = true + mediaFrame.requiresRemeasuring = true // Check postcondition: mediaContent should have the same number of children as there are // elements in mediaPlayers. if (MediaPlayerData.players().size != mediaContent.childCount) { diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java deleted file mode 100644 index 52103d3bd739..000000000000 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.navigationbar; - -import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU; - -import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE; -import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE; - -import android.content.ContentResolver; -import android.content.Context; -import android.database.ContentObserver; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.os.UserHandle; -import android.provider.Settings; -import android.view.accessibility.AccessibilityManager; - -import androidx.annotation.NonNull; - -import com.android.systemui.Dumpable; -import com.android.systemui.accessibility.AccessibilityButtonModeObserver; -import com.android.systemui.assist.AssistManager; -import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.dump.DumpManager; -import com.android.systemui.recents.OverviewProxyService; -import com.android.systemui.settings.UserTracker; -import com.android.systemui.shared.system.QuickStepContract; -import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; - -import javax.inject.Inject; - -import dagger.Lazy; - -/** - * Extracts shared elements between navbar and taskbar delegate to de-dupe logic and help them - * experience the joys of friendship. - * The events are then passed through - * - * Currently consolidates - * * A11y - * * Assistant - */ -@SysUISingleton -public final class NavBarHelper implements - AccessibilityButtonModeObserver.ModeChangedListener, - OverviewProxyService.OverviewProxyListener, NavigationModeController.ModeChangedListener, - Dumpable { - private final AccessibilityManager mAccessibilityManager; - private final Lazy<AssistManager> mAssistManagerLazy; - private final UserTracker mUserTracker; - private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver; - private final List<NavbarTaskbarStateUpdater> mA11yEventListeners = new ArrayList<>(); - private Context mContext; - private ContentResolver mContentResolver; - private boolean mAssistantAvailable; - private boolean mLongPressHomeEnabled; - private boolean mAssistantTouchGestureEnabled; - private int mNavBarMode; - - private final ContentObserver mAssistContentObserver = new ContentObserver( - new Handler(Looper.getMainLooper())) { - @Override - public void onChange(boolean selfChange, Uri uri) { - updateAssitantAvailability(); - } - }; - - @Inject - public NavBarHelper(AccessibilityManager accessibilityManager, - AccessibilityManagerWrapper accessibilityManagerWrapper, - AccessibilityButtonModeObserver accessibilityButtonModeObserver, - OverviewProxyService overviewProxyService, - Lazy<AssistManager> assistManagerLazy, - NavigationModeController navigationModeController, - UserTracker userTracker, - DumpManager dumpManager) { - mAccessibilityManager = accessibilityManager; - mAssistManagerLazy = assistManagerLazy; - mUserTracker = userTracker; - accessibilityManagerWrapper.addCallback( - accessibilityManager1 -> NavBarHelper.this.dispatchA11yEventUpdate()); - mAccessibilityButtonModeObserver = accessibilityButtonModeObserver; - - mAccessibilityButtonModeObserver.addListener(this); - mNavBarMode = navigationModeController.addListener(this); - overviewProxyService.addCallback(this); - dumpManager.registerDumpable(this); - } - - public void init(Context context) { - mContext = context; - mContentResolver = mContext.getContentResolver(); - mContentResolver.registerContentObserver( - Settings.Secure.getUriFor(Settings.Secure.ASSISTANT), - false /* notifyForDescendants */, mAssistContentObserver, UserHandle.USER_ALL); - mContentResolver.registerContentObserver( - Settings.Secure.getUriFor(Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED), - false, mAssistContentObserver, UserHandle.USER_ALL); - mContentResolver.registerContentObserver( - Settings.Secure.getUriFor(Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED), - false, mAssistContentObserver, UserHandle.USER_ALL); - updateAssitantAvailability(); - } - - public void destroy() { - mContentResolver.unregisterContentObserver(mAssistContentObserver); - } - - /** - * @param listener Will immediately get callbacks based on current state - */ - public void registerNavTaskStateUpdater(NavbarTaskbarStateUpdater listener) { - mA11yEventListeners.add(listener); - listener.updateAccessibilityServicesState(); - listener.updateAssistantAvailable(mAssistantAvailable); - } - - public void removeNavTaskStateUpdater(NavbarTaskbarStateUpdater listener) { - mA11yEventListeners.remove(listener); - } - - private void dispatchA11yEventUpdate() { - for (NavbarTaskbarStateUpdater listener : mA11yEventListeners) { - listener.updateAccessibilityServicesState(); - } - } - - private void dispatchAssistantEventUpdate(boolean assistantAvailable) { - for (NavbarTaskbarStateUpdater listener : mA11yEventListeners) { - listener.updateAssistantAvailable(assistantAvailable); - } - } - - @Override - public void onAccessibilityButtonModeChanged(int mode) { - dispatchA11yEventUpdate(); - } - - /** - * See {@link QuickStepContract#SYSUI_STATE_A11Y_BUTTON_CLICKABLE} and - * {@link QuickStepContract#SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE} - * - * @return the a11y button clickable and long_clickable states, or 0 if there is no - * a11y button in the navbar - */ - public int getA11yButtonState() { - // AccessibilityManagerService resolves services for the current user since the local - // AccessibilityManager is created from a Context with the INTERACT_ACROSS_USERS permission - final List<String> a11yButtonTargets = - mAccessibilityManager.getAccessibilityShortcutTargets( - AccessibilityManager.ACCESSIBILITY_BUTTON); - final int requestingServices = a11yButtonTargets.size(); - - // If accessibility button is floating menu mode, click and long click state should be - // disabled. - if (mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode() - == ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU) { - return 0; - } - - return (requestingServices >= 1 ? SYSUI_STATE_A11Y_BUTTON_CLICKABLE : 0) - | (requestingServices >= 2 ? SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE : 0); - } - - @Override - public void onConnectionChanged(boolean isConnected) { - if (isConnected) { - updateAssitantAvailability(); - } - } - - private void updateAssitantAvailability() { - boolean assistantAvailableForUser = mAssistManagerLazy.get() - .getAssistInfoForUser(UserHandle.USER_CURRENT) != null; - boolean longPressDefault = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_assistLongPressHomeEnabledDefault); - mLongPressHomeEnabled = Settings.Secure.getIntForUser(mContentResolver, - Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, longPressDefault ? 1 : 0, - mUserTracker.getUserId()) != 0; - boolean gestureDefault = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_assistTouchGestureEnabledDefault); - mAssistantTouchGestureEnabled = Settings.Secure.getIntForUser(mContentResolver, - Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED, gestureDefault ? 1 : 0, - mUserTracker.getUserId()) != 0; - - mAssistantAvailable = assistantAvailableForUser - && mAssistantTouchGestureEnabled - && QuickStepContract.isGesturalMode(mNavBarMode); - dispatchAssistantEventUpdate(mAssistantAvailable); - } - - public boolean getLongPressHomeEnabled() { - return mLongPressHomeEnabled; - } - - @Override - public void startAssistant(Bundle bundle) { - mAssistManagerLazy.get().startAssist(bundle); - } - - @Override - public void onNavigationModeChanged(int mode) { - mNavBarMode = mode; - updateAssitantAvailability(); - } - - /** - * Callbacks will get fired once immediately after registering via - * {@link #registerNavTaskStateUpdater(NavbarTaskbarStateUpdater)} - */ - public interface NavbarTaskbarStateUpdater { - void updateAccessibilityServicesState(); - void updateAssistantAvailable(boolean available); - } - - @Override - public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) { - pw.println("NavbarTaskbarFriendster"); - pw.println(" longPressHomeEnabled=" + mLongPressHomeEnabled); - pw.println(" mAssistantTouchGestureEnabled=" + mAssistantTouchGestureEnabled); - pw.println(" mAssistantAvailable=" + mAssistantAvailable); - pw.println(" mNavBarMode=" + mNavBarMode); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java index 5141f25e4933..bc023cc892a6 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java @@ -68,18 +68,22 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; +import android.database.ContentObserver; import android.graphics.Insets; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.RectF; import android.inputmethodservice.InputMethodService; +import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; +import android.os.Looper; import android.os.RemoteException; import android.os.UserHandle; import android.provider.DeviceConfig; +import android.provider.Settings; import android.telecom.TelecomManager; import android.text.TextUtils; import android.util.Log; @@ -196,7 +200,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, private final Handler mHandler; private final NavigationBarOverlayController mNavbarOverlayController; private final UiEventLogger mUiEventLogger; - private final NavBarHelper mNavBarHelper; + private final NavigationBarA11yHelper mNavigationBarA11yHelper; + private final UserTracker mUserTracker; private final NotificationShadeDepthController mNotificationShadeDepthController; private Bundle mSavedState; @@ -208,7 +213,9 @@ public class NavigationBar implements View.OnAttachStateChangeListener, private int mNavigationIconHints = 0; private @TransitionMode int mNavigationBarMode; private ContentResolver mContentResolver; + private boolean mAssistantAvailable; private boolean mLongPressHomeEnabled; + private boolean mAssistantTouchGestureEnabled; private int mDisabledFlags1; private int mDisabledFlags2; @@ -302,31 +309,16 @@ public class NavigationBar implements View.OnAttachStateChangeListener, } }; - private final NavBarHelper.NavbarTaskbarStateUpdater mNavbarTaskbarStateUpdater = - new NavBarHelper.NavbarTaskbarStateUpdater() { - @Override - public void updateAccessibilityServicesState() { - updateAcessibilityStateFlags(); - } - - @Override - public void updateAssistantAvailable(boolean available) { - // TODO(b/198002034): Content observers currently can still be called back after - // being unregistered, and in this case we can ignore the change if the nav bar - // has been destroyed already - if (mNavigationBarView == null) { - return; - } - mLongPressHomeEnabled = mNavBarHelper.getLongPressHomeEnabled(); - updateAssistantEntrypoints(available); - } - }; - private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() { @Override public void onConnectionChanged(boolean isConnected) { mNavigationBarView.updateStates(); updateScreenPinningGestures(); + + // Send the assistant availability upon connection + if (isConnected) { + updateAssistantEntrypoints(); + } } @Override @@ -429,6 +421,20 @@ public class NavigationBar implements View.OnAttachStateChangeListener, } }; + private final ContentObserver mAssistContentObserver = new ContentObserver( + new Handler(Looper.getMainLooper())) { + @Override + public void onChange(boolean selfChange, Uri uri) { + // TODO(b/198002034): Content observers currently can still be called back after being + // unregistered, and in this case we can ignore the change if the nav bar has been + // destroyed already + if (mNavigationBarView == null) { + return; + } + updateAssistantEntrypoints(); + } + }; + private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener = new DeviceConfig.OnPropertiesChangedListener() { @Override @@ -498,7 +504,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, @Main Handler mainHandler, NavigationBarOverlayController navbarOverlayController, UiEventLogger uiEventLogger, - NavBarHelper navBarHelper, + NavigationBarA11yHelper navigationBarA11yHelper, UserTracker userTracker, LightBarController mainLightBarController, LightBarController.Factory lightBarControllerFactory, @@ -529,7 +535,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mHandler = mainHandler; mNavbarOverlayController = navbarOverlayController; mUiEventLogger = uiEventLogger; - mNavBarHelper = navBarHelper; + mNavigationBarA11yHelper = navigationBarA11yHelper; + mUserTracker = userTracker; mNotificationShadeDepthController = notificationShadeDepthController; mMainLightBarController = mainLightBarController; mLightBarControllerFactory = lightBarControllerFactory; @@ -561,9 +568,18 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mIsOnDefaultDisplay = mDisplayId == DEFAULT_DISPLAY; mCommandQueue.addCallback(this); - mLongPressHomeEnabled = mNavBarHelper.getLongPressHomeEnabled(); + mAssistantAvailable = mAssistManagerLazy.get() + .getAssistInfoForUser(UserHandle.USER_CURRENT) != null; mContentResolver = mContext.getContentResolver(); - mNavBarHelper.init(mContext); + mContentResolver.registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.ASSISTANT), + false /* notifyForDescendants */, mAssistContentObserver, UserHandle.USER_ALL); + mContentResolver.registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED), + false, mAssistContentObserver, UserHandle.USER_ALL); + mContentResolver.registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED), + false, mAssistContentObserver, UserHandle.USER_ALL); mAllowForceNavBarHandleOpaque = mContext.getResources().getBoolean( R.bool.allow_force_nav_bar_handle_opaque); mForceNavBarHandleOpaque = DeviceConfig.getBoolean( @@ -577,6 +593,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, )).filter(duration -> duration != 0); DeviceConfig.addOnPropertiesChangedListener( DeviceConfig.NAMESPACE_SYSTEMUI, mHandler::post, mOnPropertiesChangedListener); + updateAssistantEntrypoints(); if (savedState != null) { mDisabledFlags1 = savedState.getInt(EXTRA_DISABLE_STATE, 0); @@ -603,8 +620,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mWindowManager.removeViewImmediate(mNavigationBarView.getRootView()); mNavigationModeController.removeListener(this); - mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - mNavBarHelper.destroy(); + mNavigationBarA11yHelper.removeA11yEventListener(mAccessibilityListener); + mContentResolver.unregisterContentObserver(mAssistContentObserver); mDeviceProvisionedController.removeCallback(mUserSetupListener); mNotificationShadeDepthController.removeListener(mDepthListener); @@ -626,7 +643,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mNavigationBarView.setWindowVisible(isNavBarWindowVisible()); mNavigationBarView.setBehavior(mBehavior); - mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); + mNavigationBarA11yHelper.registerA11yEventListener(mAccessibilityListener); mSplitScreenOptional.ifPresent(mNavigationBarView::registerDockedListener); mPipOptional.ifPresent(mNavigationBarView::registerPipExclusionBoundsChangeListener); @@ -699,7 +716,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mHandler.removeCallbacks(mAutoDim); mHandler.removeCallbacks(mOnVariableDurationHomeLongClick); mHandler.removeCallbacks(mEnableLayoutTransitions); - mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater); + mNavigationBarA11yHelper.removeA11yEventListener(mAccessibilityListener); mFrame = null; mNavigationBarView = null; mOrientationHandle = null; @@ -868,6 +885,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, pw.println(" mCurrentRotation=" + mCurrentRotation); pw.println(" mHomeButtonLongPressDurationMs=" + mHomeButtonLongPressDurationMs); pw.println(" mLongPressHomeEnabled=" + mLongPressHomeEnabled); + pw.println(" mAssistantTouchGestureEnabled=" + mAssistantTouchGestureEnabled); pw.println(" mNavigationBarWindowState=" + windowStateToString(mNavigationBarWindowState)); pw.println(" mNavigationBarMode=" @@ -1147,7 +1165,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, ButtonDispatcher accessibilityButton = mNavigationBarView.getAccessibilityButton(); accessibilityButton.setOnClickListener(this::onAccessibilityClick); accessibilityButton.setOnLongClickListener(this::onAccessibilityLongClick); - updateAcessibilityStateFlags(); + updateAccessibilityServicesState(); ButtonDispatcher imeSwitcherButton = mNavigationBarView.getImeSwitchButton(); imeSwitcherButton.setOnClickListener(this::onImeSwitcherClick); @@ -1372,8 +1390,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, return true; } - void updateAcessibilityStateFlags() { - int a11yFlags = mNavBarHelper.getA11yButtonState(); + void updateAccessibilityServicesState() { + int a11yFlags = mNavigationBarA11yHelper.getA11yButtonState(); if (mNavigationBarView != null) { boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0; @@ -1385,7 +1403,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, public void updateSystemUiStateFlags(int a11yFlags) { if (a11yFlags < 0) { - a11yFlags = mNavBarHelper.getA11yButtonState(); + a11yFlags = mNavigationBarA11yHelper.getA11yButtonState(); } boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0; boolean longClickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0; @@ -1412,10 +1430,24 @@ public class NavigationBar implements View.OnAttachStateChangeListener, } } - private void updateAssistantEntrypoints(boolean assistantAvailable) { + private void updateAssistantEntrypoints() { + mAssistantAvailable = mAssistManagerLazy.get() + .getAssistInfoForUser(UserHandle.USER_CURRENT) != null; + boolean longPressDefault = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_assistLongPressHomeEnabledDefault); + mLongPressHomeEnabled = Settings.Secure.getIntForUser(mContentResolver, + Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, longPressDefault ? 1 : 0, + mUserTracker.getUserId()) != 0; + boolean gestureDefault = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_assistTouchGestureEnabledDefault); + mAssistantTouchGestureEnabled = Settings.Secure.getIntForUser(mContentResolver, + Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED, gestureDefault ? 1 : 0, + mUserTracker.getUserId()) != 0; if (mOverviewProxyService.getProxy() != null) { try { - mOverviewProxyService.getProxy().onAssistantAvailable(assistantAvailable); + mOverviewProxyService.getProxy().onAssistantAvailable(mAssistantAvailable + && mAssistantTouchGestureEnabled + && QuickStepContract.isGesturalMode(mNavBarMode)); } catch (RemoteException e) { Log.w(TAG, "Unable to send assistant availability data to launcher"); } @@ -1486,6 +1518,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, @Override public void onNavigationModeChanged(int mode) { mNavBarMode = mode; + // update assistant entry points on system navigation radio button click + updateAssistantEntrypoints(); if (!QuickStepContract.isGesturalMode(mode)) { // Reset the override alpha @@ -1524,6 +1558,9 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mNavigationBarView.getBarTransitions().finishAnimations(); } + private final NavigationBarA11yHelper.NavA11yEventListener mAccessibilityListener = + this::updateAccessibilityServicesState; + private WindowManager.LayoutParams getBarLayoutParams(int rotation) { WindowManager.LayoutParams lp = getBarLayoutParamsForRotation(rotation); lp.paramsForRotation = new WindowManager.LayoutParams[4]; @@ -1631,7 +1668,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, } if (Intent.ACTION_USER_SWITCHED.equals(action)) { // The accessibility settings may be different for the new user - updateAcessibilityStateFlags(); + updateAccessibilityServicesState(); } } }; @@ -1667,7 +1704,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, private final Handler mMainHandler; private final NavigationBarOverlayController mNavbarOverlayController; private final UiEventLogger mUiEventLogger; - private final NavBarHelper mNavBarHelper; + private final NavigationBarA11yHelper mNavigationBarA11yHelper; private final UserTracker mUserTracker; private final LightBarController mMainLightBarController; private final LightBarController.Factory mLightBarControllerFactory; @@ -1700,7 +1737,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, @Main Handler mainHandler, NavigationBarOverlayController navbarOverlayController, UiEventLogger uiEventLogger, - NavBarHelper navBarHelper, + NavigationBarA11yHelper navigationBarA11yHelper, UserTracker userTracker, LightBarController mainLightBarController, LightBarController.Factory lightBarControllerFactory, @@ -1730,7 +1767,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mMainHandler = mainHandler; mNavbarOverlayController = navbarOverlayController; mUiEventLogger = uiEventLogger; - mNavBarHelper = navBarHelper; + mNavigationBarA11yHelper = navigationBarA11yHelper; mUserTracker = userTracker; mMainLightBarController = mainLightBarController; mLightBarControllerFactory = lightBarControllerFactory; @@ -1751,7 +1788,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, mSplitScreenOptional, mRecentsOptional, mStatusBarOptionalLazy, mShadeController, mNotificationRemoteInputManager, mNotificationShadeDepthController, mSystemActions, mMainHandler, - mNavbarOverlayController, mUiEventLogger, mNavBarHelper, + mNavbarOverlayController, mUiEventLogger, mNavigationBarA11yHelper, mUserTracker, mMainLightBarController, mLightBarControllerFactory, mMainAutoHideController, mAutoHideControllerFactory, mTelecomManagerOptional, mInputMethodManager); diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarA11yHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarA11yHelper.java new file mode 100644 index 000000000000..13e6d8b410d6 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarA11yHelper.java @@ -0,0 +1,90 @@ +package com.android.systemui.navigationbar; + +import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU; + +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE; +import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE; + +import android.view.accessibility.AccessibilityManager; + +import com.android.systemui.accessibility.AccessibilityButtonModeObserver; +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.shared.system.QuickStepContract; +import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; + +import java.util.ArrayList; +import java.util.List; + +import javax.inject.Inject; + +/** + * Extracts shared elements of a11y necessary between navbar and taskbar delegate + */ +@SysUISingleton +public final class NavigationBarA11yHelper implements + AccessibilityButtonModeObserver.ModeChangedListener { + private final AccessibilityManager mAccessibilityManager; + private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver; + private final List<NavA11yEventListener> mA11yEventListeners = new ArrayList<>(); + + @Inject + public NavigationBarA11yHelper(AccessibilityManager accessibilityManager, + AccessibilityManagerWrapper accessibilityManagerWrapper, + AccessibilityButtonModeObserver accessibilityButtonModeObserver) { + mAccessibilityManager = accessibilityManager; + accessibilityManagerWrapper.addCallback( + accessibilityManager1 -> NavigationBarA11yHelper.this.dispatchEventUpdate()); + mAccessibilityButtonModeObserver = accessibilityButtonModeObserver; + + mAccessibilityButtonModeObserver.addListener(this); + } + + public void registerA11yEventListener(NavA11yEventListener listener) { + mA11yEventListeners.add(listener); + } + + public void removeA11yEventListener(NavA11yEventListener listener) { + mA11yEventListeners.remove(listener); + } + + private void dispatchEventUpdate() { + for (NavA11yEventListener listener : mA11yEventListeners) { + listener.updateAccessibilityServicesState(); + } + } + + @Override + public void onAccessibilityButtonModeChanged(int mode) { + dispatchEventUpdate(); + } + + /** + * See {@link QuickStepContract#SYSUI_STATE_A11Y_BUTTON_CLICKABLE} and + * {@link QuickStepContract#SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE} + * + * @return the a11y button clickable and long_clickable states, or 0 if there is no + * a11y button in the navbar + */ + public int getA11yButtonState() { + // AccessibilityManagerService resolves services for the current user since the local + // AccessibilityManager is created from a Context with the INTERACT_ACROSS_USERS permission + final List<String> a11yButtonTargets = + mAccessibilityManager.getAccessibilityShortcutTargets( + AccessibilityManager.ACCESSIBILITY_BUTTON); + final int requestingServices = a11yButtonTargets.size(); + + // If accessibility button is floating menu mode, click and long click state should be + // disabled. + if (mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode() + == ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU) { + return 0; + } + + return (requestingServices >= 1 ? SYSUI_STATE_A11Y_BUTTON_CLICKABLE : 0) + | (requestingServices >= 2 ? SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE : 0); + } + + public interface NavA11yEventListener { + void updateAccessibilityServicesState(); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java index 0429c022234d..472f1f1245e1 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java @@ -101,7 +101,7 @@ public class NavigationBarController implements CommandQueue commandQueue, @Main Handler mainHandler, ConfigurationController configurationController, - NavBarHelper navBarHelper, + NavigationBarA11yHelper navigationBarA11yHelper, TaskbarDelegate taskbarDelegate, NavigationBar.Factory navigationBarFactory, DumpManager dumpManager, @@ -117,7 +117,7 @@ public class NavigationBarController implements mNavMode = navigationModeController.addListener(this); mTaskbarDelegate = taskbarDelegate; mTaskbarDelegate.setDependencies(commandQueue, overviewProxyService, - navBarHelper, navigationModeController, sysUiFlagsContainer, + navigationBarA11yHelper, navigationModeController, sysUiFlagsContainer, dumpManager, autoHideController, lightBarController); mIsTablet = isTablet(mContext); dumpManager.registerDumpable(this); diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java index 3d58a5a81251..089423fd7286 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java @@ -43,8 +43,6 @@ import android.content.res.Configuration; import android.hardware.display.DisplayManager; import android.inputmethodservice.InputMethodService; import android.os.IBinder; -import android.os.RemoteException; -import android.util.Log; import android.view.Display; import android.view.InsetsVisibilities; import android.view.View; @@ -78,13 +76,12 @@ import javax.inject.Singleton; public class TaskbarDelegate implements CommandQueue.Callbacks, OverviewProxyService.OverviewProxyListener, NavigationModeController.ModeChangedListener, ComponentCallbacks, Dumpable { - private static final String TAG = TaskbarDelegate.class.getSimpleName(); private final EdgeBackGestureHandler mEdgeBackGestureHandler; - private boolean mInitialized; + private CommandQueue mCommandQueue; private OverviewProxyService mOverviewProxyService; - private NavBarHelper mNavBarHelper; + private NavigationBarA11yHelper mNavigationBarA11yHelper; private NavigationModeController mNavigationModeController; private SysUiState mSysUiState; private AutoHideController mAutoHideController; @@ -92,18 +89,8 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, private LightBarTransitionsController mLightBarTransitionsController; private int mDisplayId; private int mNavigationIconHints; - private final NavBarHelper.NavbarTaskbarStateUpdater mNavbarTaskbarStateUpdater = - new NavBarHelper.NavbarTaskbarStateUpdater() { - @Override - public void updateAccessibilityServicesState() { - updateSysuiFlags(); - } - - @Override - public void updateAssistantAvailable(boolean available) { - updateAssistantAvailability(available); - } - }; + private final NavigationBarA11yHelper.NavA11yEventListener mNavA11yEventListener = + this::updateSysuiFlags; private int mDisabledFlags; private @WindowVisibleState int mTaskBarWindowState = WINDOW_STATE_SHOWING; private @Behavior int mBehavior; @@ -143,7 +130,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, public void setDependencies(CommandQueue commandQueue, OverviewProxyService overviewProxyService, - NavBarHelper navBarHelper, + NavigationBarA11yHelper navigationBarA11yHelper, NavigationModeController navigationModeController, SysUiState sysUiState, DumpManager dumpManager, AutoHideController autoHideController, @@ -151,7 +138,7 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, // TODO: adding this in the ctor results in a dagger dependency cycle :( mCommandQueue = commandQueue; mOverviewProxyService = overviewProxyService; - mNavBarHelper = navBarHelper; + mNavigationBarA11yHelper = navigationBarA11yHelper; mNavigationModeController = navigationModeController; mSysUiState = sysUiState; dumpManager.registerDumpable(this); @@ -183,16 +170,12 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, } public void init(int displayId) { - if (mInitialized) { - return; - } mDisplayId = displayId; mCommandQueue.addCallback(this); mOverviewProxyService.addCallback(this); mEdgeBackGestureHandler.onNavigationModeChanged( mNavigationModeController.addListener(this)); - mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - mNavBarHelper.init(mContext); + mNavigationBarA11yHelper.registerA11yEventListener(mNavA11yEventListener); mEdgeBackGestureHandler.onNavBarAttached(); // Initialize component callback Display display = mDisplayManager.getDisplay(displayId); @@ -202,31 +185,29 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, updateSysuiFlags(); mAutoHideController.setNavigationBar(mAutoHideUiElement); mLightBarController.setNavigationBar(mLightBarTransitionsController); - mInitialized = true; } public void destroy() { - if (!mInitialized) { - return; - } mCommandQueue.removeCallback(this); mOverviewProxyService.removeCallback(this); mNavigationModeController.removeListener(this); - mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - mNavBarHelper.destroy(); + mNavigationBarA11yHelper.removeA11yEventListener(mNavA11yEventListener); mEdgeBackGestureHandler.onNavBarDetached(); if (mWindowContext != null) { mWindowContext.unregisterComponentCallbacks(this); mWindowContext = null; } mAutoHideController.setNavigationBar(null); +//<<<<<<< HEAD mLightBarTransitionsController.destroy(mContext); mLightBarController.setNavigationBar(null); - mInitialized = false; +// mInitialized = false; +//======= +//>>>>>>> 2d145412fc44 (Revert "Extract assistant logic from NavigationBar to share with Taskbar") } private void updateSysuiFlags() { - int a11yFlags = mNavBarHelper.getA11yButtonState(); + int a11yFlags = mNavigationBarA11yHelper.getA11yButtonState(); boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0; boolean longClickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0; @@ -250,18 +231,6 @@ public class TaskbarDelegate implements CommandQueue.Callbacks, .commitUpdate(mDisplayId); } - private void updateAssistantAvailability(boolean assistantAvailable) { - if (mOverviewProxyService.getProxy() == null) { - return; - } - - try { - mOverviewProxyService.getProxy().onAssistantAvailable(assistantAvailable); - } catch (RemoteException e) { - Log.e(TAG, "onAssistantAvailable() failed, available: " + assistantAvailable, e); - } - } - @Override public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, boolean showImeSwitcher) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java b/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java index 2f189beb7780..768598af6885 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java @@ -133,10 +133,7 @@ public class PseudoGridView extends ViewGroup { x += width + mHorizontalSpacing; } } - y += maxHeight; - if (row > 0) { - y += mVerticalSpacing; - } + y += maxHeight + mVerticalSpacing; } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/user/UserDialog.kt b/packages/SystemUI/src/com/android/systemui/qs/user/UserDialog.kt deleted file mode 100644 index 26d1bbde2a54..000000000000 --- a/packages/SystemUI/src/com/android/systemui/qs/user/UserDialog.kt +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.qs.user - -import android.content.Context -import android.os.Bundle -import android.view.Gravity -import android.view.View -import android.view.ViewGroup -import android.view.WindowInsets -import android.view.WindowManager -import com.android.systemui.qs.PseudoGridView -import com.android.systemui.statusbar.phone.SystemUIDialog -import com.android.systemui.R - -/** - * Dialog for switching users or creating new ones. - */ -class UserDialog( - context: Context -) : SystemUIDialog(context) { - - // create() is no-op after creation - private lateinit var _doneButton: View - /** - * Button with text "Done" in dialog. - */ - val doneButton: View - get() { - create() - return _doneButton - } - - private lateinit var _settingsButton: View - /** - * Button with text "User Settings" in dialog. - */ - val settingsButton: View - get() { - create() - return _settingsButton - } - - private lateinit var _grid: PseudoGridView - /** - * Grid to populate with user avatar from adapter - */ - val grid: ViewGroup - get() { - create() - return _grid - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - window?.apply { - setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL) - attributes.fitInsetsTypes = attributes.fitInsetsTypes or WindowInsets.Type.statusBars() - attributes.receiveInsetsIgnoringZOrder = true - setGravity(Gravity.CENTER) - } - setContentView(R.layout.qs_user_dialog_content) - - _doneButton = requireViewById(R.id.done) - _settingsButton = requireViewById(R.id.settings) - _grid = requireViewById(R.id.grid) - } -}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt b/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt index d74a50e24ed3..00e04540fd94 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt @@ -21,13 +21,16 @@ import android.content.Context import android.content.DialogInterface import android.content.Intent import android.provider.Settings +import android.view.LayoutInflater import android.view.View import androidx.annotation.VisibleForTesting +import com.android.systemui.R import com.android.systemui.animation.DialogLaunchAnimator import com.android.systemui.dagger.SysUISingleton import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.FalsingManager import com.android.systemui.qs.tiles.UserDetailView +import com.android.systemui.statusbar.phone.SystemUIDialog import javax.inject.Inject import javax.inject.Provider @@ -40,7 +43,7 @@ class UserSwitchDialogController @VisibleForTesting constructor( private val activityStarter: ActivityStarter, private val falsingManager: FalsingManager, private val dialogLaunchAnimator: DialogLaunchAnimator, - private val dialogFactory: (Context) -> UserDialog + private val dialogFactory: (Context) -> SystemUIDialog ) { @Inject @@ -54,7 +57,7 @@ class UserSwitchDialogController @VisibleForTesting constructor( activityStarter, falsingManager, dialogLaunchAnimator, - { UserDialog(it) } + { SystemUIDialog(it) } ) companion object { @@ -71,9 +74,10 @@ class UserSwitchDialogController @VisibleForTesting constructor( with(dialogFactory(view.context)) { setShowForAllUsers(true) setCanceledOnTouchOutside(true) - create() // Needs to be called before we can retrieve views - settingsButton.setOnClickListener { + setTitle(R.string.qs_user_switch_dialog_title) + setPositiveButton(R.string.quick_settings_done, null) + setNeutralButton(R.string.quick_settings_more_user_settings) { _, _ -> if (!falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { dialogLaunchAnimator.disableAllCurrentDialogsExitAnimations() activityStarter.postStartActivityDismissingKeyguard( @@ -81,12 +85,14 @@ class UserSwitchDialogController @VisibleForTesting constructor( 0 ) } - dismiss() } - doneButton.setOnClickListener { dismiss() } + val gridFrame = LayoutInflater.from(this.context) + .inflate(R.layout.qs_user_dialog_content, null) + setView(gridFrame) val adapter = userDetailViewAdapterProvider.get() - adapter.linkToViewGroup(grid) + + adapter.linkToViewGroup(gridFrame.findViewById(R.id.grid)) val hostDialog = dialogLaunchAnimator.showFromView(this, view) adapter.injectDialogShower(DialogShowerImpl(hostDialog, dialogLaunchAnimator)) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 7b6cdbecc640..0f55f289ff27 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -1987,7 +1987,7 @@ public class StatusBar extends SystemUI implements } } - public void maybeEscalateHeadsUp() { + private void maybeEscalateHeadsUp() { mHeadsUpManager.getAllEntries().forEach(entry -> { final StatusBarNotification sbn = entry.getSbn(); final Notification notification = sbn.getNotification(); @@ -1998,6 +1998,7 @@ public class StatusBar extends SystemUI implements try { EventLog.writeEvent(EventLogTags.SYSUI_HEADS_UP_ESCALATION, sbn.getKey()); + wakeUpForFullScreenIntent(); notification.fullScreenIntent.send(); entry.notifyFullScreenIntentLaunched(); } catch (PendingIntent.CanceledException e) { @@ -2007,6 +2008,17 @@ public class StatusBar extends SystemUI implements mHeadsUpManager.releaseAllImmediately(); } + void wakeUpForFullScreenIntent() { + if (isGoingToSleep() || mDozing) { + mPowerManager.wakeUp( + SystemClock.uptimeMillis(), + PowerManager.WAKE_REASON_APPLICATION, + "com.android.systemui:full_screen_intent"); + mWakeUpComingFromTouch = false; + mWakeUpTouchLocation = null; + } + } + void makeExpandedVisible(boolean force) { if (SPEW) Log.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible); if (!force && (mExpandedVisible || !mCommandQueue.panelsEnabled())) { @@ -3536,7 +3548,7 @@ public class StatusBar extends SystemUI implements DejankUtils.startDetectingBlockingIpcs(tag); updateRevealEffect(false /* wakingUp */); updateNotificationPanelTouchState(); - notifyHeadsUpGoingToSleep(); + maybeEscalateHeadsUp(); dismissVolumeDialog(); mWakeUpCoordinator.setFullyAwake(false); mBypassHeadsUpNotifier.setFullyAwake(false); @@ -4081,10 +4093,6 @@ public class StatusBar extends SystemUI implements } } - protected void notifyHeadsUpGoingToSleep() { - maybeEscalateHeadsUp(); - } - /** * @return Whether the security bouncer from Keyguard is showing. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java index dba3b2418790..ce3811113912 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java @@ -41,6 +41,8 @@ import android.text.TextUtils; import android.util.EventLog; import android.view.View; +import androidx.annotation.VisibleForTesting; + import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.logging.MetricsLogger; import com.android.internal.statusbar.NotificationVisibility; @@ -593,7 +595,8 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit } } - private void handleFullScreenIntent(NotificationEntry entry) { + @VisibleForTesting + void handleFullScreenIntent(NotificationEntry entry) { if (mNotificationInterruptStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry)) { if (shouldSuppressFullScreenIntent(entry)) { mLogger.logFullScreenIntentSuppressedByDnD(entry.getKey()); @@ -617,6 +620,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit try { EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION, entry.getKey()); + mStatusBar.wakeUpForFullScreenIntent(); fullscreenIntent.send(); entry.notifyFullScreenIntentLaunched(); mMetricsLogger.count("note_fullscreen", 1); diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java deleted file mode 100644 index 734faec4ec74..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.navigationbar; - -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.ComponentName; -import android.view.accessibility.AccessibilityManager; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.systemui.SysuiTestCase; -import com.android.systemui.accessibility.AccessibilityButtonModeObserver; -import com.android.systemui.assist.AssistManager; -import com.android.systemui.dump.DumpManager; -import com.android.systemui.recents.OverviewProxyService; -import com.android.systemui.settings.UserTracker; -import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import dagger.Lazy; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class NavBarHelperTest extends SysuiTestCase { - - @Mock - AccessibilityManager mAccessibilityManager; - @Mock - AccessibilityManagerWrapper mAccessibilityManagerWrapper; - @Mock - AccessibilityButtonModeObserver mAccessibilityButtonModeObserver; - @Mock - OverviewProxyService mOverviewProxyService; - @Mock - Lazy<AssistManager> mAssistManagerLazy; - @Mock - AssistManager mAssistManager; - @Mock - NavigationModeController mNavigationModeController; - @Mock - UserTracker mUserTracker; - @Mock - ComponentName mAssistantComponent; - @Mock - DumpManager mDumpManager; - @Mock - NavBarHelper.NavbarTaskbarStateUpdater mNavbarTaskbarStateUpdater; - - private NavBarHelper mNavBarHelper; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - when(mAssistManagerLazy.get()).thenReturn(mAssistManager); - when(mAssistManager.getAssistInfoForUser(anyInt())).thenReturn(mAssistantComponent); - when(mUserTracker.getUserId()).thenReturn(1); - - mNavBarHelper = new NavBarHelper(mAccessibilityManager, - mAccessibilityManagerWrapper, mAccessibilityButtonModeObserver, - mOverviewProxyService, mAssistManagerLazy, mNavigationModeController, - mUserTracker, mDumpManager); - - } - - @Test - public void registerListenersInCtor() { - verify(mAccessibilityButtonModeObserver, times(1)).addListener(mNavBarHelper); - verify(mNavigationModeController, times(1)).addListener(mNavBarHelper); - verify(mOverviewProxyService, times(1)).addCallback(mNavBarHelper); - } - - @Test - public void registerAssistantContentObserver() { - mNavBarHelper.init(mContext); - verify(mAssistManager, times(1)).getAssistInfoForUser(anyInt()); - } - - @Test - public void callbacksFiredWhenRegistering() { - mNavBarHelper.init(mContext); - mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - verify(mNavbarTaskbarStateUpdater, times(1)) - .updateAccessibilityServicesState(); - verify(mNavbarTaskbarStateUpdater, times(1)) - .updateAssistantAvailable(anyBoolean()); - } - - @Test - public void assistantCallbacksFiredAfterConnecting() { - mNavBarHelper.init(mContext); - // 1st set of callbacks get called when registering - mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - - mNavBarHelper.onConnectionChanged(false); - // assert no more callbacks fired - verify(mNavbarTaskbarStateUpdater, times(1)) - .updateAccessibilityServicesState(); - verify(mNavbarTaskbarStateUpdater, times(1)) - .updateAssistantAvailable(anyBoolean()); - - mNavBarHelper.onConnectionChanged(true); - // assert no more callbacks fired - verify(mNavbarTaskbarStateUpdater, times(1)) - .updateAccessibilityServicesState(); - verify(mNavbarTaskbarStateUpdater, times(2)) - .updateAssistantAvailable(anyBoolean()); - } - - @Test - public void a11yCallbacksFiredAfterModeChange() { - mNavBarHelper.init(mContext); - // 1st set of callbacks get called when registering - mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - - mNavBarHelper.onAccessibilityButtonModeChanged(0); - verify(mNavbarTaskbarStateUpdater, times(2)) - .updateAccessibilityServicesState(); - verify(mNavbarTaskbarStateUpdater, times(1)) - .updateAssistantAvailable(anyBoolean()); - } - - @Test - public void assistantCallbacksFiredAfterNavModeChange() { - mNavBarHelper.init(mContext); - // 1st set of callbacks get called when registering - mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - - mNavBarHelper.onNavigationModeChanged(0); - verify(mNavbarTaskbarStateUpdater, times(1)) - .updateAccessibilityServicesState(); - verify(mNavbarTaskbarStateUpdater, times(2)) - .updateAssistantAvailable(anyBoolean()); - } - - @Test - public void removeListenerNoCallbacksFired() { - mNavBarHelper.init(mContext); - // 1st set of callbacks get called when registering - mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - - // Remove listener - mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater); - - // Would have fired 2nd callback if not removed - mNavBarHelper.onAccessibilityButtonModeChanged(0); - - // assert no more callbacks fired - verify(mNavbarTaskbarStateUpdater, times(1)) - .updateAccessibilityServicesState(); - verify(mNavbarTaskbarStateUpdater, times(1)) - .updateAssistantAvailable(anyBoolean()); - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java index 9d2541c0150f..62832205a097 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java @@ -83,7 +83,7 @@ public class NavigationBarControllerTest extends SysuiTestCase { mCommandQueue, Dependency.get(Dependency.MAIN_HANDLER), mock(ConfigurationController.class), - mock(NavBarHelper.class), + mock(NavigationBarA11yHelper.class), mock(TaskbarDelegate.class), mNavigationBarFactory, mock(DumpManager.class), diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java index 776b6aa2ef38..223ffbd7bba5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java @@ -131,7 +131,7 @@ public class NavigationBarTest extends SysuiTestCase { @Mock EdgeBackGestureHandler mEdgeBackGestureHandler; @Mock - NavBarHelper mNavBarHelper; + NavigationBarA11yHelper mNavigationBarA11yHelper; @Mock private LightBarController mLightBarController; @Mock @@ -220,7 +220,6 @@ public class NavigationBarTest extends SysuiTestCase { new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_SYSTEMUI) .setLong(HOME_BUTTON_LONG_PRESS_DURATION_MS, 100) .build()); - when(mNavBarHelper.getLongPressHomeEnabled()).thenReturn(true); mNavigationBar.onViewAttachedToWindow(mNavigationBar.createView(null)); mNavigationBar.onHomeTouch(mNavigationBar.getView(), MotionEvent.obtain( @@ -285,14 +284,14 @@ public class NavigationBarTest extends SysuiTestCase { public void testA11yEventAfterDetach() { View v = mNavigationBar.createView(null); mNavigationBar.onViewAttachedToWindow(v); - verify(mNavBarHelper).registerNavTaskStateUpdater(any( - NavBarHelper.NavbarTaskbarStateUpdater.class)); + verify(mNavigationBarA11yHelper).registerA11yEventListener(any( + NavigationBarA11yHelper.NavA11yEventListener.class)); mNavigationBar.onViewDetachedFromWindow(v); - verify(mNavBarHelper).removeNavTaskStateUpdater(any( - NavBarHelper.NavbarTaskbarStateUpdater.class)); + verify(mNavigationBarA11yHelper).removeA11yEventListener(any( + NavigationBarA11yHelper.NavA11yEventListener.class)); // Should be safe even though the internal view is now null. - mNavigationBar.updateAcessibilityStateFlags(); + mNavigationBar.updateAccessibilityServicesState(); } private NavigationBar createNavBar(Context context) { @@ -322,7 +321,7 @@ public class NavigationBarTest extends SysuiTestCase { mHandler, mock(NavigationBarOverlayController.class), mUiEventLogger, - mNavBarHelper, + mNavigationBarA11yHelper, mock(UserTracker.class), mLightBarController, mLightBarcontrollerFactory, diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserDialogTest.kt deleted file mode 100644 index d5fe588b2115..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserDialogTest.kt +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.qs.user - -import android.testing.AndroidTestingRunner -import android.testing.TestableLooper -import android.view.View -import android.view.ViewGroup -import androidx.test.filters.SmallTest -import com.android.systemui.SysuiTestCase -import com.google.common.truth.Truth.assertThat -import org.junit.After -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith - -@SmallTest -@RunWith(AndroidTestingRunner::class) -@TestableLooper.RunWithLooper -class UserDialogTest : SysuiTestCase() { - - private lateinit var dialog: UserDialog - - @Before - fun setUp() { - dialog = UserDialog(mContext) - } - - @After - fun tearDown() { - dialog.dismiss() - } - - @Test - fun doneButtonExists() { - assertThat(dialog.doneButton).isInstanceOf(View::class.java) - } - - @Test - fun settingsButtonExists() { - assertThat(dialog.settingsButton).isInstanceOf(View::class.java) - } - - @Test - fun gridExistsAndIsViewGroup() { - assertThat(dialog.grid).isInstanceOf(ViewGroup::class.java) - } -}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt index ea3a42ce501c..3c4a557eac10 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.qs.user import android.app.Dialog +import android.content.DialogInterface import android.content.Intent import android.provider.Settings import android.testing.AndroidTestingRunner @@ -28,6 +29,7 @@ import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.FalsingManager import com.android.systemui.qs.PseudoGridView import com.android.systemui.qs.tiles.UserDetailView +import com.android.systemui.statusbar.phone.SystemUIDialog import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.capture @@ -43,7 +45,6 @@ import org.mockito.Mockito.`when` import org.mockito.Mockito.anyBoolean import org.mockito.Mockito.anyInt import org.mockito.Mockito.argThat -import org.mockito.Mockito.inOrder import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @@ -53,27 +54,21 @@ import org.mockito.MockitoAnnotations class UserSwitchDialogControllerTest : SysuiTestCase() { @Mock - private lateinit var dialog: UserDialog + private lateinit var dialog: SystemUIDialog @Mock private lateinit var falsingManager: FalsingManager @Mock - private lateinit var settingsView: View - @Mock - private lateinit var doneView: View - @Mock private lateinit var activityStarter: ActivityStarter @Mock private lateinit var userDetailViewAdapter: UserDetailView.Adapter @Mock private lateinit var launchView: View @Mock - private lateinit var gridView: PseudoGridView - @Mock private lateinit var dialogLaunchAnimator: DialogLaunchAnimator @Mock private lateinit var hostDialog: Dialog @Captor - private lateinit var clickCaptor: ArgumentCaptor<View.OnClickListener> + private lateinit var clickCaptor: ArgumentCaptor<DialogInterface.OnClickListener> private lateinit var controller: UserSwitchDialogController @@ -81,11 +76,8 @@ class UserSwitchDialogControllerTest : SysuiTestCase() { fun setUp() { MockitoAnnotations.initMocks(this) - `when`(dialog.settingsButton).thenReturn(settingsView) - `when`(dialog.doneButton).thenReturn(doneView) - `when`(dialog.grid).thenReturn(gridView) - `when`(launchView.context).thenReturn(mContext) + `when`(dialog.context).thenReturn(mContext) `when`(dialogLaunchAnimator.showFromView(any(), any(), anyBoolean())) .thenReturn(hostDialog) @@ -105,30 +97,6 @@ class UserSwitchDialogControllerTest : SysuiTestCase() { } @Test - fun createCalledBeforeDoneButton() { - controller.showDialog(launchView) - val inOrder = inOrder(dialog) - inOrder.verify(dialog).create() - inOrder.verify(dialog).doneButton - } - - @Test - fun createCalledBeforeSettingsButton() { - controller.showDialog(launchView) - val inOrder = inOrder(dialog) - inOrder.verify(dialog).create() - inOrder.verify(dialog).settingsButton - } - - @Test - fun createCalledBeforeGrid() { - controller.showDialog(launchView) - val inOrder = inOrder(dialog) - inOrder.verify(dialog).create() - inOrder.verify(dialog).grid - } - - @Test fun dialog_showForAllUsers() { controller.showDialog(launchView) verify(dialog).setShowForAllUsers(true) @@ -143,51 +111,44 @@ class UserSwitchDialogControllerTest : SysuiTestCase() { @Test fun adapterAndGridLinked() { controller.showDialog(launchView) - verify(userDetailViewAdapter).linkToViewGroup(gridView) + verify(userDetailViewAdapter).linkToViewGroup(any<PseudoGridView>()) } @Test - fun clickDoneButton_dismiss() { + fun doneButtonSetWithNullHandler() { controller.showDialog(launchView) - verify(doneView).setOnClickListener(capture(clickCaptor)) - - clickCaptor.value.onClick(doneView) - - verify(activityStarter, never()).postStartActivityDismissingKeyguard(any(), anyInt()) - verify(dialog).dismiss() + verify(dialog).setPositiveButton(anyInt(), eq(null)) } @Test - fun clickSettingsButton_noFalsing_opensSettingsAndDismisses() { + fun clickSettingsButton_noFalsing_opensSettings() { `when`(falsingManager.isFalseTap(anyInt())).thenReturn(false) controller.showDialog(launchView) - verify(settingsView).setOnClickListener(capture(clickCaptor)) + verify(dialog).setNeutralButton(anyInt(), capture(clickCaptor)) - clickCaptor.value.onClick(settingsView) + clickCaptor.value.onClick(dialog, DialogInterface.BUTTON_NEUTRAL) verify(activityStarter) .postStartActivityDismissingKeyguard( argThat(IntentMatcher(Settings.ACTION_USER_SETTINGS)), eq(0) ) - verify(dialog).dismiss() } @Test - fun clickSettingsButton_Falsing_notOpensSettingsAndDismisses() { + fun clickSettingsButton_Falsing_notOpensSettings() { `when`(falsingManager.isFalseTap(anyInt())).thenReturn(true) controller.showDialog(launchView) - verify(settingsView).setOnClickListener(capture(clickCaptor)) + verify(dialog).setNeutralButton(anyInt(), capture(clickCaptor)) - clickCaptor.value.onClick(settingsView) + clickCaptor.value.onClick(dialog, DialogInterface.BUTTON_NEUTRAL) verify(activityStarter, never()).postStartActivityDismissingKeyguard(any(), anyInt()) - verify(dialog).dismiss() } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java index 72a3d664a6ce..cec5877e324a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java @@ -34,6 +34,7 @@ import static org.mockito.Mockito.when; import android.app.KeyguardManager; import android.app.Notification; +import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Intent; import android.os.Handler; @@ -62,7 +63,6 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.StatusBarState; -import com.android.systemui.statusbar.notification.NotificationActivityStarter; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider; import com.android.systemui.statusbar.notification.collection.NotifPipeline; @@ -114,6 +114,8 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { @Mock private KeyguardStateController mKeyguardStateController; @Mock + private NotificationInterruptStateProvider mNotificationInterruptStateProvider; + @Mock private Handler mHandler; @Mock private BubblesManager mBubblesManager; @@ -133,7 +135,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { @Mock private OnUserInteractionCallback mOnUserInteractionCallback; @Mock - private NotificationActivityStarter mNotificationActivityStarter; + private StatusBarNotificationActivityStarter mNotificationActivityStarter; @Mock private ActivityLaunchAnimator mActivityLaunchAnimator; private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock()); @@ -209,7 +211,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { mock(NotificationLockscreenUserManager.class), mShadeController, mKeyguardStateController, - mock(NotificationInterruptStateProvider.class), + mNotificationInterruptStateProvider, mock(LockPatternUtils.class), mock(StatusBarRemoteInputCallback.class), mActivityIntentHelper, @@ -365,4 +367,27 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase { // Notification should not be cancelled. verify(mEntryManager, never()).performRemoveNotification(eq(sbn), any(), anyInt()); } + + @Test + public void testOnFullScreenIntentWhenDozing_wakeUpDevice() { + // GIVEN entry that can has a full screen intent that can show + Notification.Builder nb = new Notification.Builder(mContext, "a") + .setContentTitle("foo") + .setSmallIcon(android.R.drawable.sym_def_app_icon) + .setFullScreenIntent(mock(PendingIntent.class), true); + StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, + "tag" + System.currentTimeMillis(), 0, 0, + nb.build(), new UserHandle(0), null, 0); + NotificationEntry entry = mock(NotificationEntry.class); + when(entry.getImportance()).thenReturn(NotificationManager.IMPORTANCE_HIGH); + when(entry.getSbn()).thenReturn(sbn); + when(mNotificationInterruptStateProvider.shouldLaunchFullScreenIntentWhenAdded(eq(entry))) + .thenReturn(true); + + // WHEN + mNotificationActivityStarter.handleFullScreenIntent(entry); + + // THEN display should try wake up for the full screen intent + verify(mStatusBar).wakeUpForFullScreenIntent(); + } } diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 1e7b676fbfe4..6afd3355b0a1 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -51,7 +51,6 @@ import static com.android.server.wm.WindowManagerService.LOGTAG_INPUT_FOCUS; import static java.lang.Integer.MAX_VALUE; import android.annotation.Nullable; -import android.graphics.Rect; import android.graphics.Region; import android.os.Handler; import android.os.IBinder; @@ -303,9 +302,6 @@ final class InputMonitor { && !mDisableWallpaperTouchEvents; inputWindowHandle.setHasWallpaper(hasWallpaper); - final Rect frame = w.getFrame(); - inputWindowHandle.setFrame(frame.left, frame.top, frame.right, frame.bottom); - // Surface insets are hardcoded to be the same in all directions // and we could probably deprecate the "left/right/top/bottom" concept. // we avoid reintroducing this concept by just choosing one of them here. @@ -315,11 +311,19 @@ final class InputMonitor { // what is on screen to what is actually being touched in the UI. inputWindowHandle.setScaleFactor(w.mGlobalScale != 1f ? (1f / w.mGlobalScale) : 1f); - final int flags = w.getSurfaceTouchableRegion(mTmpRegion, w.mAttrs.flags); - inputWindowHandle.setTouchableRegion(mTmpRegion); + // Update layout params flags to force the window to be not touch modal. We do this to + // restrict the window's touchable region to the task even if it request touches outside its + // window bounds. An example is a dialog in primary split should get touches outside its + // window within the primary task but should not get any touches going to the secondary + // task. + int flags = w.mAttrs.flags; + if (w.mAttrs.isModal()) { + flags = flags | FLAG_NOT_TOUCH_MODAL; + } inputWindowHandle.setLayoutParamsFlags(flags); - boolean useSurfaceCrop = false; + boolean useSurfaceBoundsAsTouchRegion = false; + SurfaceControl touchableRegionCrop = null; final Task task = w.getTask(); if (task != null) { // TODO(b/165794636): Remove the special case for freeform window once drag resizing is @@ -331,20 +335,22 @@ final class InputMonitor { // we need to make sure that these changes in crop are reflected in the input // windows, and so ensure this flag is set so that the input crop always reflects // the surface hierarchy. - // TODO(b/168252846): we have some issues with modal-windows, so we need to cross - // that bridge now that we organize full-screen Tasks. - inputWindowHandle.setTouchableRegionCrop(null /* Use this surfaces crop */); - inputWindowHandle.setReplaceTouchableRegionWithCrop(true); - useSurfaceCrop = true; + useSurfaceBoundsAsTouchRegion = true; + + if (w.mAttrs.isModal()) { + TaskFragment parent = w.getTaskFragment(); + touchableRegionCrop = parent != null ? parent.getSurfaceControl() : null; + } } else if (task.cropWindowsToRootTaskBounds() && !w.inFreeformWindowingMode()) { - inputWindowHandle.setTouchableRegionCrop(task.getRootTask().getSurfaceControl()); - inputWindowHandle.setReplaceTouchableRegionWithCrop(false); - useSurfaceCrop = true; + touchableRegionCrop = task.getRootTask().getSurfaceControl(); } } - if (!useSurfaceCrop) { - inputWindowHandle.setReplaceTouchableRegionWithCrop(false); - inputWindowHandle.setTouchableRegionCrop(null); + inputWindowHandle.setReplaceTouchableRegionWithCrop(useSurfaceBoundsAsTouchRegion); + inputWindowHandle.setTouchableRegionCrop(touchableRegionCrop); + + if (!useSurfaceBoundsAsTouchRegion) { + w.getSurfaceTouchableRegion(mTmpRegion, w.mAttrs); + inputWindowHandle.setTouchableRegion(mTmpRegion); } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index e0c3cf968f5c..9128732db366 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -51,7 +51,6 @@ import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND; import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; -import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; import static android.view.WindowManager.LayoutParams.FLAG_SCALED; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; @@ -2882,10 +2881,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } - int getSurfaceTouchableRegion(Region region, int flags) { - final boolean modal = (flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0; + void getSurfaceTouchableRegion(Region region, WindowManager.LayoutParams attrs) { + final boolean modal = attrs.isModal(); if (modal) { - flags |= FLAG_NOT_TOUCH_MODAL; if (mActivityRecord != null) { // Limit the outer touch to the activity root task region. updateRegionForModalActivityWindow(region); @@ -2917,8 +2915,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (mInvGlobalScale != 1.f) { region.scale(mInvGlobalScale); } - - return flags; } /** @@ -3766,10 +3762,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP * {@link WindowManager.LayoutParams#FLAG_NOT_TOUCH_MODAL touch modality.} */ void getEffectiveTouchableRegion(Region outRegion) { - final boolean modal = (mAttrs.flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0; final DisplayContent dc = getDisplayContent(); - if (modal && dc != null) { + if (mAttrs.isModal() && dc != null) { outRegion.set(dc.getBounds()); cropRegionToRootTaskBoundsIfNeeded(outRegion); subtractTouchExcludeRegionIfNeeded(outRegion); |