diff options
33 files changed, 668 insertions, 403 deletions
diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java index 4706affa3541..5f8acff80c0a 100644 --- a/core/java/com/android/internal/widget/ConversationLayout.java +++ b/core/java/com/android/internal/widget/ConversationLayout.java @@ -111,6 +111,7 @@ public class ConversationLayout extends FrameLayout private Icon mLargeIcon; private View mExpandButtonContainer; private ViewGroup mExpandButtonAndContentContainer; + private ViewGroup mExpandButtonContainerA11yContainer; private NotificationExpandButton mExpandButton; private MessagingLinearLayout mImageMessageContainer; private int mBadgeProtrusion; @@ -234,6 +235,8 @@ public class ConversationLayout extends FrameLayout }); mConversationText = findViewById(R.id.conversation_text); mExpandButtonContainer = findViewById(R.id.expand_button_container); + mExpandButtonContainerA11yContainer = + findViewById(R.id.expand_button_a11y_container); mConversationHeader = findViewById(R.id.conversation_header); mContentContainer = findViewById(R.id.notification_action_list_margin_target); mExpandButtonAndContentContainer = findViewById(R.id.expand_button_and_content_container); @@ -1091,7 +1094,7 @@ public class ConversationLayout extends FrameLayout newContainer = mExpandButtonAndContentContainer; } else { buttonGravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP; - newContainer = this; + newContainer = mExpandButtonContainerA11yContainer; } mExpandButton.setExpanded(!mIsCollapsed); diff --git a/core/res/res/layout/notification_template_material_conversation.xml b/core/res/res/layout/notification_template_material_conversation.xml index 42fb4a26dd3b..ce8a90495572 100644 --- a/core/res/res/layout/notification_template_material_conversation.xml +++ b/core/res/res/layout/notification_template_material_conversation.xml @@ -89,45 +89,62 @@ <include layout="@layout/notification_material_action_list" /> </com.android.internal.widget.RemeasuringLinearLayout> - <!--This is dynamically placed between here and at the end of the layout. It starts here since - only FrameLayout layout params have gravity--> + <!--expand_button_a11y_container ensures talkback focus order is correct when view is expanded. + The -1px of marginTop and 1px of paddingTop make sure expand_button_a11y_container is prior to + its sibling view in accessibility focus order. + {see android.view.ViewGroup.addChildrenForAccessibility()} + expand_button_container will be moved under expand_button_and_content_container when collapsed, + this dynamic movement ensures message can flow under expand button when expanded--> <FrameLayout - android:id="@+id/expand_button_container" - android:layout_width="wrap_content" + android:id="@+id/expand_button_a11y_container" + android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="end|top" android:clipChildren="false" - android:clipToPadding="false"> - <!--This layout makes sure that we can nicely center the expand content in the - collapsed layout while the parent makes sure that we're never laid out bigger - than the messaging content.--> - <LinearLayout - android:id="@+id/expand_button_touch_container" + android:clipToPadding="false" + android:layout_marginTop="-1px" + android:paddingTop="1px" + > + <!--expand_button_container is dynamically placed between here and at the end of the + layout. It starts here since only FrameLayout layout params have gravity--> + <FrameLayout + android:id="@+id/expand_button_container" android:layout_width="wrap_content" - android:layout_height="@dimen/conversation_expand_button_height" - android:orientation="horizontal" + android:layout_height="match_parent" android:layout_gravity="end|top" - android:paddingEnd="0dp" - android:clipToPadding="false" android:clipChildren="false" - > - <!-- Images --> - <com.android.internal.widget.MessagingLinearLayout - android:id="@+id/conversation_image_message_container" - android:forceHasOverlappingRendering="false" - android:layout_width="40dp" - android:layout_height="40dp" - android:layout_marginStart="@dimen/conversation_image_start_margin" - android:spacing="0dp" - android:layout_gravity="center" + android:clipToPadding="false"> + <!--expand_button_touch_container makes sure that we can nicely center the expand + content in the collapsed layout while the parent makes sure that we're never laid out + bigger than the messaging content.--> + <LinearLayout + android:id="@+id/expand_button_touch_container" + android:layout_width="wrap_content" + android:layout_height="@dimen/conversation_expand_button_height" + android:orientation="horizontal" + android:layout_gravity="end|top" + android:paddingEnd="0dp" android:clipToPadding="false" android:clipChildren="false" - /> - <include layout="@layout/notification_expand_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center" - /> - </LinearLayout> + > + <!-- Images --> + <com.android.internal.widget.MessagingLinearLayout + android:id="@+id/conversation_image_message_container" + android:forceHasOverlappingRendering="false" + android:layout_width="40dp" + android:layout_height="40dp" + android:layout_marginStart="@dimen/conversation_image_start_margin" + android:spacing="0dp" + android:layout_gravity="center" + android:clipToPadding="false" + android:clipChildren="false" + /> + <include layout="@layout/notification_expand_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + /> + </LinearLayout> + </FrameLayout> </FrameLayout> </com.android.internal.widget.ConversationLayout> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index e773a9c706b0..a6174e146367 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -4279,6 +4279,7 @@ <java-symbol type="id" name="conversation_icon_badge_ring" /> <java-symbol type="id" name="conversation_icon_badge_bg" /> <java-symbol type="id" name="expand_button_container" /> + <java-symbol type="id" name="expand_button_a11y_container" /> <java-symbol type="id" name="expand_button_touch_container" /> <java-symbol type="id" name="messaging_group_content_container" /> <java-symbol type="id" name="expand_button_and_content_container" /> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/util/GroupedRecentTaskInfo.java b/libs/WindowManager/Shell/src/com/android/wm/shell/util/GroupedRecentTaskInfo.java index eab75b983268..c045cebdf4e0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/util/GroupedRecentTaskInfo.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/GroupedRecentTaskInfo.java @@ -114,7 +114,8 @@ public class GroupedRecentTaskInfo implements Parcelable { /** * Get all {@link ActivityManager.RecentTaskInfo}s grouped together. */ - public List<ActivityManager.RecentTaskInfo> getAllTaskInfos() { + @NonNull + public List<ActivityManager.RecentTaskInfo> getTaskInfoList() { return Arrays.asList(mTasks); } @@ -148,7 +149,7 @@ public class GroupedRecentTaskInfo implements Parcelable { if (mSplitBounds != null) { taskString.append(", SplitBounds: ").append(mSplitBounds); } - taskString.append(", Type=").append(mType); + taskString.append(", Type="); switch (mType) { case TYPE_SINGLE: taskString.append("TYPE_SINGLE"); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/GroupedRecentTaskInfoTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/GroupedRecentTaskInfoTest.kt new file mode 100644 index 000000000000..baa06f2f0c45 --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/GroupedRecentTaskInfoTest.kt @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2022 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.wm.shell.recents + +import android.app.ActivityManager +import android.graphics.Rect +import android.os.Parcel +import android.testing.AndroidTestingRunner +import android.window.IWindowContainerToken +import android.window.WindowContainerToken +import androidx.test.filters.SmallTest +import com.android.wm.shell.ShellTestCase +import com.android.wm.shell.util.GroupedRecentTaskInfo +import com.android.wm.shell.util.GroupedRecentTaskInfo.CREATOR +import com.android.wm.shell.util.GroupedRecentTaskInfo.TYPE_FREEFORM +import com.android.wm.shell.util.GroupedRecentTaskInfo.TYPE_SINGLE +import com.android.wm.shell.util.GroupedRecentTaskInfo.TYPE_SPLIT +import com.android.wm.shell.util.SplitBounds +import com.google.common.truth.Correspondence +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.mock + +/** + * Tests for [GroupedRecentTaskInfo] + */ +@SmallTest +@RunWith(AndroidTestingRunner::class) +class GroupedRecentTaskInfoTest : ShellTestCase() { + + @Test + fun testSingleTask_hasCorrectType() { + assertThat(singleTaskGroupInfo().type).isEqualTo(TYPE_SINGLE) + } + + @Test + fun testSingleTask_task1Set_task2Null() { + val group = singleTaskGroupInfo() + assertThat(group.taskInfo1.taskId).isEqualTo(1) + assertThat(group.taskInfo2).isNull() + } + + @Test + fun testSingleTask_taskInfoList_hasOneTask() { + val list = singleTaskGroupInfo().taskInfoList + assertThat(list).hasSize(1) + assertThat(list[0].taskId).isEqualTo(1) + } + + @Test + fun testSplitTasks_hasCorrectType() { + assertThat(splitTasksGroupInfo().type).isEqualTo(TYPE_SPLIT) + } + + @Test + fun testSplitTasks_task1Set_task2Set_boundsSet() { + val group = splitTasksGroupInfo() + assertThat(group.taskInfo1.taskId).isEqualTo(1) + assertThat(group.taskInfo2?.taskId).isEqualTo(2) + assertThat(group.splitBounds).isNotNull() + } + + @Test + fun testSplitTasks_taskInfoList_hasTwoTasks() { + val list = splitTasksGroupInfo().taskInfoList + assertThat(list).hasSize(2) + assertThat(list[0].taskId).isEqualTo(1) + assertThat(list[1].taskId).isEqualTo(2) + } + + @Test + fun testFreeformTasks_hasCorrectType() { + assertThat(freeformTasksGroupInfo().type).isEqualTo(TYPE_FREEFORM) + } + + @Test + fun testSplitTasks_taskInfoList_hasThreeTasks() { + val list = freeformTasksGroupInfo().taskInfoList + assertThat(list).hasSize(3) + assertThat(list[0].taskId).isEqualTo(1) + assertThat(list[1].taskId).isEqualTo(2) + assertThat(list[2].taskId).isEqualTo(3) + } + + @Test + fun testParcelling_singleTask() { + val recentTaskInfo = singleTaskGroupInfo() + val parcel = Parcel.obtain() + recentTaskInfo.writeToParcel(parcel, 0) + parcel.setDataPosition(0) + // Read the object back from the parcel + val recentTaskInfoParcel = CREATOR.createFromParcel(parcel) + assertThat(recentTaskInfoParcel.type).isEqualTo(TYPE_SINGLE) + assertThat(recentTaskInfoParcel.taskInfo1.taskId).isEqualTo(1) + assertThat(recentTaskInfoParcel.taskInfo2).isNull() + } + + @Test + fun testParcelling_splitTasks() { + val recentTaskInfo = splitTasksGroupInfo() + val parcel = Parcel.obtain() + recentTaskInfo.writeToParcel(parcel, 0) + parcel.setDataPosition(0) + // Read the object back from the parcel + val recentTaskInfoParcel = CREATOR.createFromParcel(parcel) + assertThat(recentTaskInfoParcel.type).isEqualTo(TYPE_SPLIT) + assertThat(recentTaskInfoParcel.taskInfo1.taskId).isEqualTo(1) + assertThat(recentTaskInfoParcel.taskInfo2).isNotNull() + assertThat(recentTaskInfoParcel.taskInfo2!!.taskId).isEqualTo(2) + assertThat(recentTaskInfoParcel.splitBounds).isNotNull() + } + + @Test + fun testParcelling_freeformTasks() { + val recentTaskInfo = freeformTasksGroupInfo() + val parcel = Parcel.obtain() + recentTaskInfo.writeToParcel(parcel, 0) + parcel.setDataPosition(0) + // Read the object back from the parcel + val recentTaskInfoParcel = CREATOR.createFromParcel(parcel) + assertThat(recentTaskInfoParcel.type).isEqualTo(TYPE_FREEFORM) + assertThat(recentTaskInfoParcel.taskInfoList).hasSize(3) + // Only compare task ids + val taskIdComparator = Correspondence.transforming<ActivityManager.RecentTaskInfo, Int>( + { it?.taskId }, "has taskId of" + ) + assertThat(recentTaskInfoParcel.taskInfoList).comparingElementsUsing(taskIdComparator) + .containsExactly(1, 2, 3) + } + + private fun createTaskInfo(id: Int) = ActivityManager.RecentTaskInfo().apply { + taskId = id + token = WindowContainerToken(mock(IWindowContainerToken::class.java)) + } + + private fun singleTaskGroupInfo(): GroupedRecentTaskInfo { + val task = createTaskInfo(id = 1) + return GroupedRecentTaskInfo.forSingleTask(task) + } + + private fun splitTasksGroupInfo(): GroupedRecentTaskInfo { + val task1 = createTaskInfo(id = 1) + val task2 = createTaskInfo(id = 2) + val splitBounds = SplitBounds(Rect(), Rect(), 1, 2) + return GroupedRecentTaskInfo.forSplitTasks(task1, task2, splitBounds) + } + + private fun freeformTasksGroupInfo(): GroupedRecentTaskInfo { + val task1 = createTaskInfo(id = 1) + val task2 = createTaskInfo(id = 2) + val task3 = createTaskInfo(id = 3) + return GroupedRecentTaskInfo.forFreeformTasks(task1, task2, task3) + } +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java index 9e755dca7908..e9a1e2523a86 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java @@ -213,8 +213,8 @@ public class RecentTasksControllerTest extends ShellTestCase { assertEquals(GroupedRecentTaskInfo.TYPE_SINGLE, singleGroup2.getType()); // Check freeform group entries - assertEquals(t1, freeformGroup.getAllTaskInfos().get(0)); - assertEquals(t3, freeformGroup.getAllTaskInfos().get(1)); + assertEquals(t1, freeformGroup.getTaskInfoList().get(0)); + assertEquals(t3, freeformGroup.getTaskInfoList().get(1)); // Check single entries assertEquals(t2, singleGroup1.getTaskInfo1()); diff --git a/packages/SystemUI/ktfmt_includes.txt b/packages/SystemUI/ktfmt_includes.txt index 51cc1954299f..689938aded44 100644 --- a/packages/SystemUI/ktfmt_includes.txt +++ b/packages/SystemUI/ktfmt_includes.txt @@ -240,8 +240,6 @@ -packages/SystemUI/src/com/android/systemui/media/nearby/NearbyMediaDevicesManager.kt -packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt -packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttFlags.kt --packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/ChipInfoCommon.kt --packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt -packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLogger.kt -packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ChipStateReceiver.kt -packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt @@ -529,6 +527,8 @@ -packages/SystemUI/src/com/android/systemui/statusbar/tv/VpnStatusObserver.kt -packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowModule.kt -packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt +-packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt +-packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt -packages/SystemUI/src/com/android/systemui/toast/ToastDefaultAnimation.kt -packages/SystemUI/src/com/android/systemui/toast/ToastLogger.kt -packages/SystemUI/src/com/android/systemui/tv/TVSystemUICoreStartableModule.kt @@ -677,7 +677,6 @@ -packages/SystemUI/tests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt -packages/SystemUI/tests/src/com/android/systemui/media/nearby/NearbyMediaDevicesManagerTest.kt -packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt --packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt -packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerTest.kt -packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt -packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt @@ -834,6 +833,7 @@ -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/VariableDateViewControllerTest.kt -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/WalletControllerImplTest.kt -packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt +-packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt -packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateLoggingProviderTest.kt -packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt -packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 49843008af9f..f7681e8240e8 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -466,6 +466,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab FACE_AUTH_TRIGGERED_TRUST_DISABLED); } + mLogger.logTrustChanged(wasTrusted, enabled, userId); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -487,6 +488,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } } } + + if (message != null) { + mLogger.logShowTrustGrantedMessage(message.toString()); + } for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -743,6 +748,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mFingerprintCancelSignal = null; updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE, FACE_AUTH_UPDATED_FP_AUTHENTICATED); + mLogger.d("onFingerprintAuthenticated"); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -986,6 +992,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mFaceCancelSignal = null; updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE, FACE_AUTH_UPDATED_ON_FACE_AUTHENTICATED); + mLogger.d("onFaceAuthenticated"); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -3445,6 +3452,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mUserFaceAuthenticated.clear(); mTrustManager.clearAllBiometricRecognized(BiometricSourceType.FINGERPRINT, unlockedUser); mTrustManager.clearAllBiometricRecognized(BiometricSourceType.FACE, unlockedUser); + mLogger.d("clearBiometricRecognized"); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); @@ -3694,6 +3702,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab @Override public void dump(PrintWriter pw, String[] args) { pw.println("KeyguardUpdateMonitor state:"); + pw.println(" getUserHasTrust()=" + getUserHasTrust(getCurrentUser())); + pw.println(" getUserUnlockedWithBiometric()=" + + getUserUnlockedWithBiometric(getCurrentUser())); pw.println(" SIM States:"); for (SimData data : mSimDatas.values()) { pw.println(" " + data.toString()); diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt index 2bc98f1a535c..7a00cd930f2a 100644 --- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt +++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt @@ -340,4 +340,40 @@ class KeyguardUpdateMonitorLogger @Inject constructor( bool1 = dismissKeyguard }, { "reportUserRequestedUnlock origin=$str1 reason=$str2 dismissKeyguard=$bool1" }) } + + fun logShowTrustGrantedMessage( + message: String + ) { + logBuffer.log(TAG, DEBUG, { + str1 = message + }, { "showTrustGrantedMessage message$str1" }) + } + + fun logTrustChanged( + wasTrusted: Boolean, + isNowTrusted: Boolean, + userId: Int + ) { + logBuffer.log(TAG, DEBUG, { + bool1 = wasTrusted + bool2 = isNowTrusted + int1 = userId + }, { "onTrustChanged[user=$int1] wasTrusted=$bool1 isNowTrusted=$bool2" }) + } + + fun logKeyguardStateUpdate( + secure: Boolean, + canDismissLockScreen: Boolean, + trusted: Boolean, + trustManaged: Boolean + + ) { + logBuffer.log("KeyguardState", DEBUG, { + bool1 = secure + bool2 = canDismissLockScreen + bool3 = trusted + bool4 = trustManaged + }, { "#update secure=$bool1 canDismissKeyguard=$bool2" + + " trusted=$bool3 trustManaged=$bool4" }) + } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt index 8f32ff9db50c..ac2c9b1d7ff2 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt @@ -94,6 +94,7 @@ constructor( hasFavorites = favorites?.isNotEmpty() == true, hasServiceInfos = serviceInfos.isNotEmpty(), iconResourceId = component.getTileImageId(), + visibility = component.getVisibility(), ), TAG, ) @@ -110,9 +111,16 @@ constructor( isFeatureEnabled: Boolean, hasFavorites: Boolean, hasServiceInfos: Boolean, + visibility: ControlsComponent.Visibility, @DrawableRes iconResourceId: Int?, ): KeyguardQuickAffordanceConfig.State { - return if (isFeatureEnabled && hasFavorites && hasServiceInfos && iconResourceId != null) { + return if ( + isFeatureEnabled && + hasFavorites && + hasServiceInfos && + iconResourceId != null && + visibility == ControlsComponent.Visibility.AVAILABLE + ) { KeyguardQuickAffordanceConfig.State.Visible( icon = ContainedDrawable.WithResource(iconResourceId), contentDescriptionResourceId = component.getTileTitleId(), diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt index 35a6c74518e0..5d6d683f93f6 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt @@ -34,15 +34,14 @@ import com.android.settingslib.Utils import com.android.systemui.R import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main -import com.android.systemui.media.taptotransfer.common.ChipInfoCommon -import com.android.systemui.media.taptotransfer.common.DEFAULT_TIMEOUT_MILLIS -import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCommon import com.android.systemui.media.taptotransfer.common.MediaTttLogger import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.policy.ConfigurationController +import com.android.systemui.temporarydisplay.DEFAULT_TIMEOUT_MILLIS +import com.android.systemui.temporarydisplay.TemporaryViewDisplayController +import com.android.systemui.temporarydisplay.TemporaryViewInfo import com.android.systemui.util.animation.AnimationUtil.Companion.frames import com.android.systemui.util.concurrency.DelayableExecutor -import com.android.systemui.util.view.ViewUtil import javax.inject.Inject /** @@ -56,18 +55,16 @@ class MediaTttChipControllerReceiver @Inject constructor( context: Context, @MediaTttReceiverLogger logger: MediaTttLogger, windowManager: WindowManager, - viewUtil: ViewUtil, mainExecutor: DelayableExecutor, accessibilityManager: AccessibilityManager, configurationController: ConfigurationController, powerManager: PowerManager, @Main private val mainHandler: Handler, private val uiEventLogger: MediaTttReceiverUiEventLogger, -) : MediaTttChipControllerCommon<ChipReceiverInfo>( +) : TemporaryViewDisplayController<ChipReceiverInfo>( context, logger, windowManager, - viewUtil, mainExecutor, accessibilityManager, configurationController, @@ -119,18 +116,18 @@ class MediaTttChipControllerReceiver @Inject constructor( uiEventLogger.logReceiverStateChange(chipState) if (chipState == ChipStateReceiver.FAR_FROM_SENDER) { - removeChip(removalReason = ChipStateReceiver.FAR_FROM_SENDER::class.simpleName!!) + removeView(removalReason = ChipStateReceiver.FAR_FROM_SENDER::class.simpleName!!) return } if (appIcon == null) { - displayChip(ChipReceiverInfo(routeInfo, appIconDrawableOverride = null, appName)) + displayView(ChipReceiverInfo(routeInfo, appIconDrawableOverride = null, appName)) return } appIcon.loadDrawableAsync( context, Icon.OnDrawableLoadedListener { drawable -> - displayChip(ChipReceiverInfo(routeInfo, drawable, appName)) + displayView(ChipReceiverInfo(routeInfo, drawable, appName)) }, // Notify the listener on the main handler since the listener will update // the UI. @@ -138,19 +135,19 @@ class MediaTttChipControllerReceiver @Inject constructor( ) } - override fun updateChipView(newChipInfo: ChipReceiverInfo, currentChipView: ViewGroup) { - super.updateChipView(newChipInfo, currentChipView) + override fun updateView(newInfo: ChipReceiverInfo, currentView: ViewGroup) { + super.updateView(newInfo, currentView) val iconName = setIcon( - currentChipView, - newChipInfo.routeInfo.clientPackageName, - newChipInfo.appIconDrawableOverride, - newChipInfo.appNameOverride + currentView, + newInfo.routeInfo.clientPackageName, + newInfo.appIconDrawableOverride, + newInfo.appNameOverride ) - currentChipView.contentDescription = iconName + currentView.contentDescription = iconName } - override fun animateChipIn(chipView: ViewGroup) { - val appIconView = chipView.requireViewById<View>(R.id.app_icon) + override fun animateViewIn(view: ViewGroup) { + val appIconView = view.requireViewById<View>(R.id.app_icon) appIconView.animate() .translationYBy(-1 * getTranslationAmount().toFloat()) .setDuration(30.frames) @@ -160,8 +157,8 @@ class MediaTttChipControllerReceiver @Inject constructor( .setDuration(5.frames) .start() // Using withEndAction{} doesn't apply a11y focus when screen is unlocked. - appIconView.postOnAnimation { chipView.requestAccessibilityFocus() } - startRipple(chipView.requireViewById(R.id.ripple)) + appIconView.postOnAnimation { view.requestAccessibilityFocus() } + startRipple(view.requireViewById(R.id.ripple)) } override fun getIconSize(isAppIcon: Boolean): Int? = @@ -216,7 +213,7 @@ data class ChipReceiverInfo( val routeInfo: MediaRoute2Info, val appIconDrawableOverride: Drawable?, val appNameOverride: CharSequence? -) : ChipInfoCommon { +) : TemporaryViewInfo { override fun getTimeoutMs() = DEFAULT_TIMEOUT_MILLIS } diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt index a153cb6c0d31..bde588c14fc8 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt @@ -25,7 +25,7 @@ import androidx.annotation.StringRes import com.android.internal.logging.UiEventLogger import com.android.internal.statusbar.IUndoMediaTransferCallback import com.android.systemui.R -import com.android.systemui.media.taptotransfer.common.DEFAULT_TIMEOUT_MILLIS +import com.android.systemui.temporarydisplay.DEFAULT_TIMEOUT_MILLIS /** * A class enumerating all the possible states of the media tap-to-transfer chip on the sender @@ -120,7 +120,7 @@ enum class ChipStateSender( // state, but that may take too long to go through the binder and the user may be // confused ast o why the UI hasn't changed yet. So, we immediately change the UI // here. - controllerSender.displayChip( + controllerSender.displayView( ChipSenderInfo( TRANSFER_TO_THIS_DEVICE_TRIGGERED, routeInfo, undoCallback ) @@ -155,7 +155,7 @@ enum class ChipStateSender( // state, but that may take too long to go through the binder and the user may be // confused as to why the UI hasn't changed yet. So, we immediately change the UI // here. - controllerSender.displayChip( + controllerSender.displayView( ChipSenderInfo( TRANSFER_TO_RECEIVER_TRIGGERED, routeInfo, undoCallback ) diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt index 933548963390..0c1ebd70c572 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt @@ -33,14 +33,13 @@ import com.android.systemui.animation.Interpolators import com.android.systemui.animation.ViewHierarchyAnimator import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main -import com.android.systemui.media.taptotransfer.common.ChipInfoCommon -import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCommon import com.android.systemui.media.taptotransfer.common.MediaTttLogger -import com.android.systemui.media.taptotransfer.common.MediaTttRemovalReason import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.policy.ConfigurationController +import com.android.systemui.temporarydisplay.TemporaryDisplayRemovalReason +import com.android.systemui.temporarydisplay.TemporaryViewDisplayController +import com.android.systemui.temporarydisplay.TemporaryViewInfo import com.android.systemui.util.concurrency.DelayableExecutor -import com.android.systemui.util.view.ViewUtil import javax.inject.Inject /** @@ -53,17 +52,15 @@ class MediaTttChipControllerSender @Inject constructor( context: Context, @MediaTttSenderLogger logger: MediaTttLogger, windowManager: WindowManager, - viewUtil: ViewUtil, @Main mainExecutor: DelayableExecutor, accessibilityManager: AccessibilityManager, configurationController: ConfigurationController, powerManager: PowerManager, private val uiEventLogger: MediaTttSenderUiEventLogger -) : MediaTttChipControllerCommon<ChipSenderInfo>( +) : TemporaryViewDisplayController<ChipSenderInfo>( context, logger, windowManager, - viewUtil, mainExecutor, accessibilityManager, configurationController, @@ -106,53 +103,52 @@ class MediaTttChipControllerSender @Inject constructor( uiEventLogger.logSenderStateChange(chipState) if (chipState == ChipStateSender.FAR_FROM_RECEIVER) { - removeChip(removalReason = ChipStateSender.FAR_FROM_RECEIVER::class.simpleName!!) + removeView(removalReason = ChipStateSender.FAR_FROM_RECEIVER::class.simpleName!!) } else { - displayChip(ChipSenderInfo(chipState, routeInfo, undoCallback)) + displayView(ChipSenderInfo(chipState, routeInfo, undoCallback)) } } - /** Displays the chip view for the given state. */ - override fun updateChipView( - newChipInfo: ChipSenderInfo, - currentChipView: ViewGroup + override fun updateView( + newInfo: ChipSenderInfo, + currentView: ViewGroup ) { - super.updateChipView(newChipInfo, currentChipView) + super.updateView(newInfo, currentView) - val chipState = newChipInfo.state + val chipState = newInfo.state // App icon - val iconName = setIcon(currentChipView, newChipInfo.routeInfo.clientPackageName) + val iconName = setIcon(currentView, newInfo.routeInfo.clientPackageName) // Text - val otherDeviceName = newChipInfo.routeInfo.name.toString() + val otherDeviceName = newInfo.routeInfo.name.toString() val chipText = chipState.getChipTextString(context, otherDeviceName) - currentChipView.requireViewById<TextView>(R.id.text).text = chipText + currentView.requireViewById<TextView>(R.id.text).text = chipText // Loading - currentChipView.requireViewById<View>(R.id.loading).visibility = + currentView.requireViewById<View>(R.id.loading).visibility = chipState.isMidTransfer.visibleIfTrue() // Undo - val undoView = currentChipView.requireViewById<View>(R.id.undo) + val undoView = currentView.requireViewById<View>(R.id.undo) val undoClickListener = chipState.undoClickListener( - this, newChipInfo.routeInfo, newChipInfo.undoCallback, uiEventLogger + this, newInfo.routeInfo, newInfo.undoCallback, uiEventLogger ) undoView.setOnClickListener(undoClickListener) undoView.visibility = (undoClickListener != null).visibleIfTrue() // Failure - currentChipView.requireViewById<View>(R.id.failure_icon).visibility = + currentView.requireViewById<View>(R.id.failure_icon).visibility = chipState.isTransferFailure.visibleIfTrue() // For accessibility - currentChipView.requireViewById<ViewGroup>( + currentView.requireViewById<ViewGroup>( R.id.media_ttt_sender_chip_inner ).contentDescription = "$iconName $chipText" } - override fun animateChipIn(chipView: ViewGroup) { - val chipInnerView = chipView.requireViewById<ViewGroup>(R.id.media_ttt_sender_chip_inner) + override fun animateViewIn(view: ViewGroup) { + val chipInnerView = view.requireViewById<ViewGroup>(R.id.media_ttt_sender_chip_inner) ViewHierarchyAnimator.animateAddition( chipInnerView, ViewHierarchyAnimator.Hotspot.TOP, @@ -165,14 +161,14 @@ class MediaTttChipControllerSender @Inject constructor( ) } - override fun removeChip(removalReason: String) { + override fun removeView(removalReason: String) { // Don't remove the chip if we're mid-transfer since the user should still be able to // see the status of the transfer. (But do remove it if it's finally timed out.) - if (chipInfo?.state?.isMidTransfer == true && - removalReason != MediaTttRemovalReason.REASON_TIMEOUT) { + if (info?.state?.isMidTransfer == true && + removalReason != TemporaryDisplayRemovalReason.REASON_TIMEOUT) { return } - super.removeChip(removalReason) + super.removeView(removalReason) } private fun Boolean.visibleIfTrue(): Int { @@ -188,7 +184,7 @@ data class ChipSenderInfo( val state: ChipStateSender, val routeInfo: MediaRoute2Info, val undoCallback: IUndoMediaTransferCallback? = null -) : ChipInfoCommon { +) : TemporaryViewInfo { override fun getTimeoutMs() = state.timeout } diff --git a/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt b/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt index 621a6090f4a0..9b3fe92f9225 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt @@ -26,6 +26,7 @@ import com.android.systemui.Dumpable import com.android.systemui.dock.DockManager import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.FalsingManager +import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.phone.CentralSurfaces import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent import com.android.systemui.tuner.TunerService @@ -49,6 +50,7 @@ class PulsingGestureListener @Inject constructor( private val dockManager: DockManager, private val centralSurfaces: CentralSurfaces, private val ambientDisplayConfiguration: AmbientDisplayConfiguration, + private val statusBarStateController: StatusBarStateController, tunerService: TunerService, dumpManager: DumpManager ) : GestureDetector.SimpleOnGestureListener(), Dumpable { @@ -74,7 +76,8 @@ class PulsingGestureListener @Inject constructor( } override fun onSingleTapConfirmed(e: MotionEvent): Boolean { - if (singleTapEnabled && + if (statusBarStateController.isPulsing && + singleTapEnabled && !dockManager.isDocked && !falsingManager.isProximityNear && !falsingManager.isFalseTap(FalsingManager.MODERATE_PENALTY) @@ -89,7 +92,8 @@ class PulsingGestureListener @Inject constructor( } override fun onDoubleTap(e: MotionEvent): Boolean { - if ((doubleTapEnabled || singleTapEnabled) && + if (statusBarStateController.isPulsing && + (doubleTapEnabled || singleTapEnabled) && !falsingManager.isProximityNear && !falsingManager.isFalseDoubleTap ) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt index f6c4a316b211..cb13fcf246cb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt @@ -81,7 +81,6 @@ class NotificationShadeDepthController @Inject constructor( } lateinit var root: View - private var blurRoot: View? = null private var keyguardAnimator: Animator? = null private var notificationAnimator: Animator? = null private var updateScheduled: Boolean = false @@ -235,7 +234,7 @@ class NotificationShadeDepthController @Inject constructor( val opaque = scrimsVisible && !blursDisabledForAppLaunch Trace.traceCounter(Trace.TRACE_TAG_APP, "shade_blur_radius", blur) - blurUtils.applyBlur(blurRoot?.viewRootImpl ?: root.viewRootImpl, blur, opaque) + blurUtils.applyBlur(root.viewRootImpl, blur, opaque) lastAppliedBlur = blur wallpaperController.setNotificationShadeZoom(zoomOut) listeners.forEach { @@ -271,7 +270,6 @@ class NotificationShadeDepthController @Inject constructor( override fun onAnimationEnd(animation: Animator?) { keyguardAnimator = null wakeAndUnlockBlurRadius = 0f - scheduleUpdate() } }) start() @@ -302,7 +300,6 @@ class NotificationShadeDepthController @Inject constructor( override fun onDozeAmountChanged(linear: Float, eased: Float) { wakeAndUnlockBlurRadius = blurUtils.blurRadiusOfRatio(eased) - scheduleUpdate() } } @@ -439,12 +436,11 @@ class NotificationShadeDepthController @Inject constructor( shadeAnimation.animateTo(blurUtils.blurRadiusOfRatio(targetBlurNormalized).toInt()) } - private fun scheduleUpdate(viewToBlur: View? = null) { + private fun scheduleUpdate() { if (updateScheduled) { return } updateScheduled = true - blurRoot = viewToBlur choreographer.postFrameCallback(updateBlurCallback) } @@ -495,16 +491,11 @@ class NotificationShadeDepthController @Inject constructor( */ private var pendingRadius = -1 - /** - * View on {@link Surface} that wants depth. - */ - private var view: View? = null - private var springAnimation = SpringAnimation(this, object : FloatPropertyCompat<DepthAnimation>("blurRadius") { override fun setValue(rect: DepthAnimation?, value: Float) { radius = value - scheduleUpdate(view) + scheduleUpdate() } override fun getValue(rect: DepthAnimation?): Float { @@ -519,11 +510,10 @@ class NotificationShadeDepthController @Inject constructor( springAnimation.addEndListener { _, _, _, _ -> pendingRadius = -1 } } - fun animateTo(newRadius: Int, viewToBlur: View? = null) { - if (pendingRadius == newRadius && view == viewToBlur) { + fun animateTo(newRadius: Int) { + if (pendingRadius == newRadius) { return } - view = viewToBlur pendingRadius = newRadius springAnimation.animateToFinalPosition(newRadius.toFloat()) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java index 4c0764ebd314..f37243adfa9e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java @@ -394,8 +394,6 @@ public interface CentralSurfaces extends Dumpable, ActivityStarter, LifecycleOwn void fadeKeyguardAfterLaunchTransition(Runnable beforeFading, Runnable endRunnable, Runnable cancelRunnable); - void fadeKeyguardWhilePulsing(); - void animateKeyguardUnoccluding(); void startLaunchTransitionTimeout(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java index 7158fd9455ce..cebb4b76cc59 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -3025,19 +3025,6 @@ public class CentralSurfacesImpl extends CoreStartable implements } /** - * Fades the content of the Keyguard while we are dozing and makes it invisible when finished - * fading. - */ - @Override - public void fadeKeyguardWhilePulsing() { - mNotificationPanelViewController.fadeOut(0, FADE_KEYGUARD_DURATION_PULSING, - ()-> { - hideKeyguard(); - mStatusBarKeyguardViewManager.onKeyguardFadedAway(); - }).start(); - } - - /** * Plays the animation when an activity that was occluding Keyguard goes away. */ @Override @@ -3326,14 +3313,12 @@ public class CentralSurfacesImpl extends CoreStartable implements // show the bouncer/lockscreen. if (!mKeyguardViewMediator.isHiding() && !mKeyguardUnlockAnimationController.isPlayingCannedUnlockAnimation()) { - if (mState == StatusBarState.SHADE_LOCKED - && mKeyguardUpdateMonitor.isUdfpsEnrolled()) { + if (mState == StatusBarState.SHADE_LOCKED) { // shade is showing while locked on the keyguard, so go back to showing the // lock screen where users can use the UDFPS affordance to enter the device mStatusBarKeyguardViewManager.reset(true); - } else if ((mState == StatusBarState.KEYGUARD - && !mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()) - || mState == StatusBarState.SHADE_LOCKED) { + } else if (mState == StatusBarState.KEYGUARD + && !mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()) { mStatusBarKeyguardViewManager.showGenericBouncer(true /* scrimmed */); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java index 0603281fd149..24ce5e98bdd0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java @@ -209,12 +209,8 @@ public final class DozeServiceHost implements DozeHost { void updateDozing() { Assert.isMainThread(); - // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked. - boolean - dozing = - mDozingRequested && mStatusBarStateController.getState() == StatusBarState.KEYGUARD - || mBiometricUnlockControllerLazy.get().getMode() - == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING; + boolean dozing = + mDozingRequested && mStatusBarStateController.getState() == StatusBarState.KEYGUARD; // When in wake-and-unlock we may not have received a change to StatusBarState // but we still should not be dozing, manually set to false. if (mBiometricUnlockControllerLazy.get().getMode() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index c0c385b6251e..4c5c23cd3b2f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -378,11 +378,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb return; } else if (mNotificationPanelViewController.isUnlockHintRunning()) { mBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN); - } else if (mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED - && mKeyguardUpdateManager.isUdfpsEnrolled()) { + } else if (mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED) { // Don't expand to the bouncer. Instead transition back to the lock screen (see - // CentralSurfaces#showBouncerOrLockScreenIfKeyguard) where the user can use the UDFPS - // affordance to enter the device (or swipe up to the input bouncer) + // CentralSurfaces#showBouncerOrLockScreenIfKeyguard) return; } else if (bouncerNeedsScrimming()) { mBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE); @@ -838,30 +836,24 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb }); } else { executeAfterKeyguardGoneAction(); - boolean wakeUnlockPulsing = - mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK_PULSING; mCentralSurfaces.setKeyguardFadingAway(startTime, delay, fadeoutDuration); mBiometricUnlockController.startKeyguardFadingAway(); hideBouncer(true /* destroyView */); - if (wakeUnlockPulsing) { - mCentralSurfaces.fadeKeyguardWhilePulsing(); + + boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide(); + if (!staying) { + mNotificationShadeWindowController.setKeyguardFadingAway(true); + mCentralSurfaces.hideKeyguard(); + // hide() will happen asynchronously and might arrive after the scrims + // were already hidden, this means that the transition callback won't + // be triggered anymore and StatusBarWindowController will be forever in + // the fadingAway state. + mCentralSurfaces.updateScrimController(); wakeAndUnlockDejank(); } else { - boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide(); - if (!staying) { - mNotificationShadeWindowController.setKeyguardFadingAway(true); - mCentralSurfaces.hideKeyguard(); - // hide() will happen asynchronously and might arrive after the scrims - // were already hidden, this means that the transition callback won't - // be triggered anymore and StatusBarWindowController will be forever in - // the fadingAway state. - mCentralSurfaces.updateScrimController(); - wakeAndUnlockDejank(); - } else { - mCentralSurfaces.hideKeyguard(); - mCentralSurfaces.finishKeyguardFadingAway(); - mBiometricUnlockController.finishKeyguardFadingAway(); - } + mCentralSurfaces.hideKeyguard(); + mCentralSurfaces.finishKeyguardFadingAway(); + mBiometricUnlockController.finishKeyguardFadingAway(); } updateStates(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java index bdac88837969..f4d08e01d5c3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java @@ -31,6 +31,7 @@ import androidx.annotation.VisibleForTesting; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; +import com.android.keyguard.logging.KeyguardUpdateMonitorLogger; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.dagger.SysUISingleton; @@ -60,6 +61,7 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback = new UpdateMonitorCallback(); private final Lazy<KeyguardUnlockAnimationController> mUnlockAnimationControllerLazy; + private final KeyguardUpdateMonitorLogger mLogger; private boolean mCanDismissLockScreen; private boolean mShowing; @@ -107,8 +109,10 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum KeyguardUpdateMonitor keyguardUpdateMonitor, LockPatternUtils lockPatternUtils, Lazy<KeyguardUnlockAnimationController> keyguardUnlockAnimationController, + KeyguardUpdateMonitorLogger logger, DumpManager dumpManager) { mContext = context; + mLogger = logger; mKeyguardUpdateMonitor = keyguardUpdateMonitor; mLockPatternUtils = lockPatternUtils; mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback); @@ -245,6 +249,8 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum mTrusted = trusted; mTrustManaged = trustManaged; mFaceAuthEnabled = faceAuthEnabled; + mLogger.logKeyguardStateUpdate( + mSecure, mCanDismissLockScreen, mTrusted, mTrustManaged); notifyUnlockedChanged(); } Trace.endSection(); diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt index 3a0ac1b7d9b0..734eeecec215 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt +++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.media.taptotransfer.common +package com.android.systemui.temporarydisplay import android.annotation.LayoutRes import android.annotation.SuppressLint @@ -37,30 +37,30 @@ import com.android.internal.widget.CachingIconView import com.android.settingslib.Utils import com.android.systemui.R import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.media.taptotransfer.common.MediaTttLogger import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.concurrency.DelayableExecutor -import com.android.systemui.util.view.ViewUtil /** - * A superclass controller that provides common functionality for showing chips on the sender device - * and the receiver device. + * A generic controller that can temporarily display a new view in a new window. * - * Subclasses need to override and implement [updateChipView], which is where they can control what + * Subclasses need to override and implement [updateView], which is where they can control what * gets displayed to the user. * * The generic type T is expected to contain all the information necessary for the subclasses to - * display the chip in a certain state, since they receive <T> in [updateChipView]. + * display the view in a certain state, since they receive <T> in [updateView]. + * + * TODO(b/245610654): Remove all the media-specific logic from this class. */ -abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( - internal val context: Context, - internal val logger: MediaTttLogger, - internal val windowManager: WindowManager, - private val viewUtil: ViewUtil, - @Main private val mainExecutor: DelayableExecutor, - private val accessibilityManager: AccessibilityManager, - private val configurationController: ConfigurationController, - private val powerManager: PowerManager, - @LayoutRes private val chipLayoutRes: Int, +abstract class TemporaryViewDisplayController<T : TemporaryViewInfo>( + internal val context: Context, + internal val logger: MediaTttLogger, + internal val windowManager: WindowManager, + @Main private val mainExecutor: DelayableExecutor, + private val accessibilityManager: AccessibilityManager, + private val configurationController: ConfigurationController, + private val powerManager: PowerManager, + @LayoutRes private val viewLayoutRes: Int, ) { /** * Window layout params that will be used as a starting point for the [windowLayoutParams] of @@ -85,31 +85,31 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( */ internal abstract val windowLayoutParams: WindowManager.LayoutParams - /** The chip view currently being displayed. Null if the chip is not being displayed. */ - private var chipView: ViewGroup? = null + /** The view currently being displayed. Null if the view is not being displayed. */ + private var view: ViewGroup? = null - /** The chip info currently being displayed. Null if the chip is not being displayed. */ - internal var chipInfo: T? = null + /** The info currently being displayed. Null if the view is not being displayed. */ + internal var info: T? = null - /** A [Runnable] that, when run, will cancel the pending timeout of the chip. */ - private var cancelChipViewTimeout: Runnable? = null + /** A [Runnable] that, when run, will cancel the pending timeout of the view. */ + private var cancelViewTimeout: Runnable? = null /** - * Displays the chip with the provided [newChipInfo]. + * Displays the view with the provided [newInfo]. * - * This method handles inflating and attaching the view, then delegates to [updateChipView] to - * display the correct information in the chip. + * This method handles inflating and attaching the view, then delegates to [updateView] to + * display the correct information in the view. */ - fun displayChip(newChipInfo: T) { - val currentChipView = chipView + fun displayView(newInfo: T) { + val currentView = view - if (currentChipView != null) { - updateChipView(newChipInfo, currentChipView) + if (currentView != null) { + updateView(newInfo, currentView) } else { - // The chip is new, so set up all our callbacks and inflate the view + // The view is new, so set up all our callbacks and inflate the view configurationController.addCallback(displayScaleListener) - // Wake the screen if necessary so the user will see the chip. (Per b/239426653, we want - // the chip to show over the dream state, so we should only wake up if the screen is + // Wake the screen if necessary so the user will see the view. (Per b/239426653, we want + // the view to show over the dream state, so we should only wake up if the screen is // completely off.) if (!powerManager.isScreenOn) { powerManager.wakeUp( @@ -119,79 +119,79 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( ) } - inflateAndUpdateChip(newChipInfo) + inflateAndUpdateView(newInfo) } - // Cancel and re-set the chip timeout each time we get a new state. + // Cancel and re-set the view timeout each time we get a new state. val timeout = accessibilityManager.getRecommendedTimeoutMillis( - newChipInfo.getTimeoutMs().toInt(), - // Not all chips have controls so FLAG_CONTENT_CONTROLS might be superfluous, but + newInfo.getTimeoutMs().toInt(), + // Not all views have controls so FLAG_CONTENT_CONTROLS might be superfluous, but // include it just to be safe. FLAG_CONTENT_ICONS or FLAG_CONTENT_TEXT or FLAG_CONTENT_CONTROLS ) - cancelChipViewTimeout?.run() - cancelChipViewTimeout = mainExecutor.executeDelayed( - { removeChip(MediaTttRemovalReason.REASON_TIMEOUT) }, + cancelViewTimeout?.run() + cancelViewTimeout = mainExecutor.executeDelayed( + { removeView(TemporaryDisplayRemovalReason.REASON_TIMEOUT) }, timeout.toLong() ) } - /** Inflates a new chip view, updates it with [newChipInfo], and adds the view to the window. */ - private fun inflateAndUpdateChip(newChipInfo: T) { - val newChipView = LayoutInflater + /** Inflates a new view, updates it with [newInfo], and adds the view to the window. */ + private fun inflateAndUpdateView(newInfo: T) { + val newView = LayoutInflater .from(context) - .inflate(chipLayoutRes, null) as ViewGroup - chipView = newChipView - updateChipView(newChipInfo, newChipView) - windowManager.addView(newChipView, windowLayoutParams) - animateChipIn(newChipView) + .inflate(viewLayoutRes, null) as ViewGroup + view = newView + updateView(newInfo, newView) + windowManager.addView(newView, windowLayoutParams) + animateViewIn(newView) } - /** Removes then re-inflates the chip. */ - private fun reinflateChip() { - val currentChipInfo = chipInfo - if (chipView == null || currentChipInfo == null) { return } + /** Removes then re-inflates the view. */ + private fun reinflateView() { + val currentInfo = info + if (view == null || currentInfo == null) { return } - windowManager.removeView(chipView) - inflateAndUpdateChip(currentChipInfo) + windowManager.removeView(view) + inflateAndUpdateView(currentInfo) } private val displayScaleListener = object : ConfigurationController.ConfigurationListener { override fun onDensityOrFontScaleChanged() { - reinflateChip() + reinflateView() } } /** - * Hides the chip. + * Hides the view. * - * @param removalReason a short string describing why the chip was removed (timeout, state + * @param removalReason a short string describing why the view was removed (timeout, state * change, etc.) */ - open fun removeChip(removalReason: String) { - if (chipView == null) { return } + open fun removeView(removalReason: String) { + if (view == null) { return } logger.logChipRemoval(removalReason) configurationController.removeCallback(displayScaleListener) - windowManager.removeView(chipView) - chipView = null - chipInfo = null - // No need to time the chip out since it's already gone - cancelChipViewTimeout?.run() + windowManager.removeView(view) + view = null + info = null + // No need to time the view out since it's already gone + cancelViewTimeout?.run() } /** - * A method implemented by subclasses to update [currentChipView] based on [newChipInfo]. + * A method implemented by subclasses to update [currentView] based on [newInfo]. */ @CallSuper - open fun updateChipView(newChipInfo: T, currentChipView: ViewGroup) { - chipInfo = newChipInfo + open fun updateView(newInfo: T, currentView: ViewGroup) { + info = newInfo } /** - * A method that can be implemented by subclcasses to do custom animations for when the chip + * A method that can be implemented by subclasses to do custom animations for when the view * appears. */ - open fun animateChipIn(chipView: ViewGroup) {} + open fun animateViewIn(view: ViewGroup) {} /** * Returns the size that the icon should be, or null if no size override is needed. @@ -209,12 +209,12 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( * @return the content description of the icon. */ internal fun setIcon( - currentChipView: ViewGroup, + currentView: ViewGroup, appPackageName: String?, appIconDrawableOverride: Drawable? = null, appNameOverride: CharSequence? = null, ): CharSequence { - val appIconView = currentChipView.requireViewById<CachingIconView>(R.id.app_icon) + val appIconView = currentView.requireViewById<CachingIconView>(R.id.app_icon) val iconInfo = getIconInfo(appPackageName) getIconSize(iconInfo.isAppIcon)?.let { size -> @@ -264,9 +264,9 @@ abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( // Used in CTS tests UpdateMediaTapToTransferSenderDisplayTest and // UpdateMediaTapToTransferReceiverDisplayTest private const val WINDOW_TITLE = "Media Transfer Chip View" -private val TAG = MediaTttChipControllerCommon::class.simpleName!! +private val TAG = TemporaryViewDisplayController::class.simpleName!! -object MediaTttRemovalReason { +object TemporaryDisplayRemovalReason { const val REASON_TIMEOUT = "TIMEOUT" const val REASON_SCREEN_TAP = "SCREEN_TAP" } diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/ChipInfoCommon.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt index a29c5883118c..4fe753a80faf 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/ChipInfoCommon.kt +++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt @@ -14,17 +14,17 @@ * limitations under the License. */ -package com.android.systemui.media.taptotransfer.common +package com.android.systemui.temporarydisplay /** - * A superclass chip state that will be subclassed by the sender chip and receiver chip. + * A superclass view state used with [TemporaryViewDisplayController]. */ -interface ChipInfoCommon { +interface TemporaryViewInfo { /** - * Returns the amount of time the given chip state should display on the screen before it times + * Returns the amount of time the given view state should display on the screen before it times * out and disappears. */ - fun getTimeoutMs(): Long + fun getTimeoutMs(): Long = DEFAULT_TIMEOUT_MILLIS } const val DEFAULT_TIMEOUT_MILLIS = 10000L diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt index 9acd21cc6398..9a91ea91f3a2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt @@ -51,18 +51,19 @@ class HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest : SysuiTes @Parameters( name = "feature enabled = {0}, has favorites = {1}, has service infos = {2}, can show" + - " while locked = {3} - expected visible = {4}" + " while locked = {3}, visibility is AVAILABLE {4} - expected visible = {5}" ) @JvmStatic fun data() = - (0 until 16) + (0 until 32) .map { combination -> arrayOf( - /* isFeatureEnabled= */ combination and 0b1000 != 0, - /* hasFavorites= */ combination and 0b0100 != 0, - /* hasServiceInfos= */ combination and 0b0010 != 0, - /* canShowWhileLocked= */ combination and 0b0001 != 0, - /* isVisible= */ combination == 0b1111, + /* isFeatureEnabled= */ combination and 0b10000 != 0, + /* hasFavorites= */ combination and 0b01000 != 0, + /* hasServiceInfos= */ combination and 0b00100 != 0, + /* canShowWhileLocked= */ combination and 0b00010 != 0, + /* visibilityAvailable= */ combination and 0b00001 != 0, + /* isVisible= */ combination == 0b11111, ) } .toList() @@ -81,7 +82,8 @@ class HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest : SysuiTes @JvmField @Parameter(1) var hasFavorites: Boolean = false @JvmField @Parameter(2) var hasServiceInfos: Boolean = false @JvmField @Parameter(3) var canShowWhileLocked: Boolean = false - @JvmField @Parameter(4) var isVisible: Boolean = false + @JvmField @Parameter(4) var isVisibilityAvailable: Boolean = false + @JvmField @Parameter(5) var isVisibleExpected: Boolean = false @Before fun setUp() { @@ -93,6 +95,14 @@ class HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest : SysuiTes .thenReturn(Optional.of(controlsListingController)) whenever(component.canShowWhileLockedSetting) .thenReturn(MutableStateFlow(canShowWhileLocked)) + whenever(component.getVisibility()) + .thenReturn( + if (isVisibilityAvailable) { + ControlsComponent.Visibility.AVAILABLE + } else { + ControlsComponent.Visibility.UNAVAILABLE + } + ) underTest = HomeControlsKeyguardQuickAffordanceConfig( @@ -128,7 +138,7 @@ class HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest : SysuiTes assertThat(values.last()) .isInstanceOf( - if (isVisible) { + if (isVisibleExpected) { KeyguardQuickAffordanceConfig.State.Visible::class.java } else { KeyguardQuickAffordanceConfig.State.Hidden::class.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt index 059487dfdbc8..dede4ec0210c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt @@ -69,6 +69,7 @@ class HomeControlsKeyguardQuickAffordanceConfigTest : SysuiTestCase() { val controlsController = mock<ControlsController>() whenever(component.getControlsController()).thenReturn(Optional.of(controlsController)) whenever(component.getControlsListingController()).thenReturn(Optional.empty()) + whenever(component.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE) whenever(controlsController.getFavorites()).thenReturn(listOf(mock())) val values = mutableListOf<KeyguardQuickAffordanceConfig.State>() @@ -87,6 +88,7 @@ class HomeControlsKeyguardQuickAffordanceConfigTest : SysuiTestCase() { val controlsController = mock<ControlsController>() whenever(component.getControlsController()).thenReturn(Optional.of(controlsController)) whenever(component.getControlsListingController()).thenReturn(Optional.empty()) + whenever(component.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE) whenever(controlsController.getFavorites()).thenReturn(listOf(mock())) val values = mutableListOf<KeyguardQuickAffordanceConfig.State>() diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt index 171d893640d6..e7b4593b0ebb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt @@ -41,7 +41,6 @@ import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq import com.android.systemui.util.time.FakeSystemClock -import com.android.systemui.util.view.ViewUtil import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test @@ -74,8 +73,6 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { @Mock private lateinit var windowManager: WindowManager @Mock - private lateinit var viewUtil: ViewUtil - @Mock private lateinit var commandQueue: CommandQueue private lateinit var commandQueueCallback: CommandQueue.Callbacks private lateinit var fakeAppIconDrawable: Drawable @@ -102,7 +99,6 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { context, logger, windowManager, - viewUtil, FakeExecutor(FakeSystemClock()), accessibilityManager, configurationController, @@ -182,7 +178,7 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { @Test fun setIcon_isAppIcon_usesAppIconSize() { - controllerReceiver.displayChip(getChipReceiverInfo()) + controllerReceiver.displayView(getChipReceiverInfo()) val chipView = getChipView() controllerReceiver.setIcon(chipView, PACKAGE_NAME) @@ -198,7 +194,7 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { @Test fun setIcon_notAppIcon_usesGenericIconSize() { - controllerReceiver.displayChip(getChipReceiverInfo()) + controllerReceiver.displayView(getChipReceiverInfo()) val chipView = getChipView() controllerReceiver.setIcon(chipView, appPackageName = null) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt index 1061e3c6b0d5..52b6eed9a14d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt @@ -42,7 +42,6 @@ import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq import com.android.systemui.util.time.FakeSystemClock -import com.android.systemui.util.view.ViewUtil import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test @@ -51,8 +50,8 @@ import org.mockito.ArgumentCaptor import org.mockito.Mock import org.mockito.Mockito.never import org.mockito.Mockito.verify -import org.mockito.MockitoAnnotations import org.mockito.Mockito.`when` as whenever +import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidTestingRunner::class) @@ -75,8 +74,6 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Mock private lateinit var windowManager: WindowManager @Mock - private lateinit var viewUtil: ViewUtil - @Mock private lateinit var commandQueue: CommandQueue private lateinit var commandQueueCallback: CommandQueue.Callbacks private lateinit var fakeAppIconDrawable: Drawable @@ -110,7 +107,6 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { context, logger, windowManager, - viewUtil, fakeExecutor, accessibilityManager, configurationController, @@ -309,7 +305,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun almostCloseToStartCast_appIcon_deviceName_noLoadingIcon_noUndo_noFailureIcon() { val state = almostCloseToStartCast() - controllerSender.displayChip(state) + controllerSender.displayView(state) val chipView = getChipView() assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable) @@ -325,7 +321,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun almostCloseToEndCast_appIcon_deviceName_noLoadingIcon_noUndo_noFailureIcon() { val state = almostCloseToEndCast() - controllerSender.displayChip(state) + controllerSender.displayView(state) val chipView = getChipView() assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable) @@ -341,7 +337,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun transferToReceiverTriggered_appIcon_loadingIcon_noUndo_noFailureIcon() { val state = transferToReceiverTriggered() - controllerSender.displayChip(state) + controllerSender.displayView(state) val chipView = getChipView() assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable) @@ -357,7 +353,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun transferToThisDeviceTriggered_appIcon_loadingIcon_noUndo_noFailureIcon() { val state = transferToThisDeviceTriggered() - controllerSender.displayChip(state) + controllerSender.displayView(state) val chipView = getChipView() assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable) @@ -373,7 +369,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun transferToReceiverSucceeded_appIcon_deviceName_noLoadingIcon_noFailureIcon() { val state = transferToReceiverSucceeded() - controllerSender.displayChip(state) + controllerSender.displayView(state) val chipView = getChipView() assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable) @@ -387,7 +383,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun transferToReceiverSucceeded_nullUndoRunnable_noUndo() { - controllerSender.displayChip(transferToReceiverSucceeded(undoCallback = null)) + controllerSender.displayView(transferToReceiverSucceeded(undoCallback = null)) val chipView = getChipView() assertThat(chipView.getUndoButton().visibility).isEqualTo(View.GONE) @@ -398,7 +394,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { val undoCallback = object : IUndoMediaTransferCallback.Stub() { override fun onUndoTriggered() {} } - controllerSender.displayChip(transferToReceiverSucceeded(undoCallback)) + controllerSender.displayView(transferToReceiverSucceeded(undoCallback)) val chipView = getChipView() assertThat(chipView.getUndoButton().visibility).isEqualTo(View.VISIBLE) @@ -414,7 +410,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { } } - controllerSender.displayChip(transferToReceiverSucceeded(undoCallback)) + controllerSender.displayView(transferToReceiverSucceeded(undoCallback)) getChipView().getUndoButton().performClick() assertThat(undoCallbackCalled).isTrue() @@ -425,7 +421,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { val undoCallback = object : IUndoMediaTransferCallback.Stub() { override fun onUndoTriggered() {} } - controllerSender.displayChip(transferToReceiverSucceeded(undoCallback)) + controllerSender.displayView(transferToReceiverSucceeded(undoCallback)) getChipView().getUndoButton().performClick() @@ -440,7 +436,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun transferToThisDeviceSucceeded_appIcon_deviceName_noLoadingIcon_noFailureIcon() { val state = transferToThisDeviceSucceeded() - controllerSender.displayChip(state) + controllerSender.displayView(state) val chipView = getChipView() assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable) @@ -454,7 +450,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun transferToThisDeviceSucceeded_nullUndoRunnable_noUndo() { - controllerSender.displayChip(transferToThisDeviceSucceeded(undoCallback = null)) + controllerSender.displayView(transferToThisDeviceSucceeded(undoCallback = null)) val chipView = getChipView() assertThat(chipView.getUndoButton().visibility).isEqualTo(View.GONE) @@ -465,7 +461,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { val undoCallback = object : IUndoMediaTransferCallback.Stub() { override fun onUndoTriggered() {} } - controllerSender.displayChip(transferToThisDeviceSucceeded(undoCallback)) + controllerSender.displayView(transferToThisDeviceSucceeded(undoCallback)) val chipView = getChipView() assertThat(chipView.getUndoButton().visibility).isEqualTo(View.VISIBLE) @@ -481,7 +477,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { } } - controllerSender.displayChip(transferToThisDeviceSucceeded(undoCallback)) + controllerSender.displayView(transferToThisDeviceSucceeded(undoCallback)) getChipView().getUndoButton().performClick() assertThat(undoCallbackCalled).isTrue() @@ -492,7 +488,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { val undoCallback = object : IUndoMediaTransferCallback.Stub() { override fun onUndoTriggered() {} } - controllerSender.displayChip(transferToThisDeviceSucceeded(undoCallback)) + controllerSender.displayView(transferToThisDeviceSucceeded(undoCallback)) getChipView().getUndoButton().performClick() @@ -507,7 +503,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun transferToReceiverFailed_appIcon_noDeviceName_noLoadingIcon_noUndo_failureIcon() { val state = transferToReceiverFailed() - controllerSender.displayChip(state) + controllerSender.displayView(state) val chipView = getChipView() assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable) @@ -523,7 +519,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun transferToThisDeviceFailed_appIcon_noDeviceName_noLoadingIcon_noUndo_failureIcon() { val state = transferToThisDeviceFailed() - controllerSender.displayChip(state) + controllerSender.displayView(state) val chipView = getChipView() assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable) @@ -538,24 +534,24 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun changeFromAlmostCloseToStartToTransferTriggered_loadingIconAppears() { - controllerSender.displayChip(almostCloseToStartCast()) - controllerSender.displayChip(transferToReceiverTriggered()) + controllerSender.displayView(almostCloseToStartCast()) + controllerSender.displayView(transferToReceiverTriggered()) assertThat(getChipView().getLoadingIconVisibility()).isEqualTo(View.VISIBLE) } @Test fun changeFromTransferTriggeredToTransferSucceeded_loadingIconDisappears() { - controllerSender.displayChip(transferToReceiverTriggered()) - controllerSender.displayChip(transferToReceiverSucceeded()) + controllerSender.displayView(transferToReceiverTriggered()) + controllerSender.displayView(transferToReceiverSucceeded()) assertThat(getChipView().getLoadingIconVisibility()).isEqualTo(View.GONE) } @Test fun changeFromTransferTriggeredToTransferSucceeded_undoButtonAppears() { - controllerSender.displayChip(transferToReceiverTriggered()) - controllerSender.displayChip( + controllerSender.displayView(transferToReceiverTriggered()) + controllerSender.displayView( transferToReceiverSucceeded( object : IUndoMediaTransferCallback.Stub() { override fun onUndoTriggered() {} @@ -568,26 +564,26 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun changeFromTransferSucceededToAlmostCloseToStart_undoButtonDisappears() { - controllerSender.displayChip(transferToReceiverSucceeded()) - controllerSender.displayChip(almostCloseToStartCast()) + controllerSender.displayView(transferToReceiverSucceeded()) + controllerSender.displayView(almostCloseToStartCast()) assertThat(getChipView().getUndoButton().visibility).isEqualTo(View.GONE) } @Test fun changeFromTransferTriggeredToTransferFailed_failureIconAppears() { - controllerSender.displayChip(transferToReceiverTriggered()) - controllerSender.displayChip(transferToReceiverFailed()) + controllerSender.displayView(transferToReceiverTriggered()) + controllerSender.displayView(transferToReceiverFailed()) assertThat(getChipView().getFailureIcon().visibility).isEqualTo(View.VISIBLE) } @Test - fun transferToReceiverTriggeredThenRemoveChip_chipStillDisplayed() { - controllerSender.displayChip(transferToReceiverTriggered()) + fun transferToReceiverTriggeredThenRemoveView_viewStillDisplayed() { + controllerSender.displayView(transferToReceiverTriggered()) fakeClock.advanceTime(1000L) - controllerSender.removeChip("fakeRemovalReason") + controllerSender.removeView("fakeRemovalReason") fakeExecutor.runAllReady() verify(windowManager, never()).removeView(any()) @@ -596,9 +592,9 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun transferToReceiverTriggeredThenFarFromReceiver_eventuallyTimesOut() { val state = transferToReceiverTriggered() - controllerSender.displayChip(state) + controllerSender.displayView(state) fakeClock.advanceTime(1000L) - controllerSender.removeChip("fakeRemovalReason") + controllerSender.removeView("fakeRemovalReason") fakeClock.advanceTime(TIMEOUT + 1L) @@ -606,11 +602,11 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { } @Test - fun transferToThisDeviceTriggeredThenRemoveChip_chipStillDisplayed() { - controllerSender.displayChip(transferToThisDeviceTriggered()) + fun transferToThisDeviceTriggeredThenRemoveView_viewStillDisplayed() { + controllerSender.displayView(transferToThisDeviceTriggered()) fakeClock.advanceTime(1000L) - controllerSender.removeChip("fakeRemovalReason") + controllerSender.removeView("fakeRemovalReason") fakeExecutor.runAllReady() verify(windowManager, never()).removeView(any()) @@ -619,9 +615,9 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun transferToThisDeviceTriggeredThenFarFromReceiver_eventuallyTimesOut() { val state = transferToThisDeviceTriggered() - controllerSender.displayChip(state) + controllerSender.displayView(state) fakeClock.advanceTime(1000L) - controllerSender.removeChip("fakeRemovalReason") + controllerSender.removeView("fakeRemovalReason") fakeClock.advanceTime(TIMEOUT + 1L) diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt index d2970a63a860..97c0bb2c09ca 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt @@ -27,6 +27,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.dock.DockManager import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.FalsingManager +import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.phone.CentralSurfaces import com.android.systemui.tuner.TunerService import com.android.systemui.tuner.TunerService.Tunable @@ -63,6 +64,8 @@ class PulsingGestureListenerTest : SysuiTestCase() { private lateinit var tunerService: TunerService @Mock private lateinit var dumpManager: DumpManager + @Mock + private lateinit var statusBarStateController: StatusBarStateController private lateinit var tunableCaptor: ArgumentCaptor<Tunable> private lateinit var underTest: PulsingGestureListener @@ -77,6 +80,7 @@ class PulsingGestureListenerTest : SysuiTestCase() { dockManager, centralSurfaces, ambientDisplayConfiguration, + statusBarStateController, tunerService, dumpManager ) @@ -85,6 +89,8 @@ class PulsingGestureListenerTest : SysuiTestCase() { @Test fun testGestureDetector_singleTapEnabled() { + whenever(statusBarStateController.isPulsing).thenReturn(true) + // GIVEN tap is enabled, prox not covered whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true) updateSettings() @@ -102,6 +108,8 @@ class PulsingGestureListenerTest : SysuiTestCase() { @Test fun testGestureDetector_doubleTapEnabled() { + whenever(statusBarStateController.isPulsing).thenReturn(true) + // GIVEN double tap is enabled, prox not covered whenever(ambientDisplayConfiguration.doubleTapGestureEnabled(anyInt())).thenReturn(true) updateSettings() @@ -119,6 +127,8 @@ class PulsingGestureListenerTest : SysuiTestCase() { @Test fun testGestureDetector_singleTapEnabled_falsing() { + whenever(statusBarStateController.isPulsing).thenReturn(true) + // GIVEN tap is enabled, prox not covered whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true) updateSettings() @@ -135,7 +145,23 @@ class PulsingGestureListenerTest : SysuiTestCase() { } @Test + fun testGestureDetector_notPulsing_noFalsingCheck() { + whenever(statusBarStateController.isPulsing).thenReturn(false) + + // GIVEN tap is enabled, prox not covered + whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true) + // WHEN there's a tap + underTest.onSingleTapConfirmed(downEv) + + // THEN the falsing manager never gets a call (because the device wasn't pulsing + // during the tap) + verify(falsingManager, never()).isFalseTap(anyInt()) + } + + @Test fun testGestureDetector_doubleTapEnabled_falsing() { + whenever(statusBarStateController.isPulsing).thenReturn(true) + // GIVEN double tap is enabled, prox not covered whenever(ambientDisplayConfiguration.doubleTapGestureEnabled(anyInt())).thenReturn(true) updateSettings() @@ -153,6 +179,8 @@ class PulsingGestureListenerTest : SysuiTestCase() { @Test fun testGestureDetector_singleTapEnabled_proxCovered() { + whenever(statusBarStateController.isPulsing).thenReturn(true) + // GIVEN tap is enabled, not a false tap based on classifiers whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true) updateSettings() @@ -170,6 +198,8 @@ class PulsingGestureListenerTest : SysuiTestCase() { @Test fun testGestureDetector_doubleTapEnabled_proxCovered() { + whenever(statusBarStateController.isPulsing).thenReturn(true) + // GIVEN double tap is enabled, not a false tap based on classifiers whenever(ambientDisplayConfiguration.doubleTapGestureEnabled(anyInt())).thenReturn(true) updateSettings() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt index b166b7367b53..6446fb5d8c81 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt @@ -48,7 +48,6 @@ import org.mockito.ArgumentMatchers.floatThat import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito -import org.mockito.Mockito.`when` import org.mockito.Mockito.any import org.mockito.Mockito.anyFloat import org.mockito.Mockito.anyString @@ -56,6 +55,7 @@ import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` import org.mockito.junit.MockitoJUnit @RunWith(AndroidTestingRunner::class) @@ -139,7 +139,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { notificationShadeDepthController.onPanelExpansionChanged( PanelExpansionChangeEvent( fraction = 1f, expanded = true, tracking = false, dragDownPxAmount = 0f)) - verify(shadeAnimation).animateTo(eq(maxBlur), any()) + verify(shadeAnimation).animateTo(eq(maxBlur)) } @Test @@ -147,7 +147,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { notificationShadeDepthController.onPanelExpansionChanged( PanelExpansionChangeEvent( fraction = 0.01f, expanded = false, tracking = false, dragDownPxAmount = 0f)) - verify(shadeAnimation).animateTo(eq(maxBlur), any()) + verify(shadeAnimation).animateTo(eq(maxBlur)) } @Test @@ -157,7 +157,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { notificationShadeDepthController.onPanelExpansionChanged( PanelExpansionChangeEvent( fraction = 0f, expanded = false, tracking = false, dragDownPxAmount = 0f)) - verify(shadeAnimation).animateTo(eq(0), any()) + verify(shadeAnimation).animateTo(eq(0)) } @Test @@ -168,15 +168,15 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { onPanelExpansionChanged_apliesBlur_ifShade() clearInvocations(shadeAnimation) notificationShadeDepthController.onPanelExpansionChanged(event) - verify(shadeAnimation, never()).animateTo(anyInt(), any()) + verify(shadeAnimation, never()).animateTo(anyInt()) notificationShadeDepthController.onPanelExpansionChanged( event.copy(fraction = 0.9f, tracking = true)) - verify(shadeAnimation, never()).animateTo(anyInt(), any()) + verify(shadeAnimation, never()).animateTo(anyInt()) notificationShadeDepthController.onPanelExpansionChanged( event.copy(fraction = 0.8f, tracking = false)) - verify(shadeAnimation).animateTo(eq(0), any()) + verify(shadeAnimation).animateTo(eq(0)) } @Test @@ -186,7 +186,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { notificationShadeDepthController.onPanelExpansionChanged( PanelExpansionChangeEvent( fraction = 0.6f, expanded = true, tracking = true, dragDownPxAmount = 0f)) - verify(shadeAnimation).animateTo(eq(maxBlur), any()) + verify(shadeAnimation).animateTo(eq(maxBlur)) } @Test @@ -212,7 +212,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { statusBarState = StatusBarState.KEYGUARD statusBarStateListener.onStateChanged(statusBarState) - verify(shadeAnimation).animateTo(eq(0), any()) + verify(shadeAnimation).animateTo(eq(0)) } @Test @@ -395,13 +395,13 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { @Test fun brightnessMirrorVisible_whenVisible() { notificationShadeDepthController.brightnessMirrorVisible = true - verify(brightnessSpring).animateTo(eq(maxBlur), any()) + verify(brightnessSpring).animateTo(eq(maxBlur)) } @Test fun brightnessMirrorVisible_whenHidden() { notificationShadeDepthController.brightnessMirrorVisible = false - verify(brightnessSpring).animateTo(eq(0), any()) + verify(brightnessSpring).animateTo(eq(0)) } @Test @@ -424,7 +424,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { fun ignoreShadeBlurUntilHidden_whennNull_ignoresIfShadeHasNoBlur() { `when`(shadeAnimation.radius).thenReturn(0f) notificationShadeDepthController.blursDisabledForAppLaunch = true - verify(shadeAnimation, never()).animateTo(anyInt(), any()) + verify(shadeAnimation, never()).animateTo(anyInt()) } private fun enableSplitShade() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java index 2dcdcfce56eb..e790d85763d0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java @@ -51,6 +51,7 @@ import com.android.systemui.shade.NotificationPanelViewController; import com.android.systemui.shade.ShadeController; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationShadeWindowController; +import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.phone.panelstate.PanelExpansionChangeEvent; import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; @@ -277,6 +278,17 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { } @Test + public void onPanelExpansionChanged_neverTranslatesBouncerWhenShadeLocked() { + when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE_LOCKED); + mStatusBarKeyguardViewManager.onPanelExpansionChanged( + expansionEvent( + /* fraction= */ KeyguardBouncer.EXPANSION_VISIBLE, + /* expanded= */ true, + /* tracking= */ false)); + verify(mBouncer, never()).setExpansion(anyFloat()); + } + + @Test public void setOccluded_animatesPanelExpansion_onlyIfBouncerHidden() { mStatusBarKeyguardViewManager.setOccluded(false /* occluded */, true /* animated */); verify(mCentralSurfaces).animateKeyguardUnoccluding(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java index 4a8170fc2955..8f363efd9f51 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java @@ -31,6 +31,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.keyguard.logging.KeyguardUpdateMonitorLogger; import com.android.systemui.SysuiTestCase; import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; @@ -57,6 +58,8 @@ public class KeyguardStateControllerTest extends SysuiTestCase { private DumpManager mDumpManager; @Mock private Lazy<KeyguardUnlockAnimationController> mKeyguardUnlockAnimationControllerLazy; + @Mock + private KeyguardUpdateMonitorLogger mLogger; @Before public void setup() { @@ -66,6 +69,7 @@ public class KeyguardStateControllerTest extends SysuiTestCase { mKeyguardUpdateMonitor, mLockPatternUtils, mKeyguardUnlockAnimationControllerLazy, + mLogger, mDumpManager); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt index f1330682b0e1..e616c26377d2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.media.taptotransfer.common +package com.android.systemui.temporarydisplay import android.content.Context import android.content.pm.ApplicationInfo @@ -30,6 +30,7 @@ import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.media.taptotransfer.common.MediaTttLogger import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener import com.android.systemui.util.concurrency.DelayableExecutor @@ -38,7 +39,6 @@ import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.capture import com.android.systemui.util.time.FakeSystemClock -import com.android.systemui.util.view.ViewUtil import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test @@ -52,8 +52,8 @@ import org.mockito.Mockito.`when` as whenever import org.mockito.MockitoAnnotations @SmallTest -class MediaTttChipControllerCommonTest : SysuiTestCase() { - private lateinit var controllerCommon: TestControllerCommon +class TemporaryViewDisplayControllerTest : SysuiTestCase() { + private lateinit var underTest: TestController private lateinit var fakeClock: FakeSystemClock private lateinit var fakeExecutor: FakeExecutor @@ -72,8 +72,6 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { @Mock private lateinit var windowManager: WindowManager @Mock - private lateinit var viewUtil: ViewUtil - @Mock private lateinit var powerManager: PowerManager @Before @@ -97,11 +95,10 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { fakeClock = FakeSystemClock() fakeExecutor = FakeExecutor(fakeClock) - controllerCommon = TestControllerCommon( + underTest = TestController( context, logger, windowManager, - viewUtil, fakeExecutor, accessibilityManager, configurationController, @@ -110,43 +107,43 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { } @Test - fun displayChip_chipAdded() { - controllerCommon.displayChip(getState()) + fun displayView_viewAdded() { + underTest.displayView(getState()) verify(windowManager).addView(any(), any()) } @Test - fun displayChip_screenOff_screenWakes() { + fun displayView_screenOff_screenWakes() { whenever(powerManager.isScreenOn).thenReturn(false) - controllerCommon.displayChip(getState()) + underTest.displayView(getState()) verify(powerManager).wakeUp(any(), any(), any()) } @Test - fun displayChip_screenAlreadyOn_screenNotWoken() { + fun displayView_screenAlreadyOn_screenNotWoken() { whenever(powerManager.isScreenOn).thenReturn(true) - controllerCommon.displayChip(getState()) + underTest.displayView(getState()) verify(powerManager, never()).wakeUp(any(), any(), any()) } @Test - fun displayChip_twice_chipNotAddedTwice() { - controllerCommon.displayChip(getState()) + fun displayView_twice_viewNotAddedTwice() { + underTest.displayView(getState()) reset(windowManager) - controllerCommon.displayChip(getState()) + underTest.displayView(getState()) verify(windowManager, never()).addView(any(), any()) } @Test - fun displayChip_chipDoesNotDisappearsBeforeTimeout() { + fun displayView_viewDoesNotDisappearsBeforeTimeout() { val state = getState() - controllerCommon.displayChip(state) + underTest.displayView(state) reset(windowManager) fakeClock.advanceTime(TIMEOUT_MS - 1) @@ -155,9 +152,9 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { } @Test - fun displayChip_chipDisappearsAfterTimeout() { + fun displayView_viewDisappearsAfterTimeout() { val state = getState() - controllerCommon.displayChip(state) + underTest.displayView(state) reset(windowManager) fakeClock.advanceTime(TIMEOUT_MS + 1) @@ -166,176 +163,176 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { } @Test - fun displayChip_calledAgainBeforeTimeout_timeoutReset() { - // First, display the chip + fun displayView_calledAgainBeforeTimeout_timeoutReset() { + // First, display the view val state = getState() - controllerCommon.displayChip(state) + underTest.displayView(state) - // After some time, re-display the chip + // After some time, re-display the view val waitTime = 1000L fakeClock.advanceTime(waitTime) - controllerCommon.displayChip(getState()) + underTest.displayView(getState()) // Wait until the timeout for the first display would've happened fakeClock.advanceTime(TIMEOUT_MS - waitTime + 1) - // Verify we didn't hide the chip + // Verify we didn't hide the view verify(windowManager, never()).removeView(any()) } @Test - fun displayChip_calledAgainBeforeTimeout_eventuallyTimesOut() { - // First, display the chip + fun displayView_calledAgainBeforeTimeout_eventuallyTimesOut() { + // First, display the view val state = getState() - controllerCommon.displayChip(state) + underTest.displayView(state) - // After some time, re-display the chip + // After some time, re-display the view fakeClock.advanceTime(1000L) - controllerCommon.displayChip(getState()) + underTest.displayView(getState()) - // Ensure we still hide the chip eventually + // Ensure we still hide the view eventually fakeClock.advanceTime(TIMEOUT_MS + 1) verify(windowManager).removeView(any()) } @Test - fun displayScaleChange_chipReinflatedWithMostRecentState() { - controllerCommon.displayChip(getState(name = "First name")) - controllerCommon.displayChip(getState(name = "Second name")) + fun displayScaleChange_viewReinflatedWithMostRecentState() { + underTest.displayView(getState(name = "First name")) + underTest.displayView(getState(name = "Second name")) reset(windowManager) getConfigurationListener().onDensityOrFontScaleChanged() verify(windowManager).removeView(any()) verify(windowManager).addView(any(), any()) - assertThat(controllerCommon.mostRecentChipInfo?.name).isEqualTo("Second name") + assertThat(underTest.mostRecentViewInfo?.name).isEqualTo("Second name") } @Test - fun removeChip_chipRemovedAndRemovalLogged() { - // First, add the chip - controllerCommon.displayChip(getState()) + fun removeView_viewRemovedAndRemovalLogged() { + // First, add the view + underTest.displayView(getState()) // Then, remove it val reason = "test reason" - controllerCommon.removeChip(reason) + underTest.removeView(reason) verify(windowManager).removeView(any()) verify(logger).logChipRemoval(reason) } @Test - fun removeChip_noAdd_viewNotRemoved() { - controllerCommon.removeChip("reason") + fun removeView_noAdd_viewNotRemoved() { + underTest.removeView("reason") verify(windowManager, never()).removeView(any()) } @Test fun setIcon_nullAppIconDrawableAndNullPackageName_stillHasIcon() { - controllerCommon.displayChip(getState()) - val chipView = getChipView() + underTest.displayView(getState()) + val view = getView() - controllerCommon.setIcon(chipView, appPackageName = null, appIconDrawableOverride = null) + underTest.setIcon(view, appPackageName = null, appIconDrawableOverride = null) - assertThat(chipView.getAppIconView().drawable).isNotNull() + assertThat(view.getAppIconView().drawable).isNotNull() } @Test fun setIcon_nullAppIconDrawableAndInvalidPackageName_stillHasIcon() { - controllerCommon.displayChip(getState()) - val chipView = getChipView() + underTest.displayView(getState()) + val view = getView() - controllerCommon.setIcon( - chipView, appPackageName = "fakePackageName", appIconDrawableOverride = null + underTest.setIcon( + view, appPackageName = "fakePackageName", appIconDrawableOverride = null ) - assertThat(chipView.getAppIconView().drawable).isNotNull() + assertThat(view.getAppIconView().drawable).isNotNull() } @Test fun setIcon_nullAppIconDrawable_iconIsFromPackageName() { - controllerCommon.displayChip(getState()) - val chipView = getChipView() + underTest.displayView(getState()) + val view = getView() - controllerCommon.setIcon(chipView, PACKAGE_NAME, appIconDrawableOverride = null, null) + underTest.setIcon(view, PACKAGE_NAME, appIconDrawableOverride = null, null) - assertThat(chipView.getAppIconView().drawable).isEqualTo(appIconFromPackageName) + assertThat(view.getAppIconView().drawable).isEqualTo(appIconFromPackageName) } @Test fun setIcon_hasAppIconDrawable_iconIsDrawable() { - controllerCommon.displayChip(getState()) - val chipView = getChipView() + underTest.displayView(getState()) + val view = getView() val drawable = context.getDrawable(R.drawable.ic_alarm)!! - controllerCommon.setIcon(chipView, PACKAGE_NAME, drawable, null) + underTest.setIcon(view, PACKAGE_NAME, drawable, null) - assertThat(chipView.getAppIconView().drawable).isEqualTo(drawable) + assertThat(view.getAppIconView().drawable).isEqualTo(drawable) } @Test fun setIcon_nullAppNameAndNullPackageName_stillHasContentDescription() { - controllerCommon.displayChip(getState()) - val chipView = getChipView() + underTest.displayView(getState()) + val view = getView() - controllerCommon.setIcon(chipView, appPackageName = null, appNameOverride = null) + underTest.setIcon(view, appPackageName = null, appNameOverride = null) - assertThat(chipView.getAppIconView().contentDescription.toString()).isNotEmpty() + assertThat(view.getAppIconView().contentDescription.toString()).isNotEmpty() } @Test fun setIcon_nullAppNameAndInvalidPackageName_stillHasContentDescription() { - controllerCommon.displayChip(getState()) - val chipView = getChipView() + underTest.displayView(getState()) + val view = getView() - controllerCommon.setIcon( - chipView, appPackageName = "fakePackageName", appNameOverride = null + underTest.setIcon( + view, appPackageName = "fakePackageName", appNameOverride = null ) - assertThat(chipView.getAppIconView().contentDescription.toString()).isNotEmpty() + assertThat(view.getAppIconView().contentDescription.toString()).isNotEmpty() } @Test fun setIcon_nullAppName_iconContentDescriptionIsFromPackageName() { - controllerCommon.displayChip(getState()) - val chipView = getChipView() + underTest.displayView(getState()) + val view = getView() - controllerCommon.setIcon(chipView, PACKAGE_NAME, null, appNameOverride = null) + underTest.setIcon(view, PACKAGE_NAME, null, appNameOverride = null) - assertThat(chipView.getAppIconView().contentDescription).isEqualTo(APP_NAME) + assertThat(view.getAppIconView().contentDescription).isEqualTo(APP_NAME) } @Test fun setIcon_hasAppName_iconContentDescriptionIsAppNameOverride() { - controllerCommon.displayChip(getState()) - val chipView = getChipView() + underTest.displayView(getState()) + val view = getView() val appName = "Override App Name" - controllerCommon.setIcon(chipView, PACKAGE_NAME, null, appName) + underTest.setIcon(view, PACKAGE_NAME, null, appName) - assertThat(chipView.getAppIconView().contentDescription).isEqualTo(appName) + assertThat(view.getAppIconView().contentDescription).isEqualTo(appName) } @Test fun setIcon_iconSizeMatchesGetIconSize() { - controllerCommon.displayChip(getState()) - val chipView = getChipView() + underTest.displayView(getState()) + val view = getView() - controllerCommon.setIcon(chipView, PACKAGE_NAME) - chipView.measure( + underTest.setIcon(view, PACKAGE_NAME) + view.measure( View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED) ) - assertThat(chipView.getAppIconView().measuredWidth).isEqualTo(ICON_SIZE) - assertThat(chipView.getAppIconView().measuredHeight).isEqualTo(ICON_SIZE) + assertThat(view.getAppIconView().measuredWidth).isEqualTo(ICON_SIZE) + assertThat(view.getAppIconView().measuredHeight).isEqualTo(ICON_SIZE) } - private fun getState(name: String = "name") = ChipInfo(name) + private fun getState(name: String = "name") = ViewInfo(name) - private fun getChipView(): ViewGroup { + private fun getView(): ViewGroup { val viewCaptor = ArgumentCaptor.forClass(View::class.java) verify(windowManager).addView(viewCaptor.capture(), any()) return viewCaptor.value as ViewGroup @@ -349,37 +346,35 @@ class MediaTttChipControllerCommonTest : SysuiTestCase() { return callbackCaptor.value } - inner class TestControllerCommon( + inner class TestController( context: Context, logger: MediaTttLogger, windowManager: WindowManager, - viewUtil: ViewUtil, @Main mainExecutor: DelayableExecutor, accessibilityManager: AccessibilityManager, configurationController: ConfigurationController, powerManager: PowerManager, - ) : MediaTttChipControllerCommon<ChipInfo>( + ) : TemporaryViewDisplayController<ViewInfo>( context, logger, windowManager, - viewUtil, mainExecutor, accessibilityManager, configurationController, powerManager, R.layout.media_ttt_chip, ) { - var mostRecentChipInfo: ChipInfo? = null + var mostRecentViewInfo: ViewInfo? = null override val windowLayoutParams = commonWindowLayoutParams - override fun updateChipView(newChipInfo: ChipInfo, currentChipView: ViewGroup) { - super.updateChipView(newChipInfo, currentChipView) - mostRecentChipInfo = newChipInfo + override fun updateView(newInfo: ViewInfo, currentView: ViewGroup) { + super.updateView(newInfo, currentView) + mostRecentViewInfo = newInfo } override fun getIconSize(isAppIcon: Boolean): Int = ICON_SIZE } - inner class ChipInfo(val name: String) : ChipInfoCommon { + inner class ViewInfo(val name: String) : TemporaryViewInfo { override fun getTimeoutMs() = 1L } } diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java index b425420479f0..aec60deba933 100644 --- a/services/core/java/com/android/server/camera/CameraServiceProxy.java +++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java @@ -582,13 +582,18 @@ public class CameraServiceProxy extends SystemService } @Override - public boolean isCameraDisabled() { + public boolean isCameraDisabled(int userId) { DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class); if (dpm == null) { Slog.e(TAG, "Failed to get the device policy manager service"); return false; } - return dpm.getCameraDisabled(null); + try { + return dpm.getCameraDisabled(null, userId); + } catch (Exception e) { + e.printStackTrace(); + return false; + } } }; diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 06fb4b0a01d8..6aca14f08188 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -8178,7 +8178,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } final CallerIdentity caller = getCallerIdentity(who); - Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle)); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle) + || isCameraServerUid(caller)); if (parent) { Preconditions.checkCallAuthorization( @@ -9689,6 +9690,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return UserHandle.isSameApp(caller.getUid(), Process.SHELL_UID); } + private boolean isCameraServerUid(CallerIdentity caller) { + return UserHandle.isSameApp(caller.getUid(), Process.CAMERASERVER_UID); + } + private @UserIdInt int getCurrentForegroundUserId() { try { UserInfo currentUser = mInjector.getIActivityManager().getCurrentUser(); |