summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/window/WindowContainerTransaction.java6
-rw-r--r--core/jni/android_graphics_BLASTBufferQueue.cpp21
-rw-r--r--data/etc/services.core.protolog.json12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/animation/PhysicsAnimator.kt8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java14
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenConstants.java11
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java15
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java20
-rw-r--r--packages/CompanionDeviceManager/res/values/strings.xml4
-rw-r--r--packages/SystemUI/res/drawable/screenshot_edit_background.xml2
-rw-r--r--packages/SystemUI/res/layout/brightness_mirror_container.xml1
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java11
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerKt.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt35
-rw-r--r--packages/SystemUI/src/com/android/systemui/clipboardoverlay/EditTextActivity.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java172
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java97
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DebugModeCoordinator.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinator.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SharedCoordinatorLogger.kt46
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinator.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt104
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt311
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupAdapterTest.java222
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java120
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinatorTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java34
-rw-r--r--services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java13
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java10
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java26
-rw-r--r--services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java11
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java8
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java4
-rw-r--r--services/smartspace/java/com/android/server/smartspace/SmartspacePerUserService.java13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java1
62 files changed, 685 insertions, 956 deletions
diff --git a/core/java/android/window/WindowContainerTransaction.java b/core/java/android/window/WindowContainerTransaction.java
index a87b91d87f1c..3bffa890122a 100644
--- a/core/java/android/window/WindowContainerTransaction.java
+++ b/core/java/android/window/WindowContainerTransaction.java
@@ -348,8 +348,10 @@ public final class WindowContainerTransaction implements Parcelable {
* @param currentParent of the tasks to perform the operation no.
* {@code null} will perform the operation on the display.
* @param newParent for the tasks. {@code null} will perform the operation on the display.
- * @param windowingModes of the tasks to reparent.
- * @param activityTypes of the tasks to reparent.
+ * @param windowingModes of the tasks to reparent. {@code null} ignore this attribute when
+ * perform the operation.
+ * @param activityTypes of the tasks to reparent. {@code null} ignore this attribute when
+ * perform the operation.
* @param onTop When {@code true}, the child goes to the top of parent; otherwise it goes to
* the bottom.
*/
diff --git a/core/jni/android_graphics_BLASTBufferQueue.cpp b/core/jni/android_graphics_BLASTBufferQueue.cpp
index 4af28ea24361..1520ea5c6831 100644
--- a/core/jni/android_graphics_BLASTBufferQueue.cpp
+++ b/core/jni/android_graphics_BLASTBufferQueue.cpp
@@ -41,7 +41,12 @@ struct {
static JNIEnv* getenv(JavaVM* vm) {
JNIEnv* env;
- if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ auto result = vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
+ if (result == JNI_EDETACHED) {
+ if (vm->AttachCurrentThreadAsDaemon(&env, nullptr) != JNI_OK) {
+ LOG_ALWAYS_FATAL("Failed to AttachCurrentThread!");
+ }
+ } else if (result != JNI_OK) {
LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
}
return env;
@@ -60,28 +65,22 @@ public:
}
~TransactionHangCallbackWrapper() {
- if (mTransactionHangObject) {
- getenv()->DeleteGlobalRef(mTransactionHangObject);
+ if (mTransactionHangObject != nullptr) {
+ getenv(mVm)->DeleteGlobalRef(mTransactionHangObject);
mTransactionHangObject = nullptr;
}
}
void onTransactionHang(bool isGpuHang) {
if (mTransactionHangObject) {
- getenv()->CallVoidMethod(mTransactionHangObject,
- gTransactionHangCallback.onTransactionHang, isGpuHang);
+ getenv(mVm)->CallVoidMethod(mTransactionHangObject,
+ gTransactionHangCallback.onTransactionHang, isGpuHang);
}
}
private:
JavaVM* mVm;
jobject mTransactionHangObject;
-
- JNIEnv* getenv() {
- JNIEnv* env;
- mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
- return env;
- }
};
static jlong nativeCreate(JNIEnv* env, jclass clazz, jstring jName,
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 6706e4e87e0d..f01e2e809c21 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -577,12 +577,6 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
- "-1521427940": {
- "message": "commitVisibility: %s: visible=%b mVisibleRequested=%b",
- "level": "VERBOSE",
- "group": "WM_DEBUG_APP_TRANSITIONS",
- "at": "com\/android\/server\/wm\/ActivityRecord.java"
- },
"-1517908912": {
"message": "requestScrollCapture: caught exception dispatching to window.token=%s",
"level": "WARN",
@@ -1513,6 +1507,12 @@
"group": "WM_DEBUG_FOCUS_LIGHT",
"at": "com\/android\/server\/wm\/DisplayContent.java"
},
+ "-636553602": {
+ "message": "commitVisibility: %s: visible=%b visibleRequested=%b, isInTransition=%b, runningAnimation=%b, caller=%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_APP_TRANSITIONS",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"-635082269": {
"message": "******** booted=%b msg=%b haveBoot=%b haveApp=%b haveWall=%b wallEnabled=%b haveKeyguard=%b",
"level": "INFO",
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/animation/PhysicsAnimator.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/animation/PhysicsAnimator.kt
index b483fe03e80f..312af4ff7bc2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/animation/PhysicsAnimator.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/animation/PhysicsAnimator.kt
@@ -829,8 +829,12 @@ class PhysicsAnimator<T> private constructor (target: T) {
/** Cancels all in progress animations on all properties. */
fun cancel() {
- cancelAction(flingAnimations.keys)
- cancelAction(springAnimations.keys)
+ if (flingAnimations.size > 0) {
+ cancelAction(flingAnimations.keys)
+ }
+ if (springAnimations.size > 0) {
+ cancelAction(springAnimations.keys)
+ }
}
/** Cancels in progress animations on the provided properties only. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 5801d43aaefd..2e64c945ca25 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -487,13 +487,25 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
private DividerSnapAlgorithm getSnapAlgorithm(Context context, Rect rootBounds,
@Nullable Rect stableInsets) {
final boolean isLandscape = isLandscape(rootBounds);
+ final Rect insets = stableInsets != null ? stableInsets : getDisplayInsets(context);
+
+ // Make split axis insets value same as the larger one to avoid bounds1 and bounds2
+ // have difference after split switching for solving issues on non-resizable app case.
+ if (isLandscape) {
+ final int largerInsets = Math.max(insets.left, insets.right);
+ insets.set(largerInsets, insets.top, largerInsets, insets.bottom);
+ } else {
+ final int largerInsets = Math.max(insets.top, insets.bottom);
+ insets.set(insets.left, largerInsets, insets.right, largerInsets);
+ }
+
return new DividerSnapAlgorithm(
context.getResources(),
rootBounds.width(),
rootBounds.height(),
mDividerSize,
!isLandscape,
- stableInsets != null ? stableInsets : getDisplayInsets(context),
+ insets,
isLandscape ? DOCKED_LEFT : DOCKED_TOP /* dockSide */);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenConstants.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenConstants.java
index 9b614875119b..afc706ee9c8e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenConstants.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitScreenConstants.java
@@ -15,6 +15,11 @@
*/
package com.android.wm.shell.common.split;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+
import android.annotation.IntDef;
/** Helper utility class of methods and constants that are available to be imported in Launcher. */
@@ -44,4 +49,10 @@ public class SplitScreenConstants {
})
public @interface SplitPosition {
}
+
+ public static final int[] CONTROLLED_ACTIVITY_TYPES = {ACTIVITY_TYPE_STANDARD};
+ public static final int[] CONTROLLED_WINDOWING_MODES =
+ {WINDOWING_MODE_FULLSCREEN, WINDOWING_MODE_UNDEFINED};
+ public static final int[] CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE =
+ {WINDOWING_MODE_FULLSCREEN, WINDOWING_MODE_UNDEFINED, WINDOWING_MODE_MULTI_WINDOW};
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
index 2bfa5db502ce..e7ec15e70c11 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
@@ -16,6 +16,9 @@
package com.android.wm.shell.splitscreen;
+import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES;
+import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES;
+
import android.content.Context;
import android.view.SurfaceSession;
import android.window.WindowContainerToken;
@@ -74,10 +77,10 @@ class MainStage extends StageTaskListener {
if (mRootTaskInfo == null) return;
final WindowContainerToken rootToken = mRootTaskInfo.token;
wct.reparentTasks(
- rootToken,
- null /* newParent */,
- CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE,
- CONTROLLED_ACTIVITY_TYPES,
- toTop);
+ rootToken,
+ null /* newParent */,
+ null /* windowingModes */,
+ null /* activityTypes */,
+ toTop);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
index f92a0d3901b9..8639b36faf4c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
@@ -47,8 +47,8 @@ class SideStage extends StageTaskListener {
wct.reparentTasks(
mRootTaskInfo.token,
null /* newParent */,
- CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE,
- CONTROLLED_ACTIVITY_TYPES,
+ null /* windowingModes */,
+ null /* activityTypes */,
toTop);
return true;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index c8ee010e60e0..47bfaa64c831 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -26,6 +26,8 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
+import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES;
+import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
@@ -64,6 +66,7 @@ import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.InstanceId;
import com.android.internal.protolog.common.ProtoLog;
+import com.android.internal.util.ArrayUtils;
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -227,6 +230,12 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
&& mStageCoordinator.getStageOfTask(taskId) != STAGE_TYPE_UNDEFINED;
}
+ public boolean isValidToEnterSplitScreen(@NonNull ActivityManager.RunningTaskInfo taskInfo) {
+ return taskInfo.supportsMultiWindow
+ && ArrayUtils.contains(CONTROLLED_ACTIVITY_TYPES, taskInfo.getActivityType())
+ && ArrayUtils.contains(CONTROLLED_WINDOWING_MODES, taskInfo.getWindowingMode());
+ }
+
public @SplitPosition int getSplitPosition(int taskId) {
return mStageCoordinator.getSplitPosition(taskId);
}
@@ -463,11 +472,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
return Objects.equals(launchingActivity, pairedActivity);
}
- if (mFocusingTaskInfo != null
- // TODO (b/238032411): have an API to determine whether an activity is valid for
- // split screen or not.
- && mFocusingTaskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
- && mFocusingTaskInfo.getActivityType() == ACTIVITY_TYPE_STANDARD) {
+ if (mFocusingTaskInfo != null && isValidToEnterSplitScreen(mFocusingTaskInfo)) {
return Objects.equals(mFocusingTaskInfo.baseIntent.getComponent(), launchingActivity);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 70d728d90b6a..e19c572c4850 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -87,6 +87,7 @@ import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.WindowManager;
+import android.widget.Toast;
import android.window.DisplayAreaInfo;
import android.window.RemoteTransition;
import android.window.TransitionInfo;
@@ -98,6 +99,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.InstanceId;
import com.android.internal.protolog.common.ProtoLog;
import com.android.launcher3.icons.IconProvider;
+import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
@@ -1921,10 +1923,13 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@Override
public void onNoLongerSupportMultiWindow() {
if (mMainStage.isActive()) {
+ final Toast splitUnsupportedToast = Toast.makeText(mContext,
+ R.string.dock_non_resizeble_failed_to_dock_text, Toast.LENGTH_SHORT);
final boolean isMainStage = mMainStageListener == this;
if (!ENABLE_SHELL_TRANSITIONS) {
StageCoordinator.this.exitSplitScreen(isMainStage ? mMainStage : mSideStage,
EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW);
+ splitUnsupportedToast.show();
return;
}
@@ -1933,6 +1938,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
prepareExitSplitScreen(stageType, wct);
mSplitTransitions.startDismissTransition(wct,StageCoordinator.this, stageType,
EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW);
+ splitUnsupportedToast.show();
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index cb9e1a39ec52..d17ff7aff667 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -17,12 +17,12 @@
package com.android.wm.shell.splitscreen;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES;
+import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE;
import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
import android.annotation.CallSuper;
@@ -40,6 +40,7 @@ import android.window.WindowContainerTransaction;
import androidx.annotation.NonNull;
+import com.android.internal.util.ArrayUtils;
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.SurfaceUtils;
@@ -62,12 +63,6 @@ import java.util.function.Predicate;
class StageTaskListener implements ShellTaskOrganizer.TaskListener {
private static final String TAG = StageTaskListener.class.getSimpleName();
- protected static final int[] CONTROLLED_ACTIVITY_TYPES = {ACTIVITY_TYPE_STANDARD};
- protected static final int[] CONTROLLED_WINDOWING_MODES =
- {WINDOWING_MODE_FULLSCREEN, WINDOWING_MODE_UNDEFINED};
- protected static final int[] CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE =
- {WINDOWING_MODE_FULLSCREEN, WINDOWING_MODE_UNDEFINED, WINDOWING_MODE_MULTI_WINDOW};
-
/** Callback interface for listening to changes in a split-screen stage. */
public interface StageListenerCallbacks {
void onRootTaskAppeared();
@@ -212,12 +207,15 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
}
mRootTaskInfo = taskInfo;
} else if (taskInfo.parentTaskId == mRootTaskInfo.taskId) {
- if (!taskInfo.supportsMultiWindow) {
- // Leave split screen if the task no longer supports multi window.
+ if (!taskInfo.supportsMultiWindow
+ || !ArrayUtils.contains(CONTROLLED_ACTIVITY_TYPES, taskInfo.getActivityType())
+ || !ArrayUtils.contains(CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE,
+ taskInfo.getWindowingMode())) {
+ // Leave split screen if the task no longer supports multi window or have
+ // uncontrolled task.
mCallbacks.onNoLongerSupportMultiWindow();
return;
}
-
mChildrenTaskInfo.put(taskInfo.taskId, taskInfo);
mCallbacks.onChildTaskStatusChanged(taskInfo.taskId, true /* present */,
taskInfo.isVisible);
diff --git a/packages/CompanionDeviceManager/res/values/strings.xml b/packages/CompanionDeviceManager/res/values/strings.xml
index a389bfc42725..cb85ae4fe66b 100644
--- a/packages/CompanionDeviceManager/res/values/strings.xml
+++ b/packages/CompanionDeviceManager/res/values/strings.xml
@@ -48,7 +48,7 @@
<string name="helper_title_app_streaming">Cross-device services</string>
<!-- Description of the helper dialog for APP_STREAMING profile. [CHAR LIMIT=NONE] -->
- <string name="helper_summary_app_streaming"><xliff:g id="app_name" example="GMS">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="device_type" example="Chromebook">%2$s</xliff:g> to access your phone\u2019s photos, media, and notifications</string>
+ <string name="helper_summary_app_streaming"><xliff:g id="app_name" example="GMS">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="device_type" example="Chromebook">%2$s</xliff:g> to stream apps between your devices</string>
<!-- ================= DEVICE_PROFILE_AUTOMOTIVE_PROJECTION ================= -->
@@ -82,7 +82,7 @@
<string name="helper_title_computer">Google Play services</string>
<!-- Description of the helper dialog for COMPUTER profile. [CHAR LIMIT=NONE] -->
- <string name="helper_summary_computer"> <xliff:g id="app_name" example="GMS">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="device_type" example="Chromebook">%2$s</xliff:g> to stream apps between your devices</string>
+ <string name="helper_summary_computer"><xliff:g id="app_name" example="GMS">%1$s</xliff:g> is requesting permission on behalf of your <xliff:g id="device_type" example="Chromebook">%2$s</xliff:g> to access your phone\u2019s photos, media, and notifications</string>
<!-- ================= null profile ================= -->
diff --git a/packages/SystemUI/res/drawable/screenshot_edit_background.xml b/packages/SystemUI/res/drawable/screenshot_edit_background.xml
index ff5c62e1600b..a1185a2d5479 100644
--- a/packages/SystemUI/res/drawable/screenshot_edit_background.xml
+++ b/packages/SystemUI/res/drawable/screenshot_edit_background.xml
@@ -17,7 +17,7 @@
<!-- Long screenshot edit FAB background -->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- android:color="?android:textColorPrimary">
+ android:color="@color/overlay_button_ripple">
<item android:id="@android:id/background">
<shape android:shape="rectangle">
<solid android:color="?androidprv:attr/colorAccentPrimary"/>
diff --git a/packages/SystemUI/res/layout/brightness_mirror_container.xml b/packages/SystemUI/res/layout/brightness_mirror_container.xml
index ac90db3e5e19..1bf45aad8906 100644
--- a/packages/SystemUI/res/layout/brightness_mirror_container.xml
+++ b/packages/SystemUI/res/layout/brightness_mirror_container.xml
@@ -23,7 +23,6 @@
android:background="@drawable/brightness_mirror_background"
android:layout_gravity="center_vertical"
android:layout_margin="8dp"
- android:padding="@dimen/rounded_slider_background_padding"
android:gravity="center"
android:visibility="invisible">
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
index e9c1acbf7ca0..e3f568732b9d 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
@@ -18,6 +18,9 @@ package com.android.systemui.shared.recents.model;
import static android.view.Display.DEFAULT_DISPLAY;
+import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES;
+import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES;
+
import android.app.ActivityManager;
import android.app.ActivityManager.TaskDescription;
import android.app.TaskInfo;
@@ -31,6 +34,8 @@ import android.view.ViewDebug;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.internal.util.ArrayUtils;
+
import java.io.PrintWriter;
import java.util.Objects;
@@ -242,8 +247,10 @@ public class Task {
ActivityManager.TaskDescription td = taskInfo.taskDescription;
return new Task(taskKey,
td != null ? td.getPrimaryColor() : 0,
- td != null ? td.getBackgroundColor() : 0,
- taskInfo.supportsMultiWindow, isLocked, td, taskInfo.topActivity);
+ td != null ? td.getBackgroundColor() : 0, taskInfo.supportsMultiWindow
+ && ArrayUtils.contains(CONTROLLED_ACTIVITY_TYPES, taskInfo.getActivityType())
+ && ArrayUtils.contains(CONTROLLED_WINDOWING_MODES, taskInfo.getWindowingMode()),
+ isLocked, td, taskInfo.topActivity);
}
public Task(TaskKey key) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerKt.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerKt.kt
new file mode 100644
index 000000000000..c1429335292f
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerKt.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shared.system
+
+import android.app.ActivityManager
+
+/** Kotlin extensions for [ActivityManager] */
+object ActivityManagerKt {
+
+ /**
+ * Returns `true` whether the app with the given package name has an activity at the top of the
+ * most recent task; `false` otherwise
+ */
+ fun ActivityManager.isInForeground(packageName: String): Boolean {
+ val tasks: List<ActivityManager.RunningTaskInfo> = getRunningTasks(1)
+ return tasks.isNotEmpty() && packageName == tasks[0].topActivity.packageName
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt b/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
index 99267e8ee1c9..cccd3a482ef0 100644
--- a/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
@@ -17,27 +17,28 @@
package com.android.systemui.camera
import android.app.ActivityManager
-import android.app.ActivityManager.RunningTaskInfo
import android.app.ActivityOptions
-import android.app.ActivityTaskManager
+import android.app.IActivityTaskManager
import android.content.ContentResolver
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
-import android.os.AsyncTask
import android.os.RemoteException
import android.os.UserHandle
import android.util.Log
import android.view.WindowManager
+import androidx.annotation.VisibleForTesting
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.ActivityIntentHelper
-import com.android.systemui.camera.CameraIntents.Companion.isSecureCameraIntent
+import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.shared.system.ActivityManagerKt.isInForeground
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.PanelViewController
import com.android.systemui.statusbar.policy.KeyguardStateController
+import java.util.concurrent.Executor
import javax.inject.Inject
/**
@@ -52,8 +53,10 @@ class CameraGestureHelper @Inject constructor(
private val activityManager: ActivityManager,
private val activityStarter: ActivityStarter,
private val activityIntentHelper: ActivityIntentHelper,
+ private val activityTaskManager: IActivityTaskManager,
private val cameraIntents: CameraIntentsWrapper,
private val contentResolver: ContentResolver,
+ @Main private val uiExecutor: Executor,
) {
/**
* Whether the camera application can be launched for the camera launch gesture.
@@ -63,15 +66,15 @@ class CameraGestureHelper @Inject constructor(
return false
}
- val resolveInfo: ResolveInfo = packageManager.resolveActivityAsUser(
+ val resolveInfo: ResolveInfo? = packageManager.resolveActivityAsUser(
getStartCameraIntent(),
PackageManager.MATCH_DEFAULT_ONLY,
KeyguardUpdateMonitor.getCurrentUser()
)
- val resolvedPackage = resolveInfo.activityInfo?.packageName
+ val resolvedPackage = resolveInfo?.activityInfo?.packageName
return (resolvedPackage != null &&
(statusBarState != StatusBarState.SHADE ||
- !isForegroundApp(resolvedPackage)))
+ !activityManager.isInForeground(resolvedPackage)))
}
/**
@@ -85,8 +88,8 @@ class CameraGestureHelper @Inject constructor(
val wouldLaunchResolverActivity = activityIntentHelper.wouldLaunchResolverActivity(
intent, KeyguardUpdateMonitor.getCurrentUser()
)
- if (isSecureCameraIntent(intent) && !wouldLaunchResolverActivity) {
- AsyncTask.execute {
+ if (CameraIntents.isSecureCameraIntent(intent) && !wouldLaunchResolverActivity) {
+ uiExecutor.execute {
// Normally an activity will set its requested rotation animation on its window.
// However when launching an activity causes the orientation to change this is too
// late. In these cases, the default animation is used. This doesn't look good for
@@ -98,7 +101,7 @@ class CameraGestureHelper @Inject constructor(
activityOptions.rotationAnimationHint =
WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS
try {
- ActivityTaskManager.getService().startActivityAsUser(
+ activityTaskManager.startActivityAsUser(
null,
context.basePackageName,
context.attributionTag,
@@ -148,16 +151,8 @@ class CameraGestureHelper @Inject constructor(
}
}
- /**
- * Returns `true` if the application with the given package name is running in the foreground;
- * `false` otherwise
- */
- private fun isForegroundApp(packageName: String): Boolean {
- val tasks: List<RunningTaskInfo> = activityManager.getRunningTasks(1)
- return tasks.isNotEmpty() && packageName == tasks[0].topActivity.packageName
- }
-
companion object {
- private const val EXTRA_CAMERA_LAUNCH_SOURCE = "com.android.systemui.camera_launch_source"
+ @VisibleForTesting
+ const val EXTRA_CAMERA_LAUNCH_SOURCE = "com.android.systemui.camera_launch_source"
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/EditTextActivity.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/EditTextActivity.java
index 3f78f97ba563..1fa9ac574c7e 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/EditTextActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/EditTextActivity.java
@@ -74,6 +74,7 @@ public class EditTextActivity extends Activity
}
mEditText.setText(clip.getItemAt(0).getText());
mEditText.requestFocus();
+ mEditText.setSelection(0);
mSensitive = clip.getDescription().getExtras() != null
&& clip.getDescription().getExtras()
.getBoolean(ClipDescription.EXTRA_IS_SENSITIVE);
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index f2f275323d58..ec4c4e6b3363 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -42,14 +42,11 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
private static final String TAG = "MediaOutputAdapter";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private final MediaOutputDialog mMediaOutputDialog;
private ViewGroup mConnectedItem;
private boolean mIncludeDynamicGroup;
- public MediaOutputAdapter(MediaOutputController controller,
- MediaOutputDialog mediaOutputDialog) {
+ public MediaOutputAdapter(MediaOutputController controller) {
super(controller);
- mMediaOutputDialog = mediaOutputDialog;
setHasStableIds(true);
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java
index 8f065461c22d..310469dd5415 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialog.java
@@ -74,7 +74,7 @@ public class MediaOutputBroadcastDialog extends MediaOutputBaseDialog {
MediaOutputBroadcastDialog(Context context, boolean aboveStatusbar,
BroadcastSender broadcastSender, MediaOutputController mediaOutputController) {
super(context, broadcastSender, mediaOutputController);
- mAdapter = new MediaOutputGroupAdapter(mMediaOutputController);
+ mAdapter = new MediaOutputAdapter(mMediaOutputController);
// TODO(b/226710953): Move the part to MediaOutputBaseDialog for every class
// that extends MediaOutputBaseDialog
if (!aboveStatusbar) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java
index a6cf408e0099..7cf0063481a5 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java
@@ -42,7 +42,7 @@ public class MediaOutputDialog extends MediaOutputBaseDialog {
MediaOutputController mediaOutputController, UiEventLogger uiEventLogger) {
super(context, broadcastSender, mediaOutputController);
mUiEventLogger = uiEventLogger;
- mAdapter = new MediaOutputAdapter(mMediaOutputController, this);
+ mAdapter = new MediaOutputAdapter(mMediaOutputController);
if (!aboveStatusbar) {
getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java
deleted file mode 100644
index ba2f006fc58e..000000000000
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.media.dialog;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
-import android.util.Log;
-import android.util.TypedValue;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.NonNull;
-
-import com.android.settingslib.media.MediaDevice;
-import com.android.systemui.R;
-
-import java.util.List;
-
-/**
- * Adapter for media output dynamic group dialog.
- */
-//TODO: clear this class after new UI updated
-public class MediaOutputGroupAdapter extends MediaOutputBaseAdapter {
-
- private static final String TAG = "MediaOutputGroupAdapter";
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
- private final List<MediaDevice> mGroupMediaDevices;
-
- public MediaOutputGroupAdapter(MediaOutputController controller) {
- super(controller);
- mGroupMediaDevices = controller.getGroupMediaDevices();
- }
-
- @Override
- public MediaDeviceBaseViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup,
- int viewType) {
- super.onCreateViewHolder(viewGroup, viewType);
-
- return new GroupViewHolder(mHolderView);
- }
-
- @Override
- public void onBindViewHolder(@NonNull MediaDeviceBaseViewHolder viewHolder, int position) {
- // Add "Group"
- if (position == 0) {
- viewHolder.onBind(CUSTOMIZED_ITEM_GROUP, true /* topMargin */,
- false /* bottomMargin */);
- return;
- }
- // Add available devices
- final int newPosition = position - 1;
- final int size = mGroupMediaDevices.size();
- if (newPosition < size) {
- viewHolder.onBind(mGroupMediaDevices.get(newPosition), false /* topMargin */,
- newPosition == (size - 1) /* bottomMargin */, position);
- return;
- }
- if (DEBUG) {
- Log.d(TAG, "Incorrect position: " + position);
- }
- }
-
- @Override
- public int getItemCount() {
- // Require extra item for group volume operation
- return mGroupMediaDevices.size() + 1;
- }
-
- @Override
- CharSequence getItemTitle(MediaDevice device) {
- return super.getItemTitle(device);
- }
-
- class GroupViewHolder extends MediaDeviceBaseViewHolder {
-
- GroupViewHolder(View view) {
- super(view);
- }
-
- @Override
- void onBind(MediaDevice device, boolean topMargin, boolean bottomMargin, int position) {
- super.onBind(device, topMargin, bottomMargin, position);
- mCheckBox.setVisibility(View.VISIBLE);
- mCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
- onCheckBoxClicked(isChecked, device);
- });
- boolean isCurrentSeekbarInvisible = mSeekBar.getVisibility() == View.GONE;
- setTwoLineLayout(device, false /* bFocused */, true /* showSeekBar */,
- false /* showProgressBar */, false /* showSubtitle*/);
- initSeekbar(device, isCurrentSeekbarInvisible);
- final List<MediaDevice> selectedDevices = mController.getSelectedMediaDevice();
- if (isDeviceIncluded(mController.getSelectableMediaDevice(), device)) {
- mCheckBox.setButtonDrawable(R.drawable.ic_check_box);
- mCheckBox.setChecked(false);
- mCheckBox.setEnabled(true);
- } else if (isDeviceIncluded(selectedDevices, device)) {
- if (selectedDevices.size() == 1 || !isDeviceIncluded(
- mController.getDeselectableMediaDevice(), device)) {
- mCheckBox.setButtonDrawable(getDisabledCheckboxDrawable());
- mCheckBox.setChecked(true);
- mCheckBox.setEnabled(false);
- } else {
- mCheckBox.setButtonDrawable(R.drawable.ic_check_box);
- mCheckBox.setChecked(true);
- mCheckBox.setEnabled(true);
- }
- }
- }
-
- @Override
- void onBind(int customizedItem, boolean topMargin, boolean bottomMargin) {
- if (customizedItem == CUSTOMIZED_ITEM_GROUP) {
- setTwoLineLayout(mContext.getText(R.string.media_output_dialog_group),
- true /* bFocused */, true /* showSeekBar */, false /* showProgressBar */,
- false /* showSubtitle*/);
- mTitleIcon.setImageDrawable(getSpeakerDrawable());
- mCheckBox.setVisibility(View.GONE);
- initSessionSeekbar();
- }
- }
-
- private void onCheckBoxClicked(boolean isChecked, MediaDevice device) {
- if (isChecked && isDeviceIncluded(mController.getSelectableMediaDevice(), device)) {
- mController.addDeviceToPlayMedia(device);
- } else if (!isChecked && isDeviceIncluded(mController.getDeselectableMediaDevice(),
- device)) {
- mController.removeDeviceFromPlayMedia(device);
- }
- }
-
- private Drawable getDisabledCheckboxDrawable() {
- final Drawable drawable = mContext.getDrawable(R.drawable.ic_check_box_blue_24dp)
- .mutate();
- final Bitmap checkbox = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
- drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
- final Canvas canvas = new Canvas(checkbox);
- TypedValue value = new TypedValue();
- mContext.getTheme().resolveAttribute(android.R.attr.disabledAlpha, value, true);
- drawable.setAlpha((int) (value.getFloat() * 255));
- drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
- drawable.draw(canvas);
-
- return drawable;
- }
-
- private boolean isDeviceIncluded(List<MediaDevice> deviceList, MediaDevice targetDevice) {
- for (MediaDevice device : deviceList) {
- if (TextUtils.equals(device.getId(), targetDevice.getId())) {
- return true;
- }
- }
- return false;
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java
deleted file mode 100644
index bb3f969c86df..000000000000
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.media.dialog;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.view.View;
-import android.view.WindowManager;
-
-import androidx.core.graphics.drawable.IconCompat;
-
-import com.android.systemui.R;
-import com.android.systemui.broadcast.BroadcastSender;
-
-/**
- * Dialog for media output group.
- */
-// TODO(b/203073091): Remove this class once group logic been implemented.
-public class MediaOutputGroupDialog extends MediaOutputBaseDialog {
-
- MediaOutputGroupDialog(Context context, boolean aboveStatusbar, BroadcastSender broadcastSender,
- MediaOutputController mediaOutputController) {
- super(context, broadcastSender, mediaOutputController);
- mMediaOutputController.resetGroupMediaDevices();
- mAdapter = new MediaOutputGroupAdapter(mMediaOutputController);
- if (!aboveStatusbar) {
- getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY);
- }
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- }
-
- @Override
- int getHeaderIconRes() {
- return R.drawable.ic_arrow_back;
- }
-
- @Override
- IconCompat getHeaderIcon() {
- return null;
- }
-
- @Override
- int getHeaderIconSize() {
- return mContext.getResources().getDimensionPixelSize(
- R.dimen.media_output_dialog_header_back_icon_size);
- }
-
- @Override
- CharSequence getHeaderText() {
- return mContext.getString(R.string.media_output_dialog_add_output);
- }
-
- @Override
- CharSequence getHeaderSubtitle() {
- final int size = mMediaOutputController.getSelectedMediaDevice().size();
- if (size == 1) {
- return mContext.getText(R.string.media_output_dialog_single_device);
- }
- return mContext.getString(R.string.media_output_dialog_multiple_devices, size);
- }
-
- @Override
- Drawable getAppSourceIcon() {
- return null;
- }
-
- @Override
- int getStopButtonVisibility() {
- return View.VISIBLE;
- }
-
- @Override
- void onHeaderIconClick() {
- // Given that we launched the media output group dialog from the media output dialog,
- // dismissing this dialog will show the media output dialog again.
- dismiss();
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java
index 6a3799b38dc5..d1aa01bb2125 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifInflaterImpl.java
@@ -75,8 +75,8 @@ public class NotifInflaterImpl implements NotifInflater {
}
@Override
- public void abortInflation(NotificationEntry entry) {
- entry.abortTask();
+ public boolean abortInflation(NotificationEntry entry) {
+ return entry.abortTask();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 0a16fb65b1ac..b6392f705c49 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -476,11 +476,13 @@ public final class NotificationEntry extends ListEntry {
/**
* Abort all existing inflation tasks
*/
- public void abortTask() {
+ public boolean abortTask() {
if (mRunningTask != null) {
mRunningTask.abort();
mRunningTask = null;
+ return true;
}
+ return false;
}
public void setInflationTask(InflationTask abortableTask) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
index 93761f580dd4..075a0dc7555e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
@@ -314,60 +314,62 @@ public class ShadeListBuilder implements Dumpable {
}
};
- private void onPreRenderInvalidated(Invalidator invalidator) {
+ private void onPreRenderInvalidated(Invalidator invalidator, @Nullable String reason) {
Assert.isMainThread();
- mLogger.logPreRenderInvalidated(invalidator.getName(), mPipelineState.getState());
+ mLogger.logPreRenderInvalidated(invalidator, mPipelineState.getState(), reason);
rebuildListIfBefore(STATE_FINALIZING);
}
- private void onPreGroupFilterInvalidated(NotifFilter filter) {
+ private void onPreGroupFilterInvalidated(NotifFilter filter, @Nullable String reason) {
Assert.isMainThread();
- mLogger.logPreGroupFilterInvalidated(filter.getName(), mPipelineState.getState());
+ mLogger.logPreGroupFilterInvalidated(filter, mPipelineState.getState(), reason);
rebuildListIfBefore(STATE_PRE_GROUP_FILTERING);
}
- private void onReorderingAllowedInvalidated(NotifStabilityManager stabilityManager) {
+ private void onReorderingAllowedInvalidated(NotifStabilityManager stabilityManager,
+ @Nullable String reason) {
Assert.isMainThread();
mLogger.logReorderingAllowedInvalidated(
- stabilityManager.getName(),
- mPipelineState.getState());
+ stabilityManager,
+ mPipelineState.getState(),
+ reason);
rebuildListIfBefore(STATE_GROUPING);
}
- private void onPromoterInvalidated(NotifPromoter promoter) {
+ private void onPromoterInvalidated(NotifPromoter promoter, @Nullable String reason) {
Assert.isMainThread();
- mLogger.logPromoterInvalidated(promoter.getName(), mPipelineState.getState());
+ mLogger.logPromoterInvalidated(promoter, mPipelineState.getState(), reason);
rebuildListIfBefore(STATE_TRANSFORMING);
}
- private void onNotifSectionInvalidated(NotifSectioner section) {
+ private void onNotifSectionInvalidated(NotifSectioner section, @Nullable String reason) {
Assert.isMainThread();
- mLogger.logNotifSectionInvalidated(section.getName(), mPipelineState.getState());
+ mLogger.logNotifSectionInvalidated(section, mPipelineState.getState(), reason);
rebuildListIfBefore(STATE_SORTING);
}
- private void onFinalizeFilterInvalidated(NotifFilter filter) {
+ private void onFinalizeFilterInvalidated(NotifFilter filter, @Nullable String reason) {
Assert.isMainThread();
- mLogger.logFinalizeFilterInvalidated(filter.getName(), mPipelineState.getState());
+ mLogger.logFinalizeFilterInvalidated(filter, mPipelineState.getState(), reason);
rebuildListIfBefore(STATE_FINALIZE_FILTERING);
}
- private void onNotifComparatorInvalidated(NotifComparator comparator) {
+ private void onNotifComparatorInvalidated(NotifComparator comparator, @Nullable String reason) {
Assert.isMainThread();
- mLogger.logNotifComparatorInvalidated(comparator.getName(), mPipelineState.getState());
+ mLogger.logNotifComparatorInvalidated(comparator, mPipelineState.getState(), reason);
rebuildListIfBefore(STATE_SORTING);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java
index 7293953eb8d3..3627b4084ec7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java
@@ -142,7 +142,7 @@ public class BubbleCoordinator implements Coordinator {
@Override
public void invalidateNotifications(String reason) {
- mNotifFilter.invalidateList();
+ mNotifFilter.invalidateList(reason);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DebugModeCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DebugModeCoordinator.kt
index df54ccd85e73..240540515705 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DebugModeCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DebugModeCoordinator.kt
@@ -30,12 +30,12 @@ class DebugModeCoordinator @Inject constructor(
) : Coordinator {
override fun attach(pipeline: NotifPipeline) {
- pipeline.addPreGroupFilter(preGroupFilter)
- debugModeFilterProvider.registerInvalidationListener(preGroupFilter::invalidateList)
+ pipeline.addPreGroupFilter(filter)
+ debugModeFilterProvider.registerInvalidationListener { filter.invalidateList(null) }
}
- private val preGroupFilter = object : NotifFilter("DebugModeCoordinator") {
+ private val filter = object : NotifFilter("DebugModeFilter") {
override fun shouldFilterOut(entry: NotificationEntry, now: Long) =
debugModeFilterProvider.shouldFilterOut(entry)
}
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
index e8652493da6b..058042c4bccd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
@@ -90,7 +90,7 @@ public class DeviceProvisionedCoordinator implements Coordinator {
new DeviceProvisionedController.DeviceProvisionedListener() {
@Override
public void onDeviceProvisionedChanged() {
- mNotifFilter.invalidateList();
+ mNotifFilter.invalidateList("onDeviceProvisionedChanged");
}
};
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
index a61db4107c94..8278b549a7a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
@@ -35,6 +35,7 @@ import com.android.systemui.statusbar.notification.collection.render.NodeControl
import com.android.systemui.statusbar.notification.dagger.IncomingHeader
import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider
+import com.android.systemui.statusbar.notification.logKey
import com.android.systemui.statusbar.notification.stack.BUCKET_HEADS_UP
import com.android.systemui.statusbar.policy.HeadsUpManager
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener
@@ -278,8 +279,8 @@ class HeadsUpCoordinator @Inject constructor(
.firstOrNull()
?.let { posted ->
posted.entry.takeIf { entry ->
- locationLookupByKey(entry.key) == GroupLocation.Isolated
- && entry.sbn.notification.groupAlertBehavior == GROUP_ALERT_SUMMARY
+ locationLookupByKey(entry.key) == GroupLocation.Isolated &&
+ entry.sbn.notification.groupAlertBehavior == GROUP_ALERT_SUMMARY
}
}
@@ -512,7 +513,7 @@ class HeadsUpCoordinator @Inject constructor(
private val mOnHeadsUpChangedListener = object : OnHeadsUpChangedListener {
override fun onHeadsUpStateChanged(entry: NotificationEntry, isHeadsUp: Boolean) {
if (!isHeadsUp) {
- mNotifPromoter.invalidateList()
+ mNotifPromoter.invalidateList("headsUpEnded: ${entry.logKey}")
mHeadsUpViewBinder.unbindHeadsUpView(entry)
endNotifLifetimeExtensionIfExtended(entry)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinator.java
index 7b5cf8511900..e4e2bc16b77e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinator.java
@@ -41,14 +41,11 @@ import javax.inject.Inject;
@CoordinatorScope
public class HideNotifsForOtherUsersCoordinator implements Coordinator {
private final NotificationLockscreenUserManager mLockscreenUserManager;
- private final SharedCoordinatorLogger mLogger;
@Inject
public HideNotifsForOtherUsersCoordinator(
- NotificationLockscreenUserManager lockscreenUserManager,
- SharedCoordinatorLogger logger) {
+ NotificationLockscreenUserManager lockscreenUserManager) {
mLockscreenUserManager = lockscreenUserManager;
- mLogger = logger;
}
@Override
@@ -70,23 +67,19 @@ public class HideNotifsForOtherUsersCoordinator implements Coordinator {
// changes
@Override
public void onCurrentProfilesChanged(SparseArray<UserInfo> currentProfiles) {
- mLogger.logUserOrProfileChanged(
- mLockscreenUserManager.getCurrentUserId(),
- profileIdsToStr(currentProfiles));
- mFilter.invalidateList();
+ StringBuilder sb = new StringBuilder("onCurrentProfilesChanged:");
+ sb.append(" user=").append(mLockscreenUserManager.getCurrentUserId());
+ sb.append(" profiles=");
+ sb.append("{");
+ for (int i = 0; i < currentProfiles.size(); i++) {
+ if (i != 0) {
+ sb.append(",");
+ }
+ sb.append(currentProfiles.keyAt(i));
+ }
+ sb.append("}");
+ mFilter.invalidateList(sb.toString());
}
};
- private String profileIdsToStr(SparseArray<UserInfo> currentProfiles) {
- StringBuilder sb = new StringBuilder();
- sb.append("{");
- for (int i = 0; i < currentProfiles.size(); i++) {
- sb.append(currentProfiles.keyAt(i));
- if (i < currentProfiles.size() - 1) {
- sb.append(",");
- }
- }
- sb.append("}");
- return sb.toString();
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
index ef63be0633bf..e3d71c8b29d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
@@ -38,18 +38,15 @@ public class KeyguardCoordinator implements Coordinator {
private static final String TAG = "KeyguardCoordinator";
private final KeyguardNotificationVisibilityProvider mKeyguardNotificationVisibilityProvider;
private final SectionHeaderVisibilityProvider mSectionHeaderVisibilityProvider;
- private final SharedCoordinatorLogger mLogger;
private final StatusBarStateController mStatusBarStateController;
@Inject
public KeyguardCoordinator(
KeyguardNotificationVisibilityProvider keyguardNotificationVisibilityProvider,
SectionHeaderVisibilityProvider sectionHeaderVisibilityProvider,
- SharedCoordinatorLogger logger,
StatusBarStateController statusBarStateController) {
mKeyguardNotificationVisibilityProvider = keyguardNotificationVisibilityProvider;
mSectionHeaderVisibilityProvider = sectionHeaderVisibilityProvider;
- mLogger = logger;
mStatusBarStateController = statusBarStateController;
}
@@ -78,9 +75,8 @@ public class KeyguardCoordinator implements Coordinator {
}
private void invalidateListFromFilter(String reason) {
- mLogger.logKeyguardCoordinatorInvalidated(reason);
updateSectionHeadersVisibility();
- mNotifFilter.invalidateList();
+ mNotifFilter.invalidateList(reason);
}
private void updateSectionHeadersVisibility() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
index 023c4ef2b8b7..ef1e57b4cd3b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.collection.coordinator;
+import static com.android.systemui.statusbar.notification.NotificationUtils.logKey;
import static com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED;
import static java.util.Objects.requireNonNull;
@@ -147,7 +148,8 @@ public class PreparationCoordinator implements Coordinator {
@Override
public void attach(NotifPipeline pipeline) {
mNotifErrorManager.addInflationErrorListener(mInflationErrorListener);
- mAdjustmentProvider.addDirtyListener(mNotifInflatingFilter::invalidateList);
+ mAdjustmentProvider.addDirtyListener(
+ () -> mNotifInflatingFilter.invalidateList("adjustmentProviderChanged"));
pipeline.addCollectionListener(mNotifCollectionListener);
// Inflate after grouping/sorting since that affects what views to inflate.
@@ -245,12 +247,13 @@ public class PreparationCoordinator implements Coordinator {
} catch (RemoteException ex) {
// System server is dead, nothing to do about that
}
- mNotifInflationErrorFilter.invalidateList();
+ mNotifInflationErrorFilter.invalidateList("onNotifInflationError for " + logKey(entry));
}
@Override
public void onNotifInflationErrorCleared(NotificationEntry entry) {
- mNotifInflationErrorFilter.invalidateList();
+ mNotifInflationErrorFilter.invalidateList(
+ "onNotifInflationErrorCleared for " + logKey(entry));
}
};
@@ -360,9 +363,11 @@ public class PreparationCoordinator implements Coordinator {
}
private void abortInflation(NotificationEntry entry, String reason) {
- mLogger.logInflationAborted(entry, reason);
- mNotifInflater.abortInflation(entry);
- mInflatingNotifs.remove(entry);
+ final boolean taskAborted = mNotifInflater.abortInflation(entry);
+ final boolean wasInflating = mInflatingNotifs.remove(entry);
+ if (taskAborted || wasInflating) {
+ mLogger.logInflationAborted(entry, reason);
+ }
}
private void onInflationFinished(NotificationEntry entry, NotifViewController controller) {
@@ -371,7 +376,7 @@ public class PreparationCoordinator implements Coordinator {
mViewBarn.registerViewForEntry(entry, controller);
mInflationStates.put(entry, STATE_INFLATED);
mBindEventManager.notifyViewBound(entry);
- mNotifInflatingFilter.invalidateList();
+ mNotifInflatingFilter.invalidateList("onInflationFinished for " + logKey(entry));
}
private void freeNotifViews(NotificationEntry entry) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
index 5ac481341d43..67a8a63ad7da 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
@@ -199,7 +199,7 @@ public class RankingCoordinator implements Coordinator {
new StatusBarStateController.StateListener() {
@Override
public void onDozingChanged(boolean isDozing) {
- mDndVisualEffectsFilter.invalidateList();
+ mDndVisualEffectsFilter.invalidateList("onDozingChanged to " + isDozing);
}
};
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
index 3f8a39f62dfb..aeeeb4fb054d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
@@ -64,7 +64,7 @@ private class SensitiveContentCoordinatorImpl @Inject constructor(
pipeline.addPreRenderInvalidator(this)
}
- override fun onDynamicPrivacyChanged(): Unit = invalidateList()
+ override fun onDynamicPrivacyChanged(): Unit = invalidateList("onDynamicPrivacyChanged")
override fun onBeforeRenderList(entries: List<ListEntry>) {
if (keyguardStateController.isKeyguardGoingAway() ||
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SharedCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SharedCoordinatorLogger.kt
deleted file mode 100644
index 25bc641f0a84..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SharedCoordinatorLogger.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification.collection.coordinator
-
-import com.android.systemui.log.LogBuffer
-import com.android.systemui.log.LogLevel
-import com.android.systemui.log.dagger.NotificationLog
-import javax.inject.Inject
-
-/**
- * Shared logging class for coordinators that don't log enough to merit their own logger.
- */
-class SharedCoordinatorLogger @Inject constructor(
- @NotificationLog private val buffer: LogBuffer
-) {
- fun logUserOrProfileChanged(userId: Int, profiles: String) {
- buffer.log("NotCurrentUserFilter", LogLevel.INFO, {
- int1 = userId
- str1 = profiles
- }, {
- "Current user or profiles changed. Current user is $int1; profiles are $str1"
- })
- }
-
- fun logKeyguardCoordinatorInvalidated(reason: String) {
- buffer.log("KeyguardCoordinator", LogLevel.DEBUG, {
- str1 = reason
- }, {
- "KeyguardCoordinator invalidated: $str1"
- })
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinator.kt
index ce361ea88bdc..9d0f974ea68f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinator.kt
@@ -30,6 +30,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
+import com.android.systemui.statusbar.notification.logKey
import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.time.SystemClock
import java.util.concurrent.TimeUnit.SECONDS
@@ -130,7 +131,7 @@ class SmartspaceDedupingCoordinator @Inject constructor(
}
if (changed) {
- filter.invalidateList()
+ filter.invalidateList("onNewSmartspaceTargets")
notificationEntryManager.updateNotifications("Smartspace targets changed")
}
@@ -167,7 +168,7 @@ class SmartspaceDedupingCoordinator @Inject constructor(
target.cancelTimeoutRunnable = executor.executeDelayed({
target.cancelTimeoutRunnable = null
target.shouldFilter = true
- filter.invalidateList()
+ filter.invalidateList("updateAlertException: ${entry.logKey}")
notificationEntryManager.updateNotifications("deduping timeout expired")
}, alertExceptionExpires - now)
}
@@ -184,7 +185,7 @@ class SmartspaceDedupingCoordinator @Inject constructor(
isOnLockscreen = newState == StatusBarState.KEYGUARD
if (isOnLockscreen != wasOnLockscreen) {
- filter.invalidateList()
+ filter.invalidateList("recordStatusBarState: " + StatusBarState.toString(newState))
// No need to call notificationEntryManager.updateNotifications; something else already
// does it for us when the keyguard state changes
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
index b9d23b4a344a..0833df505bf3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
@@ -192,11 +192,16 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable,
+ " reorderingAllowed " + wasReorderingAllowed + "->" + mReorderingAllowed
+ " when setting " + field + "=" + value);
}
- if ((mPipelineRunAllowed && mIsSuppressingPipelineRun)
- || (mReorderingAllowed && (mIsSuppressingGroupChange
- || isSuppressingSectionChange()
- || mIsSuppressingEntryReorder))) {
- mNotifStabilityManager.invalidateList();
+ if (mPipelineRunAllowed && mIsSuppressingPipelineRun) {
+ mNotifStabilityManager.invalidateList("pipeline run suppression ended");
+ } else if (mReorderingAllowed && (mIsSuppressingGroupChange
+ || isSuppressingSectionChange()
+ || mIsSuppressingEntryReorder)) {
+ String reason = "reorder suppression ended for"
+ + " group=" + mIsSuppressingGroupChange
+ + " section=" + isSuppressingSectionChange()
+ + " sort=" + mIsSuppressingEntryReorder;
+ mNotifStabilityManager.invalidateList(reason);
}
mVisualStabilityProvider.setReorderingAllowed(mReorderingAllowed);
}
@@ -241,7 +246,7 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable,
now + ALLOW_SECTION_CHANGE_TIMEOUT));
if (!wasSectionChangeAllowed) {
- mNotifStabilityManager.invalidateList();
+ mNotifStabilityManager.invalidateList("temporarilyAllowSectionChanges");
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.kt
index 567ec85cf6c7..08e21e8f668e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.kt
@@ -42,9 +42,9 @@ interface NotifInflater {
/**
* Request to stop the inflation of an entry. For example, called when a notification is
- * removed and no longer needs to be inflated.
+ * removed and no longer needs to be inflated. Returns whether anything may have been aborted.
*/
- fun abortInflation(entry: NotificationEntry)
+ fun abortInflation(entry: NotificationEntry): Boolean
/**
* Called to let the system remove the content views from the notification row.
@@ -62,4 +62,4 @@ interface NotifInflater {
* A class holding parameters used when inflating the notification row
*/
class Params(val isLowPriority: Boolean, val reason: String)
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
index 10a627d65b83..4c406e3ba0b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
@@ -25,8 +25,15 @@ import com.android.systemui.statusbar.notification.NotifPipelineFlags
import com.android.systemui.statusbar.notification.collection.GroupEntry
import com.android.systemui.statusbar.notification.collection.ListEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.StateName
+import com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.getStateName
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifComparator
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifStabilityManager
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable
import com.android.systemui.statusbar.notification.logKey
import com.android.systemui.util.Compile
import javax.inject.Inject
@@ -60,68 +67,63 @@ class ShadeListBuilderLogger @Inject constructor(
})
}
- fun logPreRenderInvalidated(filterName: String, pipelineState: Int) {
+ private fun logPluggableInvalidated(
+ type: String,
+ pluggable: Pluggable<*>,
+ @StateName pipelineState: Int,
+ reason: String?
+ ) {
buffer.log(TAG, DEBUG, {
- str1 = filterName
+ str1 = type
+ str2 = pluggable.name
int1 = pipelineState
+ str3 = reason
}, {
- """Pre-render Invalidator "$str1" invalidated; pipeline state is $int1"""
+ """Invalidated while ${getStateName(int1)} by $str1 "$str2" because $str3"""
})
}
- fun logPreGroupFilterInvalidated(filterName: String, pipelineState: Int) {
- buffer.log(TAG, DEBUG, {
- str1 = filterName
- int1 = pipelineState
- }, {
- """Pre-group NotifFilter "$str1" invalidated; pipeline state is $int1"""
- })
- }
+ fun logPreRenderInvalidated(
+ invalidator: Invalidator,
+ @StateName pipelineState: Int,
+ reason: String?
+ ) = logPluggableInvalidated("Pre-render Invalidator", invalidator, pipelineState, reason)
- fun logReorderingAllowedInvalidated(name: String, pipelineState: Int) {
- buffer.log(TAG, DEBUG, {
- str1 = name
- int1 = pipelineState
- }, {
- """ReorderingNowAllowed "$str1" invalidated; pipeline state is $int1"""
- })
- }
+ fun logPreGroupFilterInvalidated(
+ filter: NotifFilter,
+ @StateName pipelineState: Int,
+ reason: String?
+ ) = logPluggableInvalidated("Pre-group NotifFilter", filter, pipelineState, reason)
- fun logPromoterInvalidated(name: String, pipelineState: Int) {
- buffer.log(TAG, DEBUG, {
- str1 = name
- int1 = pipelineState
- }, {
- """NotifPromoter "$str1" invalidated; pipeline state is $int1"""
- })
- }
+ fun logReorderingAllowedInvalidated(
+ stabilityManager: NotifStabilityManager,
+ @StateName pipelineState: Int,
+ reason: String?
+ ) = logPluggableInvalidated("ReorderingNowAllowed", stabilityManager, pipelineState, reason)
- fun logNotifSectionInvalidated(name: String, pipelineState: Int) {
- buffer.log(TAG, DEBUG, {
- str1 = name
- int1 = pipelineState
- }, {
- """NotifSection "$str1" invalidated; pipeline state is $int1"""
- })
- }
+ fun logPromoterInvalidated(
+ promoter: NotifPromoter,
+ @StateName pipelineState: Int,
+ reason: String?
+ ) = logPluggableInvalidated("NotifPromoter", promoter, pipelineState, reason)
- fun logNotifComparatorInvalidated(name: String, pipelineState: Int) {
- buffer.log(TAG, DEBUG, {
- str1 = name
- int1 = pipelineState
- }, {
- """NotifComparator "$str1" invalidated; pipeline state is $int1"""
- })
- }
+ fun logNotifSectionInvalidated(
+ sectioner: NotifSectioner,
+ @StateName pipelineState: Int,
+ reason: String?
+ ) = logPluggableInvalidated("NotifSection", sectioner, pipelineState, reason)
- fun logFinalizeFilterInvalidated(name: String, pipelineState: Int) {
- buffer.log(TAG, DEBUG, {
- str1 = name
- int1 = pipelineState
- }, {
- """Finalize NotifFilter "$str1" invalidated; pipeline state is $int1"""
- })
- }
+ fun logNotifComparatorInvalidated(
+ comparator: NotifComparator,
+ @StateName pipelineState: Int,
+ reason: String?
+ ) = logPluggableInvalidated("NotifComparator", comparator, pipelineState, reason)
+
+ fun logFinalizeFilterInvalidated(
+ filter: NotifFilter,
+ @StateName pipelineState: Int,
+ reason: String?
+ ) = logPluggableInvalidated("Finalize NotifFilter", filter, pipelineState, reason)
fun logDuplicateSummary(
buildId: Int,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java
index b981a9621526..966ab4c61b50 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java
@@ -49,10 +49,10 @@ public abstract class Pluggable<This> {
* Call this method when something has caused this pluggable's behavior to change. The pipeline
* will be re-run.
*/
- public final void invalidateList() {
+ public final void invalidateList(@Nullable String reason) {
if (mListener != null) {
Trace.beginSection("Pluggable<" + mName + ">.invalidateList");
- mListener.onPluggableInvalidated((This) this);
+ mListener.onPluggableInvalidated((This) this, reason);
Trace.endSection();
}
}
@@ -74,7 +74,7 @@ public abstract class Pluggable<This> {
* @param <T> The type of pluggable that is being listened to.
*/
public interface PluggableListener<T> {
- /** Called whenever {@link #invalidateList()} is called on this pluggable. */
- void onPluggableInvalidated(T pluggable);
+ /** Called whenever {@link #invalidateList(String)} is called on this pluggable. */
+ void onPluggableInvalidated(T pluggable, @Nullable String reason);
}
}
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 2daa4759457d..6258deda804f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -2721,7 +2721,8 @@ public class CentralSurfacesImpl extends CoreStartable implements
@Override
public void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction,
boolean afterKeyguardGone) {
- if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_ASLEEP
+ if (!action.willRunAnimationOnKeyguard()
+ && mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_ASLEEP
&& mKeyguardStateController.canDismissLockScreen()
&& !mStatusBarStateController.leaveOpenOnKeyguardHide()
&& mDozeServiceHost.isPulsing()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
index 5bd20ff2d090..a29ba916eb41 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
@@ -68,6 +68,7 @@ public class BrightnessMirrorController
mBrightnessMirror.setVisibility(View.INVISIBLE);
});
mVisibilityCallback = visibilityCallback;
+ updateResources();
}
public void showMirror() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt
new file mode 100644
index 000000000000..ca94ea826782
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.camera
+
+import android.app.ActivityManager
+import android.app.IActivityTaskManager
+import android.content.ComponentName
+import android.content.ContentResolver
+import android.content.Intent
+import android.content.pm.ActivityInfo
+import android.content.pm.PackageManager
+import android.content.pm.ResolveInfo
+import androidx.test.filters.SmallTest
+import com.android.systemui.ActivityIntentHelper
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.phone.CentralSurfaces
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.mockito.KotlinArgumentCaptor
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import com.google.common.truth.Truth.assertThat
+import com.google.common.util.concurrent.MoreExecutors
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mock
+import org.mockito.Mockito.any
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(JUnit4::class)
+class CameraGestureHelperTest : SysuiTestCase() {
+
+ @Mock
+ lateinit var centralSurfaces: CentralSurfaces
+ @Mock
+ lateinit var keyguardStateController: KeyguardStateController
+ @Mock
+ lateinit var packageManager: PackageManager
+ @Mock
+ lateinit var activityManager: ActivityManager
+ @Mock
+ lateinit var activityStarter: ActivityStarter
+ @Mock
+ lateinit var activityIntentHelper: ActivityIntentHelper
+ @Mock
+ lateinit var activityTaskManager: IActivityTaskManager
+ @Mock
+ lateinit var cameraIntents: CameraIntentsWrapper
+ @Mock
+ lateinit var contentResolver: ContentResolver
+
+ private lateinit var underTest: CameraGestureHelper
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ whenever(cameraIntents.getSecureCameraIntent()).thenReturn(
+ Intent(CameraIntents.DEFAULT_SECURE_CAMERA_INTENT_ACTION)
+ )
+ whenever(cameraIntents.getInsecureCameraIntent()).thenReturn(
+ Intent(CameraIntents.DEFAULT_INSECURE_CAMERA_INTENT_ACTION)
+ )
+
+ prepare()
+
+ underTest = CameraGestureHelper(
+ context = mock(),
+ centralSurfaces = centralSurfaces,
+ keyguardStateController = keyguardStateController,
+ packageManager = packageManager,
+ activityManager = activityManager,
+ activityStarter = activityStarter,
+ activityIntentHelper = activityIntentHelper,
+ activityTaskManager = activityTaskManager,
+ cameraIntents = cameraIntents,
+ contentResolver = contentResolver,
+ uiExecutor = MoreExecutors.directExecutor(),
+ )
+ }
+
+ /**
+ * Prepares for tests by setting up the various mocks to emulate a specific device state.
+ *
+ * <p>Safe to call multiple times in a single test (for example, once in [setUp] and once in the
+ * actual test case).
+ *
+ * @param isCameraAllowedByAdmin Whether the device administrator allows use of the camera app
+ * @param installedCameraAppCount The number of installed camera apps on the device
+ * @param isUsingSecureScreenLockOption Whether the user-controlled setting for Screen Lock is
+ * set with a "secure" option that requires the user to provide some secret/credentials to be
+ * able to unlock the device, for example "Face Unlock", "PIN", or "Password". Examples of
+ * non-secure options are "None" and "Swipe"
+ * @param isCameraActivityRunningOnTop Whether the camera activity is running at the top of the
+ * most recent/current task of activities
+ * @param isTaskListEmpty Whether there are no active activity tasks at all. Note that this is
+ * treated as `false` if [isCameraActivityRunningOnTop] is set to `true`
+ */
+ private fun prepare(
+ isCameraAllowedByAdmin: Boolean = true,
+ installedCameraAppCount: Int = 1,
+ isUsingSecureScreenLockOption: Boolean = true,
+ isCameraActivityRunningOnTop: Boolean = false,
+ isTaskListEmpty: Boolean = false,
+ ) {
+ whenever(centralSurfaces.isCameraAllowedByAdmin).thenReturn(isCameraAllowedByAdmin)
+
+ whenever(activityIntentHelper.wouldLaunchResolverActivity(any(), anyInt()))
+ .thenReturn(installedCameraAppCount > 1)
+
+ whenever(keyguardStateController.isMethodSecure).thenReturn(isUsingSecureScreenLockOption)
+ whenever(keyguardStateController.canDismissLockScreen())
+ .thenReturn(!isUsingSecureScreenLockOption)
+
+ if (installedCameraAppCount >= 1) {
+ val resolveInfo = ResolveInfo().apply {
+ this.activityInfo = ActivityInfo().apply {
+ packageName = CAMERA_APP_PACKAGE_NAME
+ }
+ }
+ whenever(packageManager.resolveActivityAsUser(any(), anyInt(), anyInt())).thenReturn(
+ resolveInfo
+ )
+ } else {
+ whenever(packageManager.resolveActivityAsUser(any(), anyInt(), anyInt())).thenReturn(
+ null
+ )
+ }
+
+ when {
+ isCameraActivityRunningOnTop -> {
+ val runningTaskInfo = ActivityManager.RunningTaskInfo().apply {
+ topActivity = ComponentName(CAMERA_APP_PACKAGE_NAME, "cameraActivity")
+ }
+ whenever(activityManager.getRunningTasks(anyInt())).thenReturn(
+ listOf(
+ runningTaskInfo
+ )
+ )
+ }
+ isTaskListEmpty -> {
+ whenever(activityManager.getRunningTasks(anyInt())).thenReturn(emptyList())
+ }
+ else -> {
+ whenever(activityManager.getRunningTasks(anyInt())).thenReturn(listOf())
+ }
+ }
+ }
+
+ @Test
+ fun `canCameraGestureBeLaunched - status bar state is keyguard - returns true`() {
+ assertThat(underTest.canCameraGestureBeLaunched(StatusBarState.KEYGUARD)).isTrue()
+ }
+
+ @Test
+ fun `canCameraGestureBeLaunched - state is shade-locked - returns true`() {
+ assertThat(underTest.canCameraGestureBeLaunched(StatusBarState.SHADE_LOCKED)).isTrue()
+ }
+
+ @Test
+ fun `canCameraGestureBeLaunched - state is keyguard - camera activity on top - returns true`() {
+ prepare(isCameraActivityRunningOnTop = true)
+
+ assertThat(underTest.canCameraGestureBeLaunched(StatusBarState.KEYGUARD)).isTrue()
+ }
+
+ @Test
+ fun `canCameraGestureBeLaunched - state is shade-locked - camera activity on top - true`() {
+ prepare(isCameraActivityRunningOnTop = true)
+
+ assertThat(underTest.canCameraGestureBeLaunched(StatusBarState.SHADE_LOCKED)).isTrue()
+ }
+
+ @Test
+ fun `canCameraGestureBeLaunched - not allowed by admin - returns false`() {
+ prepare(isCameraAllowedByAdmin = false)
+
+ assertThat(underTest.canCameraGestureBeLaunched(StatusBarState.KEYGUARD)).isFalse()
+ }
+
+ @Test
+ fun `canCameraGestureBeLaunched - intent does not resolve to any app - returns false`() {
+ prepare(installedCameraAppCount = 0)
+
+ assertThat(underTest.canCameraGestureBeLaunched(StatusBarState.KEYGUARD)).isFalse()
+ }
+
+ @Test
+ fun `canCameraGestureBeLaunched - state is shade - no running tasks - returns true`() {
+ prepare(isCameraActivityRunningOnTop = false, isTaskListEmpty = true)
+
+ assertThat(underTest.canCameraGestureBeLaunched(StatusBarState.SHADE)).isTrue()
+ }
+
+ @Test
+ fun `canCameraGestureBeLaunched - state is shade - camera activity on top - returns false`() {
+ prepare(isCameraActivityRunningOnTop = true)
+
+ assertThat(underTest.canCameraGestureBeLaunched(StatusBarState.SHADE)).isFalse()
+ }
+
+ @Test
+ fun `canCameraGestureBeLaunched - state is shade - camera activity not on top - true`() {
+ assertThat(underTest.canCameraGestureBeLaunched(StatusBarState.SHADE)).isTrue()
+ }
+
+ @Test
+ fun `launchCamera - only one camera app installed - using secure screen lock option`() {
+ val source = 1337
+
+ underTest.launchCamera(source)
+
+ assertActivityStarting(isSecure = true, source = source)
+ }
+
+ @Test
+ fun `launchCamera - only one camera app installed - using non-secure screen lock option`() {
+ prepare(isUsingSecureScreenLockOption = false)
+ val source = 1337
+
+ underTest.launchCamera(source)
+
+ assertActivityStarting(isSecure = false, source = source)
+ }
+
+ @Test
+ fun `launchCamera - multiple camera apps installed - using secure screen lock option`() {
+ prepare(installedCameraAppCount = 2)
+ val source = 1337
+
+ underTest.launchCamera(source)
+
+ assertActivityStarting(
+ isSecure = true,
+ source = source,
+ moreThanOneCameraAppInstalled = true
+ )
+ }
+
+ @Test
+ fun `launchCamera - multiple camera apps installed - using non-secure screen lock option`() {
+ prepare(
+ isUsingSecureScreenLockOption = false,
+ installedCameraAppCount = 2,
+ )
+ val source = 1337
+
+ underTest.launchCamera(source)
+
+ assertActivityStarting(
+ isSecure = false,
+ moreThanOneCameraAppInstalled = true,
+ source = source
+ )
+ }
+
+ private fun assertActivityStarting(
+ isSecure: Boolean,
+ source: Int,
+ moreThanOneCameraAppInstalled: Boolean = false,
+ ) {
+ val intentCaptor = KotlinArgumentCaptor(Intent::class.java)
+ if (isSecure && !moreThanOneCameraAppInstalled) {
+ verify(activityTaskManager).startActivityAsUser(
+ any(),
+ any(),
+ any(),
+ intentCaptor.capture(),
+ any(),
+ any(),
+ any(),
+ anyInt(),
+ anyInt(),
+ any(),
+ any(),
+ anyInt()
+ )
+ } else {
+ verify(activityStarter).startActivity(intentCaptor.capture(), eq(false))
+ }
+ val intent = intentCaptor.value
+
+ assertThat(CameraIntents.isSecureCameraIntent(intent)).isEqualTo(isSecure)
+ assertThat(intent.getIntExtra(CameraGestureHelper.EXTRA_CAMERA_LAUNCH_SOURCE, -1))
+ .isEqualTo(source)
+ }
+
+ companion object {
+ private const val CAMERA_APP_PACKAGE_NAME = "cameraAppPackageName"
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
index 59475cf0cb90..226182961934 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
@@ -71,7 +71,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
@Before
public void setUp() {
- mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController, mMediaOutputDialog);
+ mMediaOutputAdapter = new MediaOutputAdapter(mMediaOutputController);
mViewHolder = (MediaOutputAdapter.MediaDeviceViewHolder) mMediaOutputAdapter
.onCreateViewHolder(new LinearLayout(mContext), 0);
mSpyMediaOutputSeekbar = spy(mViewHolder.mSeekBar);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupAdapterTest.java
deleted file mode 100644
index 9256cd32291f..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupAdapterTest.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.media.dialog;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.graphics.drawable.Icon;
-import android.testing.AndroidTestingRunner;
-import android.view.View;
-import android.widget.LinearLayout;
-
-import androidx.core.graphics.drawable.IconCompat;
-import androidx.test.filters.SmallTest;
-
-import com.android.settingslib.media.MediaDevice;
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-public class MediaOutputGroupAdapterTest extends SysuiTestCase {
-
- private static final String TEST_DEVICE_NAME_1 = "test_device_name_1";
- private static final String TEST_DEVICE_NAME_2 = "test_device_name_2";
- private static final String TEST_DEVICE_ID_1 = "test_device_id_1";
- private static final String TEST_DEVICE_ID_2 = "test_device_id_2";
- private static final int TEST_VOLUME = 10;
- private static final int TEST_MAX_VOLUME = 50;
-
- // Mock
- private MediaOutputController mMediaOutputController = mock(MediaOutputController.class);
- private MediaDevice mMediaDevice1 = mock(MediaDevice.class);
- private MediaDevice mMediaDevice2 = mock(MediaDevice.class);
- private Icon mIcon = mock(Icon.class);
- private IconCompat mIconCompat = mock(IconCompat.class);
-
- private MediaOutputGroupAdapter mGroupAdapter;
- private MediaOutputGroupAdapter.GroupViewHolder mGroupViewHolder;
- private List<MediaDevice> mGroupMediaDevices = new ArrayList<>();
- private List<MediaDevice> mSelectableMediaDevices = new ArrayList<>();
- private List<MediaDevice> mSelectedMediaDevices = new ArrayList<>();
- private List<MediaDevice> mDeselectableMediaDevices = new ArrayList<>();
-
- @Before
- public void setUp() {
- when(mMediaOutputController.getGroupMediaDevices()).thenReturn(mGroupMediaDevices);
- when(mMediaOutputController.getDeviceIconCompat(mMediaDevice1)).thenReturn(mIconCompat);
- when(mMediaOutputController.getDeviceIconCompat(mMediaDevice2)).thenReturn(mIconCompat);
- when(mMediaOutputController.getSelectableMediaDevice()).thenReturn(mSelectableMediaDevices);
- when(mMediaOutputController.getSelectedMediaDevice()).thenReturn(mSelectedMediaDevices);
- when(mMediaOutputController.getDeselectableMediaDevice()).thenReturn(
- mDeselectableMediaDevices);
- when(mIconCompat.toIcon(mContext)).thenReturn(mIcon);
- when(mMediaDevice1.getName()).thenReturn(TEST_DEVICE_NAME_1);
- when(mMediaDevice1.getId()).thenReturn(TEST_DEVICE_ID_1);
- when(mMediaDevice2.getName()).thenReturn(TEST_DEVICE_NAME_2);
- when(mMediaDevice2.getId()).thenReturn(TEST_DEVICE_ID_2);
- mGroupMediaDevices.add(mMediaDevice1);
- mGroupMediaDevices.add(mMediaDevice2);
- mSelectedMediaDevices.add(mMediaDevice1);
- mSelectableMediaDevices.add(mMediaDevice2);
- mDeselectableMediaDevices.add(mMediaDevice1);
-
- mGroupAdapter = new MediaOutputGroupAdapter(mMediaOutputController);
- mGroupViewHolder = (MediaOutputGroupAdapter.GroupViewHolder) mGroupAdapter
- .onCreateViewHolder(new LinearLayout(mContext), 0);
- }
-
- @Test
- public void onBindViewHolder_verifyGroupItem() {
- mGroupAdapter.onBindViewHolder(mGroupViewHolder, 0);
-
- assertThat(mGroupViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
- assertThat(mGroupViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
- assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
- assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
- assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mGroupViewHolder.mTwoLineTitleText.getText()).isEqualTo(mContext.getText(
- R.string.media_output_dialog_group));
- }
-
- @Test
- public void onBindViewHolder_singleSelectedDevice_verifyView() {
- mGroupAdapter.onBindViewHolder(mGroupViewHolder, 1);
-
- assertThat(mGroupViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
- assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
- assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
- assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mGroupViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_1);
- assertThat(mGroupViewHolder.mCheckBox.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mGroupViewHolder.mCheckBox.isChecked()).isTrue();
- // Disabled checkBox
- assertThat(mGroupViewHolder.mCheckBox.isEnabled()).isFalse();
- }
-
- @Test
- public void onBindViewHolder_multipleSelectedDevice_verifyView() {
- mSelectedMediaDevices.clear();
- mSelectedMediaDevices.add(mMediaDevice1);
- mSelectedMediaDevices.add(mMediaDevice2);
- mDeselectableMediaDevices.clear();
- mDeselectableMediaDevices.add(mMediaDevice1);
- mDeselectableMediaDevices.add(mMediaDevice2);
- mSelectableMediaDevices.clear();
-
- mGroupAdapter.onBindViewHolder(mGroupViewHolder, 1);
-
- assertThat(mGroupViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
- assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
- assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
- assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mGroupViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_1);
- assertThat(mGroupViewHolder.mCheckBox.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mGroupViewHolder.mCheckBox.isChecked()).isTrue();
- // Enabled checkBox
- assertThat(mGroupViewHolder.mCheckBox.isEnabled()).isTrue();
- }
-
- @Test
- public void onBindViewHolder_notDeselectedDevice_verifyView() {
- mSelectedMediaDevices.clear();
- mSelectedMediaDevices.add(mMediaDevice1);
- mSelectedMediaDevices.add(mMediaDevice2);
- mDeselectableMediaDevices.clear();
- mDeselectableMediaDevices.add(mMediaDevice1);
- mSelectableMediaDevices.clear();
-
- mGroupAdapter.onBindViewHolder(mGroupViewHolder, 2);
-
- assertThat(mGroupViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
- assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
- assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
- assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mGroupViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_2);
- assertThat(mGroupViewHolder.mCheckBox.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mGroupViewHolder.mCheckBox.isChecked()).isTrue();
- // Disabled checkBox
- assertThat(mGroupViewHolder.mCheckBox.isEnabled()).isFalse();
- }
-
- @Test
- public void onBindViewHolder_selectableDevice_verifyCheckBox() {
- mGroupAdapter.onBindViewHolder(mGroupViewHolder, 2);
-
- assertThat(mGroupViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
- assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
- assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
- assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mGroupViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_2);
- assertThat(mGroupViewHolder.mCheckBox.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(mGroupViewHolder.mCheckBox.isChecked()).isFalse();
- // Enabled checkBox
- assertThat(mGroupViewHolder.mCheckBox.isEnabled()).isTrue();
- }
-
- @Test
- public void onBindViewHolder_verifyDeviceVolume() {
- when(mMediaDevice1.getCurrentVolume()).thenReturn(TEST_VOLUME);
- when(mMediaDevice1.getMaxVolume()).thenReturn(TEST_MAX_VOLUME);
- mGroupViewHolder.mSeekBar.setVisibility(View.VISIBLE);
-
- mGroupAdapter.onBindViewHolder(mGroupViewHolder, 1);
-
- assertThat(mGroupViewHolder.mSeekBar.getVolume()).isEqualTo(TEST_VOLUME);
- }
-
- @Test
- public void clickSelectedDevice_verifyRemoveDeviceFromPlayMedia() {
- mSelectedMediaDevices.clear();
- mSelectedMediaDevices.add(mMediaDevice1);
- mSelectedMediaDevices.add(mMediaDevice2);
- mDeselectableMediaDevices.clear();
- mDeselectableMediaDevices.add(mMediaDevice1);
- mDeselectableMediaDevices.add(mMediaDevice2);
- mSelectableMediaDevices.clear();
-
- mGroupAdapter.onBindViewHolder(mGroupViewHolder, 1);
- mGroupViewHolder.mCheckBox.performClick();
-
- verify(mMediaOutputController).removeDeviceFromPlayMedia(mMediaDevice1);
- }
-
- @Test
- public void clickSelectabelDevice_verifyAddDeviceToPlayMedia() {
- mGroupAdapter.onBindViewHolder(mGroupViewHolder, 2);
-
- mGroupViewHolder.mCheckBox.performClick();
-
- verify(mMediaOutputController).addDeviceToPlayMedia(mMediaDevice2);
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java
deleted file mode 100644
index 4534ae6448ec..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.media.dialog;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import android.media.AudioManager;
-import android.media.session.MediaSessionManager;
-import android.os.PowerExemptionManager;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.view.View;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.settingslib.bluetooth.LocalBluetoothManager;
-import com.android.settingslib.media.LocalMediaManager;
-import com.android.settingslib.media.MediaDevice;
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.animation.DialogLaunchAnimator;
-import com.android.systemui.broadcast.BroadcastSender;
-import com.android.systemui.media.nearby.NearbyMediaDevicesManager;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class MediaOutputGroupDialogTest extends SysuiTestCase {
-
- private static final String TEST_PACKAGE = "test_package";
-
- // Mock
- private MediaSessionManager mMediaSessionManager = mock(MediaSessionManager.class);
- private LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class);
- private ActivityStarter mStarter = mock(ActivityStarter.class);
- private BroadcastSender mBroadcastSender = mock(BroadcastSender.class);
- private LocalMediaManager mLocalMediaManager = mock(LocalMediaManager.class);
- private MediaDevice mMediaDevice = mock(MediaDevice.class);
- private MediaDevice mMediaDevice1 = mock(MediaDevice.class);
- private NotificationEntryManager mNotificationEntryManager =
- mock(NotificationEntryManager.class);
- private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class);
- private NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock(
- NearbyMediaDevicesManager.class);
- private final AudioManager mAudioManager = mock(AudioManager.class);
- private PowerExemptionManager mPowerExemptionManager = mock(PowerExemptionManager.class);
-
- private MediaOutputGroupDialog mMediaOutputGroupDialog;
- private MediaOutputController mMediaOutputController;
- private List<MediaDevice> mMediaDevices = new ArrayList<>();
-
- @Before
- public void setUp() {
- mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE,
- mMediaSessionManager, mLocalBluetoothManager, mStarter,
- mNotificationEntryManager, mDialogLaunchAnimator,
- Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager);
- mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
- mMediaOutputGroupDialog = new MediaOutputGroupDialog(mContext, false, mBroadcastSender,
- mMediaOutputController);
- mMediaOutputGroupDialog.show();
- when(mLocalMediaManager.getSelectedMediaDevice()).thenReturn(mMediaDevices);
- }
-
- @After
- public void tearDown() {
- mMediaOutputGroupDialog.dismissDialog();
- }
-
- @Test
- public void getStopButtonVisibility_returnVisible() {
- assertThat(mMediaOutputGroupDialog.getStopButtonVisibility()).isEqualTo(View.VISIBLE);
- }
-
- @Test
- public void getHeaderSubtitle_singleDevice_verifyTitle() {
- mMediaDevices.add(mMediaDevice);
-
- assertThat(mMediaOutputGroupDialog.getHeaderSubtitle()).isEqualTo(
- mContext.getText(R.string.media_output_dialog_single_device));
- }
-
- @Test
- public void getHeaderSubtitle_multipleDevices_verifyTitle() {
- mMediaDevices.add(mMediaDevice);
- mMediaDevices.add(mMediaDevice1);
-
- assertThat(mMediaOutputGroupDialog.getHeaderSubtitle()).isEqualTo(mContext.getString(
- R.string.media_output_dialog_multiple_devices, mMediaDevices.size()));
- }
-
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
index 555adfdfdc31..dfa38abc1ff8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
@@ -1028,37 +1028,37 @@ public class ShadeListBuilderTest extends SysuiTestCase {
// WHEN each pluggable is invalidated THEN the list is re-rendered
clearInvocations(mOnRenderListListener);
- packageFilter.invalidateList();
+ packageFilter.invalidateList(null);
assertTrue(mPipelineChoreographer.isScheduled());
mPipelineChoreographer.runIfScheduled();
verify(mOnRenderListListener).onRenderList(anyList());
clearInvocations(mOnRenderListListener);
- idPromoter.invalidateList();
+ idPromoter.invalidateList(null);
assertTrue(mPipelineChoreographer.isScheduled());
mPipelineChoreographer.runIfScheduled();
verify(mOnRenderListListener).onRenderList(anyList());
clearInvocations(mOnRenderListListener);
- section.invalidateList();
+ section.invalidateList(null);
assertTrue(mPipelineChoreographer.isScheduled());
mPipelineChoreographer.runIfScheduled();
verify(mOnRenderListListener).onRenderList(anyList());
clearInvocations(mOnRenderListListener);
- hypeComparator.invalidateList();
+ hypeComparator.invalidateList(null);
assertTrue(mPipelineChoreographer.isScheduled());
mPipelineChoreographer.runIfScheduled();
verify(mOnRenderListListener).onRenderList(anyList());
clearInvocations(mOnRenderListListener);
- sectionComparator.invalidateList();
+ sectionComparator.invalidateList(null);
assertTrue(mPipelineChoreographer.isScheduled());
mPipelineChoreographer.runIfScheduled();
verify(mOnRenderListListener).onRenderList(anyList());
clearInvocations(mOnRenderListListener);
- preRenderInvalidator.invalidateList();
+ preRenderInvalidator.invalidateList(null);
assertTrue(mPipelineChoreographer.isScheduled());
mPipelineChoreographer.runIfScheduled();
verify(mOnRenderListListener).onRenderList(anyList());
@@ -1584,7 +1584,7 @@ public class ShadeListBuilderTest extends SysuiTestCase {
// WHEN visual stability manager allows group changes again
mStabilityManager.setAllowGroupChanges(true);
- mStabilityManager.invalidateList();
+ mStabilityManager.invalidateList(null);
mPipelineChoreographer.runIfScheduled();
// THEN entries are grouped
@@ -1623,7 +1623,7 @@ public class ShadeListBuilderTest extends SysuiTestCase {
// WHEN section changes are allowed again
mStabilityManager.setAllowSectionChanges(true);
- mStabilityManager.invalidateList();
+ mStabilityManager.invalidateList(null);
mPipelineChoreographer.runIfScheduled();
// THEN the section updates
@@ -1719,7 +1719,7 @@ public class ShadeListBuilderTest extends SysuiTestCase {
public void testOutOfOrderPreGroupFilterInvalidationThrows() {
// GIVEN a PreGroupNotifFilter that gets invalidated during the grouping stage
NotifFilter filter = new PackageFilter(PACKAGE_5);
- OnBeforeTransformGroupsListener listener = (list) -> filter.invalidateList();
+ OnBeforeTransformGroupsListener listener = (list) -> filter.invalidateList(null);
mListBuilder.addPreGroupFilter(filter);
mListBuilder.addOnBeforeTransformGroupsListener(listener);
@@ -1735,7 +1735,7 @@ public class ShadeListBuilderTest extends SysuiTestCase {
// GIVEN a NotifPromoter that gets invalidated during the sorting stage
NotifPromoter promoter = new IdPromoter(47);
OnBeforeSortListener listener =
- (list) -> promoter.invalidateList();
+ (list) -> promoter.invalidateList(null);
mListBuilder.addPromoter(promoter);
mListBuilder.addOnBeforeSortListener(listener);
@@ -1751,7 +1751,7 @@ public class ShadeListBuilderTest extends SysuiTestCase {
// GIVEN a NotifComparator that gets invalidated during the finalizing stage
NotifComparator comparator = new HypeComparator(PACKAGE_5);
OnBeforeRenderListListener listener =
- (list) -> comparator.invalidateList();
+ (list) -> comparator.invalidateList(null);
mListBuilder.setComparators(singletonList(comparator));
mListBuilder.addOnBeforeRenderListListener(listener);
@@ -1766,7 +1766,7 @@ public class ShadeListBuilderTest extends SysuiTestCase {
public void testOutOfOrderPreRenderFilterInvalidationThrows() {
// GIVEN a PreRenderNotifFilter that gets invalidated during the finalizing stage
NotifFilter filter = new PackageFilter(PACKAGE_5);
- OnBeforeRenderListListener listener = (list) -> filter.invalidateList();
+ OnBeforeRenderListListener listener = (list) -> filter.invalidateList(null);
mListBuilder.addFinalizeFilter(filter);
mListBuilder.addOnBeforeRenderListListener(listener);
@@ -1903,7 +1903,7 @@ public class ShadeListBuilderTest extends SysuiTestCase {
public void testInOrderPreRenderFilter() {
// GIVEN a PreRenderFilter that gets invalidated during the grouping stage
NotifFilter filter = new PackageFilter(PACKAGE_5);
- OnBeforeTransformGroupsListener listener = (list) -> filter.invalidateList();
+ OnBeforeTransformGroupsListener listener = (list) -> filter.invalidateList(null);
mListBuilder.addFinalizeFilter(filter);
mListBuilder.addOnBeforeTransformGroupsListener(listener);
@@ -1936,8 +1936,8 @@ public class ShadeListBuilderTest extends SysuiTestCase {
mListBuilder.addFinalizeFilter(filter2);
// WHEN both filters invalidate
- filter1.invalidateList();
- filter2.invalidateList();
+ filter1.invalidateList(null);
+ filter2.invalidateList(null);
// THEN the pipeline choreographer is scheduled to evaluate, AND the pipeline hasn't
// actually run.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinatorTest.java
index d21053bcd691..27542a462d36 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HideNotifsForOtherUsersCoordinatorTest.java
@@ -18,7 +18,9 @@ package com.android.systemui.statusbar.notification.collection.coordinator;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -51,7 +53,6 @@ public class HideNotifsForOtherUsersCoordinatorTest extends SysuiTestCase {
@Mock private NotificationLockscreenUserManager mLockscreenUserManager;
@Mock private NotifPipeline mNotifPipeline;
@Mock private PluggableListener<NotifFilter> mInvalidationListener;
- @Mock private SharedCoordinatorLogger mLogger;
@Captor private ArgumentCaptor<UserChangedListener> mUserChangedListenerCaptor;
@Captor private ArgumentCaptor<NotifFilter> mNotifFilterCaptor;
@@ -66,7 +67,7 @@ public class HideNotifsForOtherUsersCoordinatorTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
HideNotifsForOtherUsersCoordinator coordinator =
- new HideNotifsForOtherUsersCoordinator(mLockscreenUserManager, mLogger);
+ new HideNotifsForOtherUsersCoordinator(mLockscreenUserManager);
coordinator.attach(mNotifPipeline);
verify(mLockscreenUserManager).addUserChangedListener(mUserChangedListenerCaptor.capture());
@@ -102,6 +103,6 @@ public class HideNotifsForOtherUsersCoordinatorTest extends SysuiTestCase {
mCapturedUserChangeListener.onCurrentProfilesChanged(new SparseArray<>());
// THEN the filter is invalidated
- verify(mInvalidationListener).onPluggableInvalidated(mCapturedNotifFilter);
+ verify(mInvalidationListener).onPluggableInvalidated(eq(mCapturedNotifFilter), any());
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt
index 8c506a6d16ae..7e2e6f619946 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt
@@ -41,7 +41,6 @@ class KeyguardCoordinatorTest : SysuiTestCase() {
private val notifPipeline: NotifPipeline = mock()
private val keyguardNotifVisibilityProvider: KeyguardNotificationVisibilityProvider = mock()
private val sectionHeaderVisibilityProvider: SectionHeaderVisibilityProvider = mock()
- private val sharedCoordinatorLogger: SharedCoordinatorLogger = mock()
private val statusBarStateController: StatusBarStateController = mock()
private lateinit var onStateChangeListener: Consumer<String>
@@ -52,7 +51,6 @@ class KeyguardCoordinatorTest : SysuiTestCase() {
val keyguardCoordinator = KeyguardCoordinator(
keyguardNotifVisibilityProvider,
sectionHeaderVisibilityProvider,
- sharedCoordinatorLogger,
statusBarStateController
)
keyguardCoordinator.attach(notifPipeline)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
index a6d3719de5cc..f4adf6927e31 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
@@ -463,7 +463,8 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
}
@Override
- public void abortInflation(@NonNull NotificationEntry entry) {
+ public boolean abortInflation(@NonNull NotificationEntry entry) {
+ return false;
}
public InflationCallback getInflateCallback(NotificationEntry entry) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt
index a2d8e3ddba24..27be4c802aec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt
@@ -34,6 +34,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.withArgCaptor
import dagger.BindsInstance
@@ -79,7 +80,7 @@ class SensitiveContentCoordinatorTest : SysuiTestCase() {
dynamicPrivacyListener.onDynamicPrivacyChanged()
- verify(invalidationListener).onPluggableInvalidated(invalidator)
+ verify(invalidationListener).onPluggableInvalidated(eq(invalidator), any())
}
@Test
@@ -265,4 +266,4 @@ interface TestSensitiveContentCoordinatorComponent {
@BindsInstance keyguardStateController: KeyguardStateController
): TestSensitiveContentCoordinatorComponent
}
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt
index fdff6e9a52f3..d4f05050b6dd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt
@@ -35,21 +35,23 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
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.mockito.withArgCaptor
import com.android.systemui.util.time.FakeSystemClock
+import java.util.concurrent.TimeUnit
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.anyString
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
-import java.util.concurrent.TimeUnit
@SmallTest
class SmartspaceDedupingCoordinatorTest : SysuiTestCase() {
@@ -349,7 +351,7 @@ class SmartspaceDedupingCoordinatorTest : SysuiTestCase() {
// THEN the new pipeline is invalidated (but the old one isn't because it's not
// necessary) because the notif should no longer be filtered out
- verify(pluggableListener).onPluggableInvalidated(filter)
+ verify(pluggableListener).onPluggableInvalidated(eq(filter), any())
verify(notificationEntryManager, never()).updateNotifications(anyString())
assertFalse(filter.shouldFilterOut(entry2HasNotRecentlyAlerted, now))
}
@@ -387,7 +389,7 @@ class SmartspaceDedupingCoordinatorTest : SysuiTestCase() {
}
private fun verifyPipelinesInvalidated() {
- verify(pluggableListener).onPluggableInvalidated(filter)
+ verify(pluggableListener).onPluggableInvalidated(eq(filter), any())
verify(notificationEntryManager).updateNotifications(anyString())
}
@@ -396,7 +398,7 @@ class SmartspaceDedupingCoordinatorTest : SysuiTestCase() {
}
private fun verifyPipelinesNotInvalidated() {
- verify(pluggableListener, never()).onPluggableInvalidated(filter)
+ verify(pluggableListener, never()).onPluggableInvalidated(eq(filter), any())
verify(notificationEntryManager, never()).updateNotifications(anyString())
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
index 2f37f8928e79..96c40ecd3d81 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator;
import static junit.framework.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
@@ -55,6 +56,7 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.verification.VerificationMode;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@@ -130,7 +132,7 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
doAnswer(i -> {
mNotifStabilityManager.onBeginRun();
return null;
- }).when(mInvalidateListener).onPluggableInvalidated(eq(mNotifStabilityManager));
+ }).when(mInvalidateListener).onPluggableInvalidated(eq(mNotifStabilityManager), any());
}
@Test
@@ -280,7 +282,7 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
mCoordinator.temporarilyAllowSectionChanges(mEntry, mFakeSystemClock.uptimeMillis());
// THEN the notification list is invalidated
- verify(mInvalidateListener, times(1)).onPluggableInvalidated(mNotifStabilityManager);
+ verifyStabilityManagerWasInvalidated(times(1));
}
@Test
@@ -295,7 +297,7 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
mCoordinator.temporarilyAllowSectionChanges(mEntry, mFakeSystemClock.currentTimeMillis());
// THEN invalidate is not called because this entry was never suppressed from reordering
- verify(mInvalidateListener, never()).onPluggableInvalidated(mNotifStabilityManager);
+ verifyStabilityManagerWasInvalidated(never());
}
@Test
@@ -312,7 +314,7 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
// THEN invalidate is not called because this entry was never suppressed from reordering;
// THEN section changes are allowed for this notification
- verify(mInvalidateListener, never()).onPluggableInvalidated(mNotifStabilityManager);
+ verifyStabilityManagerWasInvalidated(never());
assertTrue(mNotifStabilityManager.isSectionChangeAllowed(mEntry));
// WHEN we're pulsing (now disallowing reordering)
@@ -341,13 +343,13 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
// WHEN we temporarily allow section changes for this notification entry
mCoordinator.temporarilyAllowSectionChanges(mEntry, mFakeSystemClock.currentTimeMillis());
// can now reorder, so invalidates
- verify(mInvalidateListener, times(1)).onPluggableInvalidated(mNotifStabilityManager);
+ verifyStabilityManagerWasInvalidated(times(1));
// WHEN reordering is now allowed because device isn't pulsing anymore
setPulsing(false);
// THEN invalidate isn't called a second time since reordering was already allowed
- verify(mInvalidateListener, times(1)).onPluggableInvalidated(mNotifStabilityManager);
+ verifyStabilityManagerWasInvalidated(times(1));
}
@Test
@@ -368,7 +370,7 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
// THEN we never see any calls to invalidate since there weren't any notifications that
// were being suppressed from grouping or section changes
- verify(mInvalidateListener, never()).onPluggableInvalidated(mNotifStabilityManager);
+ verifyStabilityManagerWasInvalidated(never());
}
@Test
@@ -386,7 +388,7 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
setPanelExpanded(false);
// invalidate is called because we were previously suppressing a group change
- verify(mInvalidateListener, times(1)).onPluggableInvalidated(mNotifStabilityManager);
+ verifyStabilityManagerWasInvalidated(times(1));
}
@Test
@@ -400,7 +402,7 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
setActivityLaunching(false);
// invalidate is called, b/c we were previously suppressing the pipeline from running
- verify(mInvalidateListener, times(1)).onPluggableInvalidated(mNotifStabilityManager);
+ verifyStabilityManagerWasInvalidated(times(1));
}
@Test
@@ -414,7 +416,7 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
setPanelCollapsing(false);
// invalidate is called, b/c we were previously suppressing the pipeline from running
- verify(mInvalidateListener, times(1)).onPluggableInvalidated(mNotifStabilityManager);
+ verifyStabilityManagerWasInvalidated(times(1));
}
@Test
@@ -426,7 +428,7 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
setPanelCollapsing(false);
// THEN invalidate is not called, b/c nothing has been suppressed
- verify(mInvalidateListener, never()).onPluggableInvalidated(mNotifStabilityManager);
+ verifyStabilityManagerWasInvalidated(never());
}
@Test
@@ -438,7 +440,7 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
setActivityLaunching(false);
// THEN invalidate is not called, b/c nothing has been suppressed
- verify(mInvalidateListener, never()).onPluggableInvalidated(mNotifStabilityManager);
+ verifyStabilityManagerWasInvalidated(never());
}
@Test
@@ -457,7 +459,7 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
setPanelExpanded(false);
// invalidate is called because we were previously suppressing an entry reorder
- verify(mInvalidateListener, times(1)).onPluggableInvalidated(mNotifStabilityManager);
+ verifyStabilityManagerWasInvalidated(times(1));
}
@Test
@@ -474,7 +476,7 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
setPanelExpanded(false);
// invalidate is not called because we were not told that an entry reorder was suppressed
- verify(mInvalidateListener, never()).onPluggableInvalidated(mNotifStabilityManager);
+ verifyStabilityManagerWasInvalidated(never());
}
@Test
@@ -499,6 +501,10 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
assertFalse(mNotifStabilityManager.isGroupPruneAllowed(mGroupEntry));
}
+ private void verifyStabilityManagerWasInvalidated(VerificationMode mode) {
+ verify(mInvalidateListener, mode).onPluggableInvalidated(eq(mNotifStabilityManager), any());
+ }
+
private void setActivityLaunching(boolean activityLaunching) {
mNotifPanelEventsCallback.onLaunchingActivityChanged(activityLaunching);
}
diff --git a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
index 1af8ad344190..84707a8d9c00 100644
--- a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
+++ b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
@@ -398,18 +398,7 @@ public class AppPredictionPerUserService extends
final IBinder.DeathRecipient mDeathRecipient;
private final RemoteCallbackList<IPredictionCallback> mCallbacks =
- new RemoteCallbackList<IPredictionCallback>() {
- @Override
- public void onCallbackDied(IPredictionCallback callback) {
- if (DEBUG) {
- Slog.d(TAG, "Binder died for session Id=" + mSessionId
- + " and callback=" + callback.asBinder());
- }
- if (mCallbacks.getRegisteredCallbackCount() == 0) {
- destroy();
- }
- }
- };
+ new RemoteCallbackList<>();
AppPredictionSessionInfo(
@NonNull final AppPredictionSessionId id,
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 1a1c265f568d..9d15ed33797f 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -5754,10 +5754,12 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
@Override
public void onImeParentChanged() {
synchronized (ImfLock.class) {
- // Hide the IME method menu when the IME surface parent will change in
- // case seeing the dialog dismiss flickering during the next focused window
- // starting the input connection.
- mMenuController.hideInputMethodMenu();
+ // Hide the IME method menu only when the IME surface parent is changed by the
+ // input target changed, in case seeing the dialog dismiss flickering during
+ // the next focused window starting the input connection.
+ if (mLastImeTargetWindow != mCurFocusedWindow) {
+ mMenuController.hideInputMethodMenu();
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index d4155d13992c..867be2427741 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -224,6 +224,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WIND
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
+import static com.android.server.wm.WindowManagerService.sEnableShellTransitions;
import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
@@ -3149,15 +3150,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mWillCloseOrEnterPip = willCloseOrEnterPip;
}
- /**
- * Returns whether this {@link ActivityRecord} is considered closing. Conditions are either
- * 1. Is this app animating and was requested to be hidden
- * 2. App is delayed closing since it might enter PIP.
- */
- boolean isClosingOrEnteringPip() {
- return (isAnimating(TRANSITION | PARENTS, ANIMATION_TYPE_APP_TRANSITION)
- && !mVisibleRequested) || mWillCloseOrEnterPip;
+ boolean willCloseOrEnterPip() {
+ return mWillCloseOrEnterPip;
}
+
/**
* @return Whether AppOps allows this package to enter picture-in-picture.
*/
@@ -5272,12 +5268,19 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
final int windowsCount = mChildren.size();
+ // With Shell-Transition, the activity will running a transition when it is visible.
+ // It won't be included when fromTransition is true means the call from finishTransition.
+ final boolean runningAnimation = sEnableShellTransitions ? visible
+ : isAnimating(PARENTS, ANIMATION_TYPE_APP_TRANSITION);
for (int i = 0; i < windowsCount; i++) {
- mChildren.get(i).onAppVisibilityChanged(visible, isAnimating(PARENTS,
- ANIMATION_TYPE_APP_TRANSITION));
+ mChildren.get(i).onAppVisibilityChanged(visible, runningAnimation);
}
setVisible(visible);
setVisibleRequested(visible);
+ ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "commitVisibility: %s: visible=%b"
+ + " visibleRequested=%b, isInTransition=%b, runningAnimation=%b, caller=%s",
+ this, isVisible(), mVisibleRequested, isInTransition(), runningAnimation,
+ Debug.getCallers(5));
if (!visible) {
stopFreezingScreen(true, true);
} else {
@@ -5300,9 +5303,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
task.dispatchTaskInfoChangedIfNeeded(false /* force */);
task = task.getParent().asTask();
}
- ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
- "commitVisibility: %s: visible=%b mVisibleRequested=%b", this,
- isVisible(), mVisibleRequested);
final DisplayContent displayContent = getDisplayContent();
displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
if (performLayout) {
diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
index 0d4cfa3a8128..3e6e06a27fdc 100644
--- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
@@ -234,7 +234,7 @@ final class ImeInsetsSourceProvider extends WindowContainerInsetsSourceProvider
//
private static boolean isImeLayeringTarget(@NonNull InsetsControlTarget target,
@NonNull InsetsControlTarget dcTarget) {
- return !dcTarget.getWindow().isClosing() && target == dcTarget;
+ return !isImeTargetWindowClosing(dcTarget.getWindow()) && target == dcTarget;
}
private static boolean isAboveImeLayeringTarget(@NonNull InsetsControlTarget target,
@@ -256,7 +256,14 @@ final class ImeInsetsSourceProvider extends WindowContainerInsetsSourceProvider
final InsetsControlTarget target = mDisplayContent.getImeTarget(IME_TARGET_CONTROL);
return target == mImeRequester
&& (mImeRequester.getWindow() == null
- || !mImeRequester.getWindow().isClosing());
+ || !isImeTargetWindowClosing(mImeRequester.getWindow()));
+ }
+
+ private static boolean isImeTargetWindowClosing(@NonNull WindowState win) {
+ return win.mAnimatingExit || win.mActivityRecord != null
+ && (win.mActivityRecord.isInTransition()
+ && !win.mActivityRecord.isVisibleRequested()
+ || win.mActivityRecord.willCloseOrEnterPip());
}
private boolean isTargetChangedWithinActivity(InsetsControlTarget target) {
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 4bbb1b1fb745..6bb5eceec84e 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -1235,8 +1235,12 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
+ " task=" + task);
return false;
}
- if (!ArrayUtils.contains(hop.getActivityTypes(), task.getActivityType())
- || !ArrayUtils.contains(hop.getWindowingModes(), task.getWindowingMode())) {
+ if (!ArrayUtils.isEmpty(hop.getActivityTypes())
+ && !ArrayUtils.contains(hop.getActivityTypes(), task.getActivityType())) {
+ return false;
+ }
+ if (!ArrayUtils.isEmpty(hop.getWindowingModes())
+ && !ArrayUtils.contains(hop.getWindowingModes(), task.getWindowingMode())) {
return false;
}
if (isLockTaskModeViolation(finalNewParent, task, isInLockTaskMode)) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 46091d842c2a..30d18ab04369 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3461,10 +3461,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return mClient.asBinder().isBinderAlive();
}
- boolean isClosing() {
- return mAnimatingExit || (mActivityRecord != null && mActivityRecord.isClosingOrEnteringPip());
- }
-
void sendAppVisibilityToClients() {
super.sendAppVisibilityToClients();
diff --git a/services/smartspace/java/com/android/server/smartspace/SmartspacePerUserService.java b/services/smartspace/java/com/android/server/smartspace/SmartspacePerUserService.java
index dcffc9e73c0e..f041fbd7bf90 100644
--- a/services/smartspace/java/com/android/server/smartspace/SmartspacePerUserService.java
+++ b/services/smartspace/java/com/android/server/smartspace/SmartspacePerUserService.java
@@ -334,18 +334,7 @@ public class SmartspacePerUserService extends
@NonNull
private final SmartspaceConfig mSmartspaceConfig;
private final RemoteCallbackList<ISmartspaceCallback> mCallbacks =
- new RemoteCallbackList<ISmartspaceCallback>() {
- @Override
- public void onCallbackDied(ISmartspaceCallback callback) {
- if (DEBUG) {
- Slog.d(TAG, "Binder died for session Id=" + mSessionId
- + " and callback=" + callback.asBinder());
- }
- if (mCallbacks.getRegisteredCallbackCount() == 0) {
- destroy();
- }
- }
- };
+ new RemoteCallbackList<>();
SmartspaceSessionInfo(
@NonNull final SmartspaceSessionId id,
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 40e266c71328..11a7c7ddf778 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -2118,7 +2118,6 @@ public class DisplayContentTests extends WindowTestsBase {
final WindowState appWin2 = createWindow(null, TYPE_BASE_APPLICATION, act2, "appWin2");
appWin2.setHasSurface(true);
assertTrue(appWin2.canBeImeTarget());
- doReturn(true).when(appWin1).isClosing();
doReturn(true).when(appWin1).inTransitionSelfOrParent();
// Test step 3: Verify appWin2 will be the next IME target and the IME snapshot surface will