Merge "Fix two flicker tests assumptions re: usesTaskbar vs. isTablet" into main
diff --git a/core/java/android/os/VibrationAttributes.java b/core/java/android/os/VibrationAttributes.java
index da863e5..5896227 100644
--- a/core/java/android/os/VibrationAttributes.java
+++ b/core/java/android/os/VibrationAttributes.java
@@ -151,31 +151,6 @@
*/
public static final int USAGE_MEDIA = 0x10 | USAGE_CLASS_MEDIA;
- /** @hide */
- @IntDef(prefix = { "CATEGORY_" }, value = {
- CATEGORY_UNKNOWN,
- CATEGORY_KEYBOARD,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Category {}
-
- /**
- * Category value when the vibration category is unknown.
- *
- * @hide
- */
- public static final int CATEGORY_UNKNOWN = 0x0;
-
- /**
- * Category value for keyboard vibrations.
- *
- * <p>Most typical keyboard vibrations are haptic feedback for virtual keyboard key
- * press/release, for example.
- *
- * @hide
- */
- public static final int CATEGORY_KEYBOARD = 1;
-
/**
* @hide
*/
@@ -252,14 +227,12 @@
private final int mUsage;
private final int mFlags;
private final int mOriginalAudioUsage;
- private final int mCategory;
private VibrationAttributes(@Usage int usage, @AudioAttributes.AttributeUsage int audioUsage,
- @Flag int flags, @Category int category) {
+ @Flag int flags) {
mUsage = usage;
mOriginalAudioUsage = audioUsage;
mFlags = flags & FLAG_ALL_SUPPORTED;
- mCategory = category;
}
/**
@@ -297,20 +270,6 @@
}
/**
- * Return the vibration category.
- *
- * <p>Vibration categories describe the source of the vibration, and it can be combined with
- * the vibration usage to best match to a user setting, e.g. a vibration with usage touch and
- * category keyboard can be used to control keyboard haptic feedback independently.
- *
- * @hide
- */
- @Category
- public int getCategory() {
- return mCategory;
- }
-
- /**
* Check whether a flag is set
* @return true if a flag is set and false otherwise
*/
@@ -362,14 +321,12 @@
dest.writeInt(mUsage);
dest.writeInt(mOriginalAudioUsage);
dest.writeInt(mFlags);
- dest.writeInt(mCategory);
}
private VibrationAttributes(Parcel src) {
mUsage = src.readInt();
mOriginalAudioUsage = src.readInt();
mFlags = src.readInt();
- mCategory = src.readInt();
}
public static final @NonNull Parcelable.Creator<VibrationAttributes>
@@ -392,12 +349,12 @@
}
VibrationAttributes rhs = (VibrationAttributes) o;
return mUsage == rhs.mUsage && mOriginalAudioUsage == rhs.mOriginalAudioUsage
- && mFlags == rhs.mFlags && mCategory == rhs.mCategory;
+ && mFlags == rhs.mFlags;
}
@Override
public int hashCode() {
- return Objects.hash(mUsage, mOriginalAudioUsage, mFlags, mCategory);
+ return Objects.hash(mUsage, mOriginalAudioUsage, mFlags);
}
@Override
@@ -405,7 +362,6 @@
return "VibrationAttributes{"
+ "mUsage=" + usageToString()
+ ", mAudioUsage= " + AudioAttributes.usageToString(mOriginalAudioUsage)
- + ", mCategory=" + categoryToString()
+ ", mFlags=" + mFlags
+ '}';
}
@@ -445,23 +401,6 @@
}
}
- /** @hide */
- public String categoryToString() {
- return categoryToString(mCategory);
- }
-
- /** @hide */
- public static String categoryToString(@Category int category) {
- switch (category) {
- case CATEGORY_UNKNOWN:
- return "UNKNOWN";
- case CATEGORY_KEYBOARD:
- return "KEYBOARD";
- default:
- return "unknown category " + category;
- }
- }
-
/**
* Builder class for {@link VibrationAttributes} objects.
* By default, all information is set to UNKNOWN.
@@ -471,7 +410,6 @@
private int mUsage = USAGE_UNKNOWN;
private int mOriginalAudioUsage = AudioAttributes.USAGE_UNKNOWN;
private int mFlags = 0x0;
- private int mCategory = CATEGORY_UNKNOWN;
/**
* Constructs a new Builder with the defaults.
@@ -487,7 +425,6 @@
mUsage = vib.mUsage;
mOriginalAudioUsage = vib.mOriginalAudioUsage;
mFlags = vib.mFlags;
- mCategory = vib.mCategory;
}
}
@@ -554,7 +491,7 @@
*/
public @NonNull VibrationAttributes build() {
VibrationAttributes ans = new VibrationAttributes(
- mUsage, mOriginalAudioUsage, mFlags, mCategory);
+ mUsage, mOriginalAudioUsage, mFlags);
return ans;
}
@@ -570,19 +507,6 @@
}
/**
- * Sets the attribute describing the category of the corresponding vibration.
- *
- * @param category The category for the vibration
- * @return the same Builder instance.
- *
- * @hide
- */
- public @NonNull Builder setCategory(@Category int category) {
- mCategory = category;
- return this;
- }
-
- /**
* Sets only the flags specified in the bitmask, leaving the other supported flag values
* unchanged in the builder.
*
diff --git a/core/java/android/text/Selection.java b/core/java/android/text/Selection.java
index 6a54d23..711578c 100644
--- a/core/java/android/text/Selection.java
+++ b/core/java/android/text/Selection.java
@@ -350,7 +350,7 @@
private static final char PARAGRAPH_SEPARATOR = '\n';
/**
- * Move the cusrot to the closest paragraph start offset.
+ * Move the cursor to the closest paragraph start offset.
*
* @param text the spannable text
* @param layout layout to be used for drawing.
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index 33610a0..c7e1fba 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -396,6 +396,9 @@
int cujType = conf.mCujType;
if (!shouldMonitor()) {
return false;
+ } else if (!conf.hasValidView()) {
+ Log.w(TAG, "The view has since become invalid, aborting the CUJ.");
+ return false;
}
RunningTracker tracker = putTrackerIfNoCurrent(cujType, () ->
diff --git a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
index 4aeee6c..cbcbf2db 100644
--- a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
@@ -736,7 +736,7 @@
return UUID.nameUUIDFromBytes(fullStringIdentifier.getBytes()).getMostSignificantBits();
}
- private static final int STACK_SIZE_TO_PROTO_LOG_ENTRY_CALL = 12;
+ private static final int STACK_SIZE_TO_PROTO_LOG_ENTRY_CALL = 6;
private String collectStackTrace() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 9112d37..284c299 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -19,14 +19,6 @@
#include "com_android_internal_os_Zygote.h"
-#include <async_safe/log.h>
-
-// sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc
-#include <sys/mount.h>
-#include <linux/fs.h>
-#include <sys/types.h>
-#include <dirent.h>
-
#include <algorithm>
#include <array>
#include <atomic>
@@ -41,19 +33,18 @@
#include <android/fdsan.h>
#include <arpa/inet.h>
+#include <dirent.h>
#include <fcntl.h>
#include <grp.h>
#include <inttypes.h>
#include <malloc.h>
#include <mntent.h>
-#include <paths.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
-#include <sys/auxv.h>
#include <sys/capability.h>
-#include <sys/cdefs.h>
#include <sys/eventfd.h>
+#include <sys/mount.h>
#include <sys/personality.h>
#include <sys/prctl.h>
#include <sys/resource.h>
@@ -66,6 +57,7 @@
#include <sys/wait.h>
#include <unistd.h>
+#include <async_safe/log.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
diff --git a/core/tests/coretests/src/android/os/VibrationAttributesTest.java b/core/tests/coretests/src/android/os/VibrationAttributesTest.java
index d8142c8..5bdae0e 100644
--- a/core/tests/coretests/src/android/os/VibrationAttributesTest.java
+++ b/core/tests/coretests/src/android/os/VibrationAttributesTest.java
@@ -28,11 +28,9 @@
@Test
public void testSimple() throws Exception {
final VibrationAttributes attr = new VibrationAttributes.Builder()
- .setCategory(VibrationAttributes.CATEGORY_KEYBOARD)
.setUsage(VibrationAttributes.USAGE_ALARM)
.build();
- assertEquals(VibrationAttributes.CATEGORY_KEYBOARD, attr.getCategory());
assertEquals(VibrationAttributes.USAGE_ALARM, attr.getUsage());
}
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 25c767a..c36eda9 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -84,6 +84,7 @@
import android.util.IntArray;
import android.util.Log;
import android.util.Pair;
+import android.util.Slog;
import android.view.KeyEvent;
import com.android.internal.annotations.GuardedBy;
@@ -4283,7 +4284,7 @@
final OnAudioFocusChangeListener listener =
fri.mRequest.getOnAudioFocusChangeListener();
if (listener != null) {
- Log.d(TAG, "dispatching onAudioFocusChange("
+ Slog.i(TAG, "dispatching onAudioFocusChange("
+ msg.arg1 + ") to " + msg.obj);
listener.onAudioFocusChange(msg.arg1);
}
diff --git a/nfc/api/current.txt b/nfc/api/current.txt
index b0d1f71..447e980 100644
--- a/nfc/api/current.txt
+++ b/nfc/api/current.txt
@@ -220,11 +220,14 @@
field @Deprecated public static final String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT";
field public static final String CATEGORY_OTHER = "other";
field public static final String CATEGORY_PAYMENT = "payment";
+ field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final String DH = "DH";
+ field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final String ESE = "ESE";
field public static final String EXTRA_CATEGORY = "category";
field public static final String EXTRA_SERVICE_COMPONENT = "component";
field public static final int SELECTION_MODE_ALWAYS_ASK = 1; // 0x1
field public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2; // 0x2
field public static final int SELECTION_MODE_PREFER_DEFAULT = 0; // 0x0
+ field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final String UICC = "UICC";
}
public abstract class HostApduService extends android.app.Service {
diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt
index ae63e19..2ff9829 100644
--- a/nfc/api/system-current.txt
+++ b/nfc/api/system-current.txt
@@ -75,6 +75,8 @@
public final class CardEmulation {
method @FlaggedApi("android.permission.flags.wallet_role_enabled") @Nullable @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static android.content.ComponentName getPreferredPaymentService(@NonNull android.content.Context);
method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public java.util.List<android.nfc.cardemulation.ApduServiceInfo> getServices(@NonNull String, int);
+ method @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public void overrideRoutingTable(@NonNull android.app.Activity, @Nullable String, @Nullable String);
+ method @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public void recoverRoutingTable(@NonNull android.app.Activity);
}
}
diff --git a/nfc/java/android/nfc/INfcCardEmulation.aidl b/nfc/java/android/nfc/INfcCardEmulation.aidl
index cb97f23..79f1275 100644
--- a/nfc/java/android/nfc/INfcCardEmulation.aidl
+++ b/nfc/java/android/nfc/INfcCardEmulation.aidl
@@ -48,6 +48,6 @@
boolean setServiceEnabledForCategoryOther(int userHandle, in ComponentName app, boolean status);
boolean isDefaultPaymentRegistered();
- boolean overrideRoutingTable(int userHandle, String protocol, String technology);
- boolean recoverRoutingTable(int userHandle);
+ void overrideRoutingTable(int userHandle, String protocol, String technology, in String pkg);
+ void recoverRoutingTable(int userHandle);
}
diff --git a/nfc/java/android/nfc/cardemulation/CardEmulation.java b/nfc/java/android/nfc/cardemulation/CardEmulation.java
index e0438ce..03372b2 100644
--- a/nfc/java/android/nfc/cardemulation/CardEmulation.java
+++ b/nfc/java/android/nfc/cardemulation/CardEmulation.java
@@ -23,6 +23,7 @@
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.StringDef;
import android.annotation.SystemApi;
import android.annotation.UserHandleAware;
import android.annotation.UserIdInt;
@@ -43,6 +44,8 @@
import android.provider.Settings.SettingNotFoundException;
import android.util.Log;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.HashMap;
import java.util.HexFormat;
import java.util.List;
@@ -148,6 +151,21 @@
* that service will be invoked directly.
*/
public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2;
+ /**
+ * Route to Device Host (DH).
+ */
+ @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE)
+ public static final String DH = "DH";
+ /**
+ * Route to eSE.
+ */
+ @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE)
+ public static final String ESE = "ESE";
+ /**
+ * Route to UICC.
+ */
+ @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE)
+ public static final String UICC = "UICC";
static boolean sIsInitialized = false;
static HashMap<Context, CardEmulation> sCardEmus = new HashMap<Context, CardEmulation>();
@@ -865,11 +883,22 @@
sService.setServiceEnabledForCategoryOther(userId, service, status), false);
}
+ /** @hide */
+ @StringDef({
+ DH,
+ ESE,
+ UICC
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ProtocolAndTechnologyRoute {}
+
/**
* Setting NFC controller routing table, which includes Protocol Route and Technology Route,
* while this Activity is in the foreground.
*
- * The parameter set to null can be used to keep current values for that entry.
+ * The parameter set to null can be used to keep current values for that entry. Either
+ * Protocol Route or Technology Route should be override when calling this API, otherwise
+ * throw {@link IllegalArgumentException}.
* <p>
* Example usage in an Activity that requires to set proto route to "ESE" and keep tech route:
* <pre>
@@ -877,26 +906,39 @@
* mNfcAdapter.overrideRoutingTable(this , "ESE" , null);
* }</pre>
* </p>
- * Also activities must call this method when it goes to the background,
- * with all parameters set to null.
+ * Also activities must call {@link #recoverRoutingTable(Activity)}
+ * when it goes to the background. Only the package of the
+ * currently preferred service (the service set as preferred by the current foreground
+ * application via {@link CardEmulation#setPreferredService(Activity, ComponentName)} or the
+ * current Default Wallet Role Holder {@link android.app.role.RoleManager#ROLE_WALLET}),
+ * otherwise a call to this method will fail and throw {@link SecurityException}.
* @param activity The Activity that requests NFC controller routing table to be changed.
* @param protocol ISO-DEP route destination, which can be "DH" or "UICC" or "ESE".
* @param technology Tech-A, Tech-B route destination, which can be "DH" or "UICC" or "ESE".
- * @return true if operation is successful and false otherwise
- *
+ * @throws SecurityException if the caller is not the preferred NFC service
+ * @throws IllegalArgumentException if the activity is not resumed or the caller is not in the
+ * foreground, or both protocol route and technology route are null.
+ * <p>
* This is a high risk API and only included to support mainline effort
* @hide
*/
- public boolean overrideRoutingTable(Activity activity, String protocol, String technology) {
- if (activity == null) {
- throw new NullPointerException("activity or service or category is null");
- }
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE)
+ public void overrideRoutingTable(
+ @NonNull Activity activity, @ProtocolAndTechnologyRoute @Nullable String protocol,
+ @ProtocolAndTechnologyRoute @Nullable String technology) {
if (!activity.isResumed()) {
throw new IllegalArgumentException("Activity must be resumed.");
}
- return callServiceReturn(() ->
+ if (protocol == null && technology == null) {
+ throw new IllegalArgumentException(("Both Protocol and Technology are null."));
+ }
+ callService(() ->
sService.overrideRoutingTable(
- mContext.getUser().getIdentifier(), protocol, technology), false);
+ mContext.getUser().getIdentifier(),
+ protocol,
+ technology,
+ mContext.getPackageName()));
}
/**
@@ -904,20 +946,19 @@
* which was changed by {@link #overrideRoutingTable(Activity, String, String)}
*
* @param activity The Activity that requested NFC controller routing table to be changed.
- * @return true if operation is successful and false otherwise
+ * @throws IllegalArgumentException if the caller is not in the foreground.
*
* @hide
*/
- public boolean recoverRoutingTable(Activity activity) {
- if (activity == null) {
- throw new NullPointerException("activity is null");
- }
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE)
+ public void recoverRoutingTable(@NonNull Activity activity) {
if (!activity.isResumed()) {
throw new IllegalArgumentException("Activity must be resumed.");
}
- return callServiceReturn(() ->
+ callService(() ->
sService.recoverRoutingTable(
- mContext.getUser().getIdentifier()), false);
+ mContext.getUser().getIdentifier()));
}
/**
diff --git a/nfc/java/android/nfc/flags.aconfig b/nfc/java/android/nfc/flags.aconfig
index 5819b98..0fda91d 100644
--- a/nfc/java/android/nfc/flags.aconfig
+++ b/nfc/java/android/nfc/flags.aconfig
@@ -133,3 +133,11 @@
description: "Add Settings.ACTION_MANAGE_OTHER_NFC_SERVICES_SETTINGS"
bug: "358129872"
}
+
+flag {
+ name: "nfc_override_recover_routing_table"
+ is_exported: true
+ namespace: "nfc"
+ description: "Enable override and recover routing table"
+ bug: "329043523"
+}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveErrorFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveErrorFragment.java
index d33433f..2fb32a7 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveErrorFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/UnarchiveErrorFragment.java
@@ -16,10 +16,12 @@
package com.android.packageinstaller;
+import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import android.app.Activity;
import android.app.AlertDialog;
+import android.app.BroadcastOptions;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.PendingIntent;
@@ -161,25 +163,31 @@
return;
}
+ // Allow the error handling actvities to start in the background.
+ final BroadcastOptions options = BroadcastOptions.makeBasic();
+ options.setPendingIntentBackgroundActivityStartMode(
+ MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
switch (mStatus) {
case PackageInstaller.UNARCHIVAL_ERROR_USER_ACTION_NEEDED:
activity.startIntentSender(mExtraIntent.getIntentSender(), /* fillInIntent= */
- null, /* flagsMask= */ 0, FLAG_ACTIVITY_NEW_TASK, /* extraFlags= */ 0);
+ null, /* flagsMask= */ 0, FLAG_ACTIVITY_NEW_TASK, /* extraFlags= */ 0,
+ options.toBundle());
break;
case PackageInstaller.UNARCHIVAL_ERROR_INSUFFICIENT_STORAGE:
if (mExtraIntent != null) {
activity.startIntentSender(mExtraIntent.getIntentSender(), /* fillInIntent= */
- null, /* flagsMask= */ 0, FLAG_ACTIVITY_NEW_TASK, /* extraFlags= */ 0);
+ null, /* flagsMask= */ 0, FLAG_ACTIVITY_NEW_TASK, /* extraFlags= */ 0,
+ options.toBundle());
} else {
Intent intent = new Intent("android.intent.action.MANAGE_PACKAGE_STORAGE");
- startActivity(intent);
+ startActivity(intent, options.toBundle());
}
break;
case PackageInstaller.UNARCHIVAL_ERROR_INSTALLER_DISABLED:
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", mInstallerPackageName, null);
intent.setData(uri);
- startActivity(intent);
+ startActivity(intent, options.toBundle());
break;
default:
// Do nothing. The rest of the dialogs are purely informational.
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
index 4b141e7..69ef718 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
@@ -22,6 +22,7 @@
import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
import static android.service.notification.SystemZenRules.getTriggerDescriptionForScheduleEvent;
import static android.service.notification.SystemZenRules.getTriggerDescriptionForScheduleTime;
+import static android.service.notification.SystemZenRules.PACKAGE_ANDROID;
import static android.service.notification.ZenModeConfig.tryParseCountdownConditionId;
import static android.service.notification.ZenModeConfig.tryParseEventConditionId;
import static android.service.notification.ZenModeConfig.tryParseScheduleConditionId;
@@ -129,7 +130,11 @@
}
public static ZenMode manualDndMode(AutomaticZenRule manualRule, boolean isActive) {
- return new ZenMode(MANUAL_DND_MODE_ID, manualRule,
+ // Manual rule is owned by the system, so we set it here
+ AutomaticZenRule manualRuleWithPkg = new AutomaticZenRule.Builder(manualRule)
+ .setPackage(PACKAGE_ANDROID)
+ .build();
+ return new ZenMode(MANUAL_DND_MODE_ID, manualRuleWithPkg,
isActive ? Status.ENABLED_AND_ACTIVE : Status.ENABLED, true);
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java
index d9fdcc38..f464247 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java
@@ -19,6 +19,7 @@
import static android.app.NotificationManager.INTERRUPTION_FILTER_ALARMS;
import static android.app.NotificationManager.INTERRUPTION_FILTER_NONE;
import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY;
+import static android.service.notification.SystemZenRules.PACKAGE_ANDROID;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -67,6 +68,7 @@
assertThat(manualMode.canEditNameAndIcon()).isFalse();
assertThat(manualMode.canBeDeleted()).isFalse();
assertThat(manualMode.isActive()).isFalse();
+ assertThat(manualMode.getRule().getPackageName()).isEqualTo(PACKAGE_ANDROID);
}
@Test
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 5632e30..df28654 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -380,6 +380,17 @@
}
flag {
+ name: "status_bar_stop_updating_window_height"
+ namespace: "systemui"
+ description: "Don't have PhoneStatusBarView manually trigger an update of the height in "
+ "StatusBarWindowController"
+ bug: "360115167"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "compose_bouncer"
namespace: "systemui"
description: "Use the new compose bouncer in SystemUI"
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
index b93b049..7472d81 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
@@ -1410,7 +1410,10 @@
R.string.accessibility_action_label_close_communal_hub
)
) {
- viewModel.changeScene(CommunalScenes.Blank)
+ viewModel.changeScene(
+ CommunalScenes.Blank,
+ "closed by accessibility"
+ )
true
},
CustomAccessibilityAction(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt
index 9ccf99b..70529cc 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt
@@ -112,7 +112,7 @@
testScope.runTest {
val scene by collectLastValue(communalSceneInteractor.currentScene)
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
assertThat(scene).isEqualTo(CommunalScenes.Communal)
communalSceneInteractor.setEditModeState(EditModeState.STARTING)
@@ -133,7 +133,7 @@
testScope.runTest {
val scene by collectLastValue(communalSceneInteractor.currentScene)
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
assertThat(scene).isEqualTo(CommunalScenes.Communal)
communalSceneInteractor.setIsLaunchingWidget(true)
@@ -154,7 +154,7 @@
testScope.runTest {
val scene by collectLastValue(communalSceneInteractor.currentScene)
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
assertThat(scene).isEqualTo(CommunalScenes.Communal)
communalSceneInteractor.setIsLaunchingWidget(false)
@@ -174,7 +174,7 @@
with(kosmos) {
testScope.runTest {
val scene by collectLastValue(communalSceneInteractor.currentScene)
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
assertThat(scene).isEqualTo(CommunalScenes.Communal)
communalInteractor.setEditModeOpen(true)
@@ -213,7 +213,7 @@
testScope.runTest {
whenever(centralSurfaces.isLaunchingActivityOverLockscreen).thenReturn(false)
val scene by collectLastValue(communalSceneInteractor.currentScene)
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
assertThat(scene).isEqualTo(CommunalScenes.Communal)
updateDocked(true)
@@ -233,7 +233,7 @@
testScope.runTest {
whenever(centralSurfaces.isLaunchingActivityOverLockscreen).thenReturn(true)
val scene by collectLastValue(communalSceneInteractor.currentScene)
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
assertThat(scene).isEqualTo(CommunalScenes.Communal)
updateDocked(true)
@@ -270,7 +270,7 @@
with(kosmos) {
testScope.runTest {
val scene by collectLastValue(communalSceneInteractor.currentScene)
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
assertThat(scene).isEqualTo(CommunalScenes.Communal)
fakeKeyguardTransitionRepository.sendTransitionSteps(
@@ -292,7 +292,7 @@
with(kosmos) {
testScope.runTest {
val scene by collectLastValue(communalSceneInteractor.currentScene)
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
assertThat(scene).isEqualTo(CommunalScenes.Communal)
fakeKeyguardTransitionRepository.sendTransitionSteps(
@@ -320,7 +320,7 @@
fun dockingOnLockscreen_forcesCommunal() =
with(kosmos) {
testScope.runTest {
- communalSceneInteractor.changeScene(CommunalScenes.Blank)
+ communalSceneInteractor.changeScene(CommunalScenes.Blank, "test")
val scene by collectLastValue(communalSceneInteractor.currentScene)
// device is docked while on the lockscreen
@@ -342,7 +342,7 @@
fun dockingOnLockscreen_doesNotForceCommunalIfDreamStarts() =
with(kosmos) {
testScope.runTest {
- communalSceneInteractor.changeScene(CommunalScenes.Blank)
+ communalSceneInteractor.changeScene(CommunalScenes.Blank, "test")
val scene by collectLastValue(communalSceneInteractor.currentScene)
// device is docked while on the lockscreen
@@ -374,7 +374,7 @@
testScope.runTest {
// Device is dreaming and on communal.
updateDreaming(true)
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
val scene by collectLastValue(communalSceneInteractor.currentScene)
assertThat(scene).isEqualTo(CommunalScenes.Communal)
@@ -391,7 +391,7 @@
testScope.runTest {
// Device is not dreaming and on communal.
updateDreaming(false)
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
// Scene stays as Communal
advanceTimeBy(SCREEN_TIMEOUT.milliseconds)
@@ -406,7 +406,7 @@
testScope.runTest {
// Device is dreaming and on communal.
updateDreaming(true)
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
val scene by collectLastValue(communalSceneInteractor.currentScene)
assertThat(scene).isEqualTo(CommunalScenes.Communal)
@@ -429,7 +429,7 @@
testScope.runTest {
// Device is on communal, but not dreaming.
updateDreaming(false)
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
val scene by collectLastValue(communalSceneInteractor.currentScene)
assertThat(scene).isEqualTo(CommunalScenes.Communal)
@@ -450,7 +450,7 @@
with(kosmos) {
testScope.runTest {
// Device is on communal.
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
// Device stays on the hub after the timeout since we're not dreaming.
advanceTimeBy(SCREEN_TIMEOUT.milliseconds * 2)
@@ -471,7 +471,7 @@
testScope.runTest {
// Device is dreaming and on communal.
updateDreaming(true)
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
val scene by collectLastValue(communalSceneInteractor.currentScene)
assertThat(scene).isEqualTo(CommunalScenes.Communal)
@@ -500,7 +500,7 @@
// Device is dreaming and on communal.
updateDreaming(true)
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
val scene by collectLastValue(communalSceneInteractor.currentScene)
assertThat(scene).isEqualTo(CommunalScenes.Communal)
@@ -520,7 +520,7 @@
with(kosmos) {
testScope.runTest {
val scene by collectLastValue(communalSceneInteractor.currentScene)
- communalSceneInteractor.changeScene(CommunalScenes.Blank)
+ communalSceneInteractor.changeScene(CommunalScenes.Blank, "test")
assertThat(scene).isEqualTo(CommunalScenes.Blank)
fakeKeyguardTransitionRepository.sendTransitionSteps(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt
index e57a4cb..864795b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt
@@ -482,7 +482,7 @@
testScope.runTest {
val targetScene = CommunalScenes.Communal
- underTest.changeScene(targetScene)
+ underTest.changeScene(targetScene, "test")
val desiredScene = collectLastValue(communalRepository.currentScene)
runCurrent()
@@ -635,7 +635,7 @@
runCurrent()
assertThat(isCommunalShowing()).isEqualTo(false)
- underTest.changeScene(CommunalScenes.Communal)
+ underTest.changeScene(CommunalScenes.Communal, "test")
isCommunalShowing = collectLastValue(underTest.isCommunalShowing)
runCurrent()
@@ -659,12 +659,12 @@
assertThat(isCommunalShowing).isFalse()
// Verify scene changes (without the flag) to communal sets the value to true
- underTest.changeScene(CommunalScenes.Communal)
+ underTest.changeScene(CommunalScenes.Communal, "test")
runCurrent()
assertThat(isCommunalShowing).isTrue()
// Verify scene changes (without the flag) to blank sets the value back to false
- underTest.changeScene(CommunalScenes.Blank)
+ underTest.changeScene(CommunalScenes.Blank, "test")
runCurrent()
assertThat(isCommunalShowing).isFalse()
}
@@ -679,7 +679,7 @@
assertThat(isCommunalShowing).isFalse()
// Verify scene changes without the flag doesn't have any impact
- underTest.changeScene(CommunalScenes.Communal)
+ underTest.changeScene(CommunalScenes.Communal, "test")
runCurrent()
assertThat(isCommunalShowing).isFalse()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorTest.kt
index 43293c7..ed7e910 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorTest.kt
@@ -53,7 +53,7 @@
val currentScene by collectLastValue(underTest.currentScene)
assertThat(currentScene).isEqualTo(CommunalScenes.Blank)
- underTest.changeScene(CommunalScenes.Communal)
+ underTest.changeScene(CommunalScenes.Communal, "test")
assertThat(currentScene).isEqualTo(CommunalScenes.Communal)
}
@@ -63,7 +63,7 @@
val currentScene by collectLastValue(underTest.currentScene)
assertThat(currentScene).isEqualTo(CommunalScenes.Blank)
- underTest.snapToScene(CommunalScenes.Communal)
+ underTest.snapToScene(CommunalScenes.Communal, "test")
assertThat(currentScene).isEqualTo(CommunalScenes.Communal)
}
@@ -75,6 +75,7 @@
assertThat(currentScene).isEqualTo(CommunalScenes.Blank)
underTest.snapToScene(
CommunalScenes.Communal,
+ "test",
ActivityTransitionAnimator.TIMINGS.totalDuration
)
assertThat(currentScene).isEqualTo(CommunalScenes.Blank)
@@ -86,7 +87,7 @@
fun changeSceneForActivityStartOnDismissKeyguard() =
testScope.runTest {
val currentScene by collectLastValue(underTest.currentScene)
- underTest.snapToScene(CommunalScenes.Communal)
+ underTest.snapToScene(CommunalScenes.Communal, "test")
assertThat(currentScene).isEqualTo(CommunalScenes.Communal)
underTest.changeSceneForActivityStartOnDismissKeyguard()
@@ -97,7 +98,7 @@
fun changeSceneForActivityStartOnDismissKeyguard_willNotChangeScene_forEditModeActivity() =
testScope.runTest {
val currentScene by collectLastValue(underTest.currentScene)
- underTest.snapToScene(CommunalScenes.Communal)
+ underTest.snapToScene(CommunalScenes.Communal, "test")
assertThat(currentScene).isEqualTo(CommunalScenes.Communal)
underTest.setEditModeState(EditModeState.STARTING)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt
index 3a23e14..7e28e19 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt
@@ -158,7 +158,7 @@
kosmos.setCommunalAvailable(true)
communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_NOT_STARTED)
- communalInteractor.changeScene(CommunalScenes.Blank)
+ communalInteractor.changeScene(CommunalScenes.Blank, "test")
assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_NOT_STARTED)
}
@@ -171,7 +171,7 @@
goToCommunal()
communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_STARTED)
- communalInteractor.changeScene(CommunalScenes.Blank)
+ communalInteractor.changeScene(CommunalScenes.Blank, "test")
assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_COMPLETED)
}
@@ -184,13 +184,13 @@
goToCommunal()
communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED)
- communalInteractor.changeScene(CommunalScenes.Blank)
+ communalInteractor.changeScene(CommunalScenes.Blank, "test")
assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_COMPLETED)
}
private suspend fun goToCommunal() {
kosmos.setCommunalAvailable(true)
- communalInteractor.changeScene(CommunalScenes.Communal)
+ communalInteractor.changeScene(CommunalScenes.Communal, "test")
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/CommunalTransitionAnimatorControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/CommunalTransitionAnimatorControllerTest.kt
index e36fd75..a052b07 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/CommunalTransitionAnimatorControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/CommunalTransitionAnimatorControllerTest.kt
@@ -76,7 +76,7 @@
val launching by collectLastValue(communalSceneInteractor.isLaunchingWidget)
val scene by collectLastValue(communalSceneInteractor.currentScene)
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
Truth.assertThat(scene).isEqualTo(CommunalScenes.Communal)
communalSceneInteractor.setIsLaunchingWidget(true)
assertTrue(launching!!)
@@ -103,7 +103,7 @@
val launching by collectLastValue(communalSceneInteractor.isLaunchingWidget)
val scene by collectLastValue(communalSceneInteractor.currentScene)
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
Truth.assertThat(scene).isEqualTo(CommunalScenes.Communal)
communalSceneInteractor.setIsLaunchingWidget(true)
assertTrue(launching!!)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
index 7a86e57..da82b5f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
@@ -68,7 +68,6 @@
import com.android.systemui.testKosmos
import com.android.systemui.touch.TouchInsetManager
import com.android.systemui.util.concurrency.FakeExecutor
-import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
@@ -87,6 +86,7 @@
import org.mockito.Mockito.isNull
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.any
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.eq
import org.mockito.kotlin.spy
@@ -669,7 +669,7 @@
runCurrent()
verify(mDreamOverlayCallback).onRedirectWake(true)
client.onWakeRequested()
- verify(mCommunalInteractor).changeScene(eq(CommunalScenes.Communal), isNull())
+ verify(mCommunalInteractor).changeScene(eq(CommunalScenes.Communal), any(), isNull())
verify(mUiEventLogger).log(CommunalUiEvent.DREAM_TO_COMMUNAL_HUB_DREAM_AWAKE_START)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
index 8c1e8de..9792c28 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
@@ -845,7 +845,7 @@
runTransitionAndSetWakefulness(KeyguardState.LOCKSCREEN, KeyguardState.GONE)
// WHEN the glanceable hub is shown
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
runCurrent()
assertThat(transitionRepository)
@@ -1004,7 +1004,7 @@
fun alternateBouncerToGlanceableHub() =
testScope.runTest {
// GIVEN the device is idle on the glanceable hub
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
runCurrent()
clearInvocations(transitionRepository)
@@ -1123,7 +1123,7 @@
fun primaryBouncerToGlanceableHub() =
testScope.runTest {
// GIVEN the device is idle on the glanceable hub
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
runCurrent()
// GIVEN a prior transition has run to PRIMARY_BOUNCER
@@ -1157,7 +1157,7 @@
advanceTimeBy(600L)
// GIVEN the device is idle on the glanceable hub
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
runCurrent()
// GIVEN a prior transition has run to PRIMARY_BOUNCER
@@ -1971,7 +1971,7 @@
fun glanceableHubToLockscreen_communalKtfRefactor() =
testScope.runTest {
// GIVEN a prior transition has run to GLANCEABLE_HUB
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
runCurrent()
clearInvocations(transitionRepository)
@@ -2035,7 +2035,7 @@
fun glanceableHubToDozing_communalKtfRefactor() =
testScope.runTest {
// GIVEN a prior transition has run to GLANCEABLE_HUB
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
runCurrent()
clearInvocations(transitionRepository)
@@ -2136,7 +2136,7 @@
fun glanceableHubToOccluded_communalKtfRefactor() =
testScope.runTest {
// GIVEN a prior transition has run to GLANCEABLE_HUB
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
runCurrent()
clearInvocations(transitionRepository)
@@ -2184,7 +2184,7 @@
fun glanceableHubToGone_communalKtfRefactor() =
testScope.runTest {
// GIVEN a prior transition has run to GLANCEABLE_HUB
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
runCurrent()
clearInvocations(transitionRepository)
@@ -2265,7 +2265,7 @@
advanceTimeBy(600L)
// GIVEN a prior transition has run to GLANCEABLE_HUB
- communalSceneInteractor.changeScene(CommunalScenes.Communal)
+ communalSceneInteractor.changeScene(CommunalScenes.Communal, "test")
runCurrent()
clearInvocations(transitionRepository)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BaseHeadsUpManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BaseHeadsUpManagerTest.java
index 9005ae3..89aa670 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BaseHeadsUpManagerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BaseHeadsUpManagerTest.java
@@ -241,7 +241,7 @@
alm.showNotification(entry);
final boolean removedImmediately = alm.removeNotification(
- entry.getKey(), /* releaseImmediately = */ false);
+ entry.getKey(), /* releaseImmediately = */ false, "removeDeferred");
assertFalse(removedImmediately);
assertTrue(alm.isHeadsUpEntry(entry.getKey()));
}
@@ -254,7 +254,7 @@
alm.showNotification(entry);
final boolean removedImmediately = alm.removeNotification(
- entry.getKey(), /* releaseImmediately = */ true);
+ entry.getKey(), /* releaseImmediately = */ true, "forceRemove");
assertTrue(removedImmediately);
assertFalse(alm.isHeadsUpEntry(entry.getKey()));
}
@@ -430,7 +430,7 @@
hum.showNotification(entry);
final boolean removedImmediately = hum.removeNotification(
- entry.getKey(), /* releaseImmediately = */ false);
+ entry.getKey(), /* releaseImmediately = */ false, "beforeMinimumDisplayTime");
assertFalse(removedImmediately);
assertTrue(hum.isHeadsUpEntry(entry.getKey()));
@@ -452,7 +452,7 @@
assertTrue(hum.isHeadsUpEntry(entry.getKey()));
final boolean removedImmediately = hum.removeNotification(
- entry.getKey(), /* releaseImmediately = */ false);
+ entry.getKey(), /* releaseImmediately = */ false, "afterMinimumDisplayTime");
assertTrue(removedImmediately);
assertFalse(hum.isHeadsUpEntry(entry.getKey()));
}
@@ -466,7 +466,7 @@
hum.showNotification(entry);
final boolean removedImmediately = hum.removeNotification(
- entry.getKey(), /* releaseImmediately = */ true);
+ entry.getKey(), /* releaseImmediately = */ true, "afterMinimumDisplayTime");
assertTrue(removedImmediately);
assertFalse(hum.isHeadsUpEntry(entry.getKey()));
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HeadsUpManagerPhoneTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HeadsUpManagerPhoneTest.kt
index 7a6838a..ca106fa 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HeadsUpManagerPhoneTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HeadsUpManagerPhoneTest.kt
@@ -179,8 +179,8 @@
mContext
.getOrCreateTestableResources()
.addOverride(R.integer.ambient_notification_extension_time, 500)
- mAvalancheController = AvalancheController(dumpManager, mUiEventLogger,
- mHeadsUpManagerLogger, mBgHandler)
+ mAvalancheController =
+ AvalancheController(dumpManager, mUiEventLogger, mHeadsUpManagerLogger, mBgHandler)
}
@Test
@@ -200,7 +200,12 @@
hmp.addSwipedOutNotification(entry.key)
// Remove should succeed because the notification is swiped out
- val removedImmediately = hmp.removeNotification(entry.key, /* releaseImmediately= */ false)
+ val removedImmediately =
+ hmp.removeNotification(
+ entry.key,
+ /* releaseImmediately= */ false,
+ /* reason= */ "swipe out"
+ )
Assert.assertTrue(removedImmediately)
Assert.assertFalse(hmp.isHeadsUpEntry(entry.key))
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/TestableHeadsUpManager.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/TestableHeadsUpManager.java
index 69207ba..3efabd7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/TestableHeadsUpManager.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/TestableHeadsUpManager.java
@@ -100,7 +100,7 @@
@Override
public boolean removeNotification(@NonNull String key, boolean releaseImmediately,
- boolean animate) {
+ boolean animate, @NonNull String reason) {
throw new UnsupportedOperationException();
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt
index bcad7e7..54b7d25 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt
@@ -23,6 +23,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.settingslib.notification.modes.TestModeBuilder
+import com.android.settingslib.notification.modes.ZenMode
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.testDispatcher
@@ -30,6 +31,7 @@
import com.android.systemui.statusbar.policy.data.repository.fakeZenModeRepository
import com.android.systemui.statusbar.policy.domain.interactor.zenModeInteractor
import com.android.systemui.statusbar.policy.ui.dialog.mockModesDialogDelegate
+import com.android.systemui.statusbar.policy.ui.dialog.mockModesDialogEventLogger
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -40,6 +42,7 @@
import org.junit.runner.RunWith
import org.mockito.Mockito.clearInvocations
import org.mockito.kotlin.argumentCaptor
+import org.mockito.kotlin.times
import org.mockito.kotlin.verify
@SmallTest
@@ -50,9 +53,16 @@
private val repository = kosmos.fakeZenModeRepository
private val interactor = kosmos.zenModeInteractor
private val mockDialogDelegate = kosmos.mockModesDialogDelegate
+ private val mockDialogEventLogger = kosmos.mockModesDialogEventLogger
private val underTest =
- ModesDialogViewModel(context, interactor, kosmos.testDispatcher, mockDialogDelegate)
+ ModesDialogViewModel(
+ context,
+ interactor,
+ kosmos.testDispatcher,
+ mockDialogDelegate,
+ mockDialogEventLogger
+ )
@Test
fun tiles_filtersOutUserDisabledModes() =
@@ -432,4 +442,84 @@
assertThat(intent.extras?.getString(Settings.EXTRA_AUTOMATIC_ZEN_RULE_ID))
.isEqualTo("B")
}
+
+ @Test
+ fun onClick_logsOnOffEvents() =
+ testScope.runTest {
+ val tiles by collectLastValue(underTest.tiles)
+
+ repository.addModes(
+ listOf(
+ TestModeBuilder.MANUAL_DND_ACTIVE,
+ TestModeBuilder()
+ .setId("id1")
+ .setName("Inactive Mode One")
+ .setActive(false)
+ .setManualInvocationAllowed(true)
+ .build(),
+ TestModeBuilder()
+ .setId("id2")
+ .setName("Active Non-Invokable Mode Two") // but can be turned off by tile
+ .setActive(true)
+ .setManualInvocationAllowed(false)
+ .build(),
+ )
+ )
+ runCurrent()
+
+ assertThat(tiles?.size).isEqualTo(3)
+
+ // Trigger onClick for each tile in sequence
+ tiles?.forEach { it.onClick.invoke() }
+ runCurrent()
+
+ val onModeCaptor = argumentCaptor<ZenMode>()
+ val offModeCaptor = argumentCaptor<ZenMode>()
+
+ // manual mode and mode 2 should have turned off
+ verify(mockDialogEventLogger, times(2)).logModeOff(offModeCaptor.capture())
+ val off0 = offModeCaptor.firstValue
+ assertThat(off0.isManualDnd).isTrue()
+
+ val off1 = offModeCaptor.secondValue
+ assertThat(off1.id).isEqualTo("id2")
+
+ // should also have logged turning mode 1 on
+ verify(mockDialogEventLogger).logModeOn(onModeCaptor.capture())
+ val on = onModeCaptor.lastValue
+ assertThat(on.id).isEqualTo("id1")
+ }
+
+ @Test
+ fun onLongClick_logsSettingsEvents() =
+ testScope.runTest {
+ val tiles by collectLastValue(underTest.tiles)
+
+ repository.addModes(
+ listOf(
+ TestModeBuilder.MANUAL_DND_ACTIVE,
+ TestModeBuilder()
+ .setId("id1")
+ .setName("Inactive Mode One")
+ .setActive(false)
+ .setManualInvocationAllowed(true)
+ .build(),
+ )
+ )
+ runCurrent()
+
+ assertThat(tiles?.size).isEqualTo(2)
+ val modeCaptor = argumentCaptor<ZenMode>()
+
+ // long click manual DND and then automatic mode
+ tiles?.forEach { it.onLongClick.invoke() }
+ runCurrent()
+
+ verify(mockDialogEventLogger, times(2)).logModeSettings(modeCaptor.capture())
+ val manualMode = modeCaptor.firstValue
+ assertThat(manualMode.isManualDnd).isTrue()
+
+ val automaticMode = modeCaptor.lastValue
+ assertThat(automaticMode.id).isEqualTo("id1")
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index baf8f5a..a301155 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -49,7 +49,6 @@
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
-import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider;
import com.android.systemui.statusbar.phone.SystemUIDialogManager;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -140,7 +139,6 @@
@Inject Lazy<SysUiState> mSysUiStateFlagsContainer;
@Inject Lazy<CommandQueue> mCommandQueue;
@Inject Lazy<UiEventLogger> mUiEventLogger;
- @Inject Lazy<StatusBarContentInsetsProvider> mContentInsetsProviderLazy;
@Inject Lazy<FeatureFlags> mFeatureFlagsLazy;
@Inject Lazy<NotificationSectionsManager> mNotificationSectionsManagerLazy;
@Inject Lazy<ScreenOffAnimationController> mScreenOffAnimationController;
@@ -186,7 +184,6 @@
mProviders.put(CommandQueue.class, mCommandQueue::get);
mProviders.put(UiEventLogger.class, mUiEventLogger::get);
mProviders.put(FeatureFlags.class, mFeatureFlagsLazy::get);
- mProviders.put(StatusBarContentInsetsProvider.class, mContentInsetsProviderLazy::get);
mProviders.put(NotificationSectionsManager.class, mNotificationSectionsManagerLazy::get);
mProviders.put(ScreenOffAnimationController.class, mScreenOffAnimationController::get);
mProviders.put(AmbientState.class, mAmbientStateLazy::get);
diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt
index b7c02ea..6e01393 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt
@@ -112,7 +112,11 @@
communalSceneInteractor.editModeState.value == EditModeState.STARTING ||
communalSceneInteractor.isLaunchingWidget.value
if (!delaySceneTransition) {
- communalSceneInteractor.changeScene(nextScene, nextTransition)
+ communalSceneInteractor.changeScene(
+ newScene = nextScene,
+ loggingReason = "KTF syncing",
+ transitionKey = nextTransition,
+ )
}
}
.launchIn(applicationScope)
@@ -176,7 +180,10 @@
if (scene == CommunalScenes.Communal && isDreaming && timeoutJob == null) {
// If dreaming starts after timeout has expired, ex. if dream restarts under
// the hub, just close the hub immediately.
- communalSceneInteractor.changeScene(CommunalScenes.Blank)
+ communalSceneInteractor.changeScene(
+ CommunalScenes.Blank,
+ "dream started after timeout",
+ )
}
}
}
@@ -201,7 +208,10 @@
bgScope.launch {
delay(screenTimeout.milliseconds)
if (isDreaming) {
- communalSceneInteractor.changeScene(CommunalScenes.Blank)
+ communalSceneInteractor.changeScene(
+ newScene = CommunalScenes.Blank,
+ loggingReason = "hub timeout",
+ )
}
timeoutJob = null
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
index 99bcc12..7181b15 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
@@ -329,8 +329,11 @@
@Deprecated(
"Use com.android.systemui.communal.domain.interactor.CommunalSceneInteractor instead"
)
- fun changeScene(newScene: SceneKey, transitionKey: TransitionKey? = null) =
- communalSceneInteractor.changeScene(newScene, transitionKey)
+ fun changeScene(
+ newScene: SceneKey,
+ loggingReason: String,
+ transitionKey: TransitionKey? = null
+ ) = communalSceneInteractor.changeScene(newScene, loggingReason, transitionKey)
fun setEditModeOpen(isOpen: Boolean) {
_editModeOpen.value = isOpen
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractor.kt
index e45a695..a0b9966 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractor.kt
@@ -22,6 +22,7 @@
import com.android.compose.animation.scene.TransitionKey
import com.android.systemui.communal.data.repository.CommunalSceneRepository
import com.android.systemui.communal.domain.model.CommunalTransitionProgressModel
+import com.android.systemui.communal.shared.log.CommunalSceneLogger
import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.communal.shared.model.CommunalTransitionKeys
import com.android.systemui.communal.shared.model.EditModeState
@@ -29,6 +30,7 @@
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.util.kotlin.BooleanFlowOperators.allOf
+import com.android.systemui.util.kotlin.pairwiseBy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -42,8 +44,8 @@
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
-import kotlinx.coroutines.launch
@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
@@ -51,7 +53,8 @@
@Inject
constructor(
@Application private val applicationScope: CoroutineScope,
- private val communalSceneRepository: CommunalSceneRepository,
+ private val repository: CommunalSceneRepository,
+ private val logger: CommunalSceneLogger,
) {
private val _isLaunchingWidget = MutableStateFlow(false)
@@ -80,25 +83,39 @@
*/
fun changeScene(
newScene: SceneKey,
+ loggingReason: String,
transitionKey: TransitionKey? = null,
keyguardState: KeyguardState? = null,
) {
- applicationScope.launch {
+ applicationScope.launch("$TAG#changeScene") {
+ logger.logSceneChangeRequested(
+ from = currentScene.value,
+ to = newScene,
+ reason = loggingReason,
+ isInstant = false,
+ )
notifyListeners(newScene, keyguardState)
- communalSceneRepository.changeScene(newScene, transitionKey)
+ repository.changeScene(newScene, transitionKey)
}
}
/** Immediately snaps to the new scene. */
fun snapToScene(
newScene: SceneKey,
+ loggingReason: String,
delayMillis: Long = 0,
keyguardState: KeyguardState? = null
) {
applicationScope.launch("$TAG#snapToScene") {
delay(delayMillis)
+ logger.logSceneChangeRequested(
+ from = currentScene.value,
+ to = newScene,
+ reason = loggingReason,
+ isInstant = true,
+ )
notifyListeners(newScene, keyguardState)
- communalSceneRepository.snapToScene(newScene)
+ repository.snapToScene(newScene)
}
}
@@ -113,13 +130,30 @@
if (_editModeState.value == EditModeState.STARTING) {
return
}
- changeScene(CommunalScenes.Blank, CommunalTransitionKeys.SimpleFade)
+ changeScene(
+ CommunalScenes.Blank,
+ "activity start dismissing keyguard",
+ CommunalTransitionKeys.SimpleFade,
+ )
}
/**
* Target scene as requested by the underlying [SceneTransitionLayout] or through [changeScene].
*/
- val currentScene: Flow<SceneKey> = communalSceneRepository.currentScene
+ val currentScene: StateFlow<SceneKey> =
+ repository.currentScene
+ .pairwiseBy(initialValue = repository.currentScene.value) { from, to ->
+ logger.logSceneChangeCommitted(
+ from = from,
+ to = to,
+ )
+ to
+ }
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.Eagerly,
+ initialValue = repository.currentScene.value,
+ )
private val _editModeState = MutableStateFlow<EditModeState?>(null)
/**
@@ -134,7 +168,13 @@
/** Transition state of the hub mode. */
val transitionState: StateFlow<ObservableTransitionState> =
- communalSceneRepository.transitionState
+ repository.transitionState
+ .onEach { logger.logSceneTransition(it) }
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.Eagerly,
+ initialValue = repository.transitionState.value,
+ )
/**
* Updates the transition state of the hub [SceneTransitionLayout].
@@ -142,7 +182,7 @@
* Note that you must call is with `null` when the UI is done or risk a memory leak.
*/
fun setTransitionState(transitionState: Flow<ObservableTransitionState>?) {
- communalSceneRepository.setTransitionState(transitionState)
+ repository.setTransitionState(transitionState)
}
/** Returns a flow that tracks the progress of transitions to the given scene from 0-1. */
diff --git a/packages/SystemUI/src/com/android/systemui/communal/shared/log/CommunalSceneLogger.kt b/packages/SystemUI/src/com/android/systemui/communal/shared/log/CommunalSceneLogger.kt
new file mode 100644
index 0000000..aed9215
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/shared/log/CommunalSceneLogger.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2024 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.communal.shared.log
+
+import com.android.compose.animation.scene.ObservableTransitionState
+import com.android.compose.animation.scene.SceneKey
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.core.LogLevel
+import com.android.systemui.log.dagger.CommunalLog
+import javax.inject.Inject
+
+class CommunalSceneLogger @Inject constructor(@CommunalLog private val logBuffer: LogBuffer) {
+
+ fun logSceneChangeRequested(
+ from: SceneKey,
+ to: SceneKey,
+ reason: String,
+ isInstant: Boolean,
+ ) {
+ logBuffer.log(
+ tag = TAG,
+ level = LogLevel.INFO,
+ messageInitializer = {
+ str1 = from.toString()
+ str2 = to.toString()
+ str3 = reason
+ bool1 = isInstant
+ },
+ messagePrinter = {
+ buildString {
+ append("Scene change requested: $str1 → $str2")
+ if (isInstant) {
+ append(" (instant)")
+ }
+ append(", reason: $str3")
+ }
+ },
+ )
+ }
+
+ fun logSceneChangeCommitted(
+ from: SceneKey,
+ to: SceneKey,
+ ) {
+ logBuffer.log(
+ tag = TAG,
+ level = LogLevel.INFO,
+ messageInitializer = {
+ str1 = from.toString()
+ str2 = to.toString()
+ },
+ messagePrinter = { "Scene change committed: $str1 → $str2" },
+ )
+ }
+
+ fun logSceneTransition(transitionState: ObservableTransitionState) {
+ when (transitionState) {
+ is ObservableTransitionState.Transition -> {
+ logBuffer.log(
+ tag = TAG,
+ level = LogLevel.INFO,
+ messageInitializer = {
+ str1 = transitionState.fromScene.toString()
+ str2 = transitionState.toScene.toString()
+ },
+ messagePrinter = { "Scene transition started: $str1 → $str2" },
+ )
+ }
+ is ObservableTransitionState.Idle -> {
+ logBuffer.log(
+ tag = TAG,
+ level = LogLevel.INFO,
+ messageInitializer = { str1 = transitionState.currentScene.toString() },
+ messagePrinter = { "Scene transition idle on: $str1" },
+ )
+ }
+ }
+ }
+
+ companion object {
+ private const val TAG = "CommunalSceneLogger"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
index d1a5a4b..b822133 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
@@ -106,10 +106,11 @@
*/
fun changeScene(
scene: SceneKey,
+ loggingReason: String,
transitionKey: TransitionKey? = null,
keyguardState: KeyguardState? = null
) {
- communalSceneInteractor.changeScene(scene, transitionKey, keyguardState)
+ communalSceneInteractor.changeScene(scene, loggingReason, transitionKey, keyguardState)
}
fun setEditModeState(state: EditModeState?) = communalSceneInteractor.setEditModeState(state)
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt
index bbd8596..6239373 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalTransitionViewModel.kt
@@ -67,7 +67,10 @@
* transition.
*/
fun snapToCommunal() {
- communalSceneInteractor.snapToScene(CommunalScenes.Communal)
+ communalSceneInteractor.snapToScene(
+ newScene = CommunalScenes.Communal,
+ loggingReason = "transition view model",
+ )
}
// Show UMO on glanceable hub immediately on transition into glanceable hub
diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalTransitionAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalTransitionAnimatorController.kt
index 0844462..e7cedc6 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalTransitionAnimatorController.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalTransitionAnimatorController.kt
@@ -42,6 +42,7 @@
// TODO(b/330672236): move this to onTransitionAnimationEnd() without the delay.
communalSceneInteractor.snapToScene(
CommunalScenes.Blank,
+ "CommunalTransitionAnimatorController",
ActivityTransitionAnimator.TIMINGS.totalDuration
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt
index 668fef6..6d7cdc4 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt
@@ -218,9 +218,10 @@
lifecycleScope.launch {
communalViewModel.canShowEditMode.collect {
communalViewModel.changeScene(
- CommunalScenes.Blank,
- CommunalTransitionKeys.ToEditMode,
- KeyguardState.GONE,
+ scene = CommunalScenes.Blank,
+ loggingReason = "edit mode opening",
+ transitionKey = CommunalTransitionKeys.ToEditMode,
+ keyguardState = KeyguardState.GONE,
)
// wait till transitioned to Blank scene, then animate in communal content in
// edit mode
@@ -252,8 +253,9 @@
communalViewModel.cleanupEditModeState()
communalViewModel.changeScene(
- CommunalScenes.Communal,
- CommunalTransitionKeys.FromEditMode
+ scene = CommunalScenes.Communal,
+ loggingReason = "edit mode closing",
+ transitionKey = CommunalTransitionKeys.FromEditMode
)
// Wait for the current scene to be idle on communal.
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
index 4b9e5a0..0c1fb72 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
@@ -442,7 +442,9 @@
@Override
public void onWakeRequested() {
mUiEventLogger.log(CommunalUiEvent.DREAM_TO_COMMUNAL_HUB_DREAM_AWAKE_START);
- mCommunalInteractor.changeScene(CommunalScenes.Communal, null);
+ mCommunalInteractor.changeScene(CommunalScenes.Communal,
+ "dream wake requested",
+ null);
}
private Lifecycle.State getLifecycleStateLocked() {
@@ -493,7 +495,7 @@
mSystemDialogsCloser.closeSystemDialogs();
// Hide glanceable hub (this is a nop if glanceable hub is not open).
- mCommunalInteractor.changeScene(CommunalScenes.Blank, null);
+ mCommunalInteractor.changeScene(CommunalScenes.Blank, "dream come to front", null);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt b/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt
index 4b07f78..5c0335a6 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt
@@ -20,9 +20,9 @@
import com.android.systemui.Flags.glanceableHubAllowKeyguardWhenDreaming
import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.communal.domain.interactor.CommunalInteractor
-import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dump.DumpManager
+import com.android.systemui.keyguard.domain.interactor.FromDreamingTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.Edge
import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
@@ -51,6 +51,7 @@
fromGlanceableHubTransitionInteractor: GlanceableHubToDreamingTransitionViewModel,
toGlanceableHubTransitionViewModel: DreamingToGlanceableHubTransitionViewModel,
private val toLockscreenTransitionViewModel: DreamingToLockscreenTransitionViewModel,
+ private val fromDreamingTransitionInteractor: FromDreamingTransitionInteractor,
private val communalInteractor: CommunalInteractor,
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
private val userTracker: UserTracker,
@@ -61,11 +62,9 @@
val showGlanceableHub =
communalInteractor.isCommunalEnabled.value &&
!keyguardUpdateMonitor.isEncryptedOrLockdown(userTracker.userId)
- if (showGlanceableHub && !glanceableHubAllowKeyguardWhenDreaming()) {
- communalInteractor.changeScene(CommunalScenes.Communal)
- } else {
- toLockscreenTransitionViewModel.startTransition()
- }
+ fromDreamingTransitionInteractor.startToLockscreenOrGlanceableHubTransition(
+ showGlanceableHub && !glanceableHubAllowKeyguardWhenDreaming()
+ )
}
val dreamOverlayTranslationX: Flow<Float> =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
index 0c12f8c..90aaf0d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
@@ -273,9 +273,10 @@
private suspend fun transitionToGlanceableHub() {
if (communalSceneKtfRefactor()) {
communalSceneInteractor.changeScene(
- CommunalScenes.Communal,
+ newScene = CommunalScenes.Communal,
+ loggingReason = "from dozing to hub",
// Immediately show the hub when transitioning from dozing to hub.
- CommunalTransitionKeys.Immediately,
+ transitionKey = CommunalTransitionKeys.Immediately,
)
} else {
startTransitionTo(KeyguardState.GLANCEABLE_HUB)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
index 7bf9c2f1..4666430 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
@@ -20,7 +20,9 @@
import com.android.app.animation.Interpolators
import com.android.app.tracing.coroutines.launch
import com.android.systemui.Flags.communalSceneKtfRefactor
+import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor
import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor
+import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
@@ -58,6 +60,7 @@
@Main mainDispatcher: CoroutineDispatcher,
keyguardInteractor: KeyguardInteractor,
private val glanceableHubTransitions: GlanceableHubTransitions,
+ private val communalSceneInteractor: CommunalSceneInteractor,
private val communalSettingsInteractor: CommunalSettingsInteractor,
powerInteractor: PowerInteractor,
keyguardOcclusionInteractor: KeyguardOcclusionInteractor,
@@ -126,17 +129,24 @@
}
}
- fun startToLockscreenTransition() {
+ fun startToLockscreenOrGlanceableHubTransition(openHub: Boolean) {
scope.launch {
if (
transitionInteractor.startedKeyguardState.replayCache.last() ==
KeyguardState.DREAMING
) {
if (powerInteractor.detailedWakefulness.value.isAwake()) {
- startTransitionTo(
- KeyguardState.LOCKSCREEN,
- ownerReason = "Dream has ended and device is awake"
- )
+ if (openHub) {
+ communalSceneInteractor.changeScene(
+ newScene = CommunalScenes.Communal,
+ loggingReason = "FromDreamingTransitionInteractor",
+ )
+ } else {
+ startTransitionTo(
+ KeyguardState.LOCKSCREEN,
+ ownerReason = "Dream has ended and device is awake"
+ )
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt
index befcc9e..c9db26d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt
@@ -159,6 +159,7 @@
if (communalSceneKtfRefactor()) {
communalSceneInteractor.changeScene(
newScene = CommunalScenes.Blank,
+ loggingReason = "hub to dozing",
transitionKey = CommunalTransitionKeys.Immediately,
keyguardState = KeyguardState.DOZING,
)
@@ -182,6 +183,7 @@
if (communalSceneKtfRefactor()) {
communalSceneInteractor.changeScene(
newScene = CommunalScenes.Blank,
+ loggingReason = "hub to occluded (KeyguardWmStateRefactor)",
transitionKey = CommunalTransitionKeys.SimpleFade,
keyguardState = state,
)
@@ -211,6 +213,7 @@
.collect { _ ->
communalSceneInteractor.changeScene(
newScene = CommunalScenes.Blank,
+ loggingReason = "hub to occluded",
transitionKey = CommunalTransitionKeys.SimpleFade,
keyguardState = KeyguardState.OCCLUDED,
)
@@ -254,6 +257,7 @@
} else {
communalSceneInteractor.changeScene(
newScene = CommunalScenes.Blank,
+ loggingReason = "hub to gone",
transitionKey = CommunalTransitionKeys.SimpleFade,
keyguardState = KeyguardState.GONE
)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt
index 905ca8e..7b6949f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt
@@ -146,8 +146,9 @@
if (SceneContainerFlag.isEnabled) return
if (communalSceneKtfRefactor()) {
communalSceneInteractor.changeScene(
- CommunalScenes.Communal,
- CommunalTransitionKeys.SimpleFade
+ newScene = CommunalScenes.Communal,
+ loggingReason = "occluded to hub",
+ transitionKey = CommunalTransitionKeys.SimpleFade
)
} else {
startTransitionTo(KeyguardState.GLANCEABLE_HUB)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
index 2823b93..0118f8e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
@@ -175,7 +175,10 @@
!communalSceneInteractor.isLaunchingWidget.value &&
communalSceneInteractor.editModeState.value == null
) {
- communalSceneInteractor.snapToScene(CommunalScenes.Blank)
+ communalSceneInteractor.snapToScene(
+ newScene = CommunalScenes.Blank,
+ loggingReason = "FromPrimaryBouncerTransitionInteractor",
+ )
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModel.kt
index 34c1436..38f5d3e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModel.kt
@@ -50,5 +50,9 @@
}
.distinctUntilChanged()
- fun openCommunalHub() = communalInteractor.changeScene(CommunalScenes.Communal)
+ fun openCommunalHub() =
+ communalInteractor.changeScene(
+ newScene = CommunalScenes.Communal,
+ loggingReason = "accessibility",
+ )
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
index b5ec7a6..10605b2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
@@ -18,7 +18,6 @@
import com.android.app.animation.Interpolators.EMPHASIZED
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.domain.interactor.FromDreamingTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.FromDreamingTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
import com.android.systemui.keyguard.shared.model.Edge
import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
@@ -39,10 +38,8 @@
class DreamingToLockscreenTransitionViewModel
@Inject
constructor(
- private val fromDreamingTransitionInteractor: FromDreamingTransitionInteractor,
animationFlow: KeyguardTransitionAnimationFlow,
) : DeviceEntryIconTransition {
- fun startTransition() = fromDreamingTransitionInteractor.startToLockscreenTransition()
private val transitionAnimation =
animationFlow.setup(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSModesEvent.kt b/packages/SystemUI/src/com/android/systemui/qs/QSModesEvent.kt
new file mode 100644
index 0000000..1891c41
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSModesEvent.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs
+
+import com.android.internal.logging.UiEvent
+import com.android.internal.logging.UiEventLogger
+
+/** Events of user interactions with modes from the QS Modes dialog. {@see ModesDialogViewModel} */
+enum class QSModesEvent(private val _id: Int) : UiEventLogger.UiEventEnum {
+ @UiEvent(doc = "User turned manual Do Not Disturb on via modes dialog") QS_MODES_DND_ON(1870),
+ @UiEvent(doc = "User turned manual Do Not Disturb off via modes dialog") QS_MODES_DND_OFF(1871),
+ @UiEvent(doc = "User opened mode settings from the Do Not Disturb tile in the modes dialog")
+ QS_MODES_DND_SETTINGS(1872),
+ @UiEvent(doc = "User turned automatic mode on via modes dialog") QS_MODES_MODE_ON(1873),
+ @UiEvent(doc = "User turned automatic mode off via modes dialog") QS_MODES_MODE_OFF(1874),
+ @UiEvent(doc = "User opened mode settings from a mode tile in the modes dialog")
+ QS_MODES_MODE_SETTINGS(1875),
+ @UiEvent(doc = "User clicked on Settings from the modes dialog") QS_MODES_SETTINGS(1876),
+ @UiEvent(doc = "User clicked on Do Not Disturb tile, opening the time selection dialog")
+ QS_MODES_DURATION_DIALOG(1879);
+
+ override fun getId() = _id
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorController.kt
index 2b7df7d..67c53d46 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorController.kt
@@ -142,14 +142,15 @@
}
override fun onIntentStarted(willAnimate: Boolean) {
+ val reason = "onIntentStarted(willAnimate=$willAnimate)"
if (ActivityTransitionAnimator.DEBUG_TRANSITION_ANIMATION) {
- Log.d(TAG, "onIntentStarted(willAnimate=$willAnimate)")
+ Log.d(TAG, reason)
}
notificationLaunchAnimationInteractor.setIsLaunchAnimationRunning(willAnimate)
notificationEntry.isExpandAnimationRunning = willAnimate
if (!willAnimate) {
- removeHun(animate = true)
+ removeHun(animate = true, reason)
onFinishAnimationCallback?.run()
}
}
@@ -166,13 +167,18 @@
}
}
- private fun removeHun(animate: Boolean) {
+ private fun removeHun(animate: Boolean, reason: String) {
val row = headsUpNotificationRow ?: return
// TODO: b/297247841 - Call on the row we're removing, which may differ from notification.
HeadsUpUtil.setNeedsHeadsUpDisappearAnimationAfterClick(notification, animate)
- headsUpManager.removeNotification(row.entry.key, true /* releaseImmediately */, animate)
+ headsUpManager.removeNotification(
+ row.entry.key,
+ true /* releaseImmediately */,
+ animate,
+ reason
+ )
}
override fun onTransitionAnimationCancelled(newKeyguardOccludedState: Boolean?) {
@@ -184,7 +190,7 @@
// here?
notificationLaunchAnimationInteractor.setIsLaunchAnimationRunning(false)
notificationEntry.isExpandAnimationRunning = false
- removeHun(animate = true)
+ removeHun(animate = true, "onLaunchAnimationCancelled()")
onFinishAnimationCallback?.run()
}
@@ -206,7 +212,7 @@
notificationEntry.isExpandAnimationRunning = false
notificationListContainer.setExpandingNotification(null)
applyParams(null)
- removeHun(animate = false)
+ removeHun(animate = false, "onLaunchAnimationEnd()")
onFinishAnimationCallback?.run()
}
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 e50d64b..ec8566b 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
@@ -496,7 +496,11 @@
if (posted?.shouldHeadsUpEver == false) {
if (posted.isHeadsUpEntry) {
// We don't want this to be interrupting anymore, let's remove it
- mHeadsUpManager.removeNotification(posted.key, false /*removeImmediately*/)
+ mHeadsUpManager.removeNotification(
+ posted.key,
+ /* removeImmediately= */ false,
+ "onEntryUpdated"
+ )
} else if (posted.isBinding) {
// Don't let the bind finish
cancelHeadsUpBind(posted.entry)
@@ -520,7 +524,11 @@
val removeImmediatelyForRemoteInput =
(mRemoteInputManager.isSpinning(entryKey) &&
!NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY)
- mHeadsUpManager.removeNotification(entry.key, removeImmediatelyForRemoteInput)
+ mHeadsUpManager.removeNotification(
+ entry.key,
+ removeImmediatelyForRemoteInput,
+ "onEntryRemoved, reason: $reason"
+ )
}
}
@@ -721,7 +729,9 @@
{
mHeadsUpManager.removeNotification(
entry.key, /* releaseImmediately */
- true
+ true,
+ "cancel lifetime extension - extended for reason: " +
+ "$reason, isSticky: true"
)
},
removeAfterMillis
@@ -730,7 +740,9 @@
mExecutor.execute {
mHeadsUpManager.removeNotification(
entry.key, /* releaseImmediately */
- false
+ false,
+ "lifetime extension - extended for reason: $reason" +
+ ", isSticky: false"
)
}
mNotifsExtendingLifetime[entry] = null
@@ -902,7 +914,7 @@
fun commitModifications() {
deferred.forEach { (key, releaseImmediately) ->
- headsUpManager.removeNotification(key, releaseImmediately)
+ headsUpManager.removeNotification(key, releaseImmediately, "commitModifications")
}
deferred.clear()
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 41195aa..fa12bb9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -638,8 +638,11 @@
if (row.isPinned() && !canChildBeDismissed(row)
&& row.getEntry().getSbn().getNotification().fullScreenIntent
== null) {
- mHeadsUpManager.removeNotification(row.getEntry().getSbn().getKey(),
- true /* removeImmediately */);
+ mHeadsUpManager.removeNotification(
+ row.getEntry().getSbn().getKey(),
+ /* removeImmediately= */ true ,
+ /* reason= */ "onChildSnappedBack"
+ );
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt
index 107bf1e..d4ef42c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt
@@ -613,8 +613,9 @@
super.onTransitionAnimationStart(isExpandingFullyAbove)
if (Flags.communalHub()) {
communalSceneInteractor.snapToScene(
- CommunalScenes.Blank,
- ActivityTransitionAnimator.TIMINGS.totalDuration
+ newScene = CommunalScenes.Blank,
+ loggingReason = "ActivityStarterInternalImpl",
+ delayMillis = ActivityTransitionAnimator.TIMINGS.totalDuration
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
index ac10155..ec92990 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
@@ -193,7 +193,11 @@
void fireNotificationPulse(NotificationEntry entry) {
Runnable pulseSuppressedListener = () -> {
mHeadsUpManager.removeNotification(
- entry.getKey(), /* releaseImmediately= */ true, /* animate= */ false);
+ entry.getKey(),
+ /* releaseImmediately= */ true,
+ /* animate= */ false,
+ "fireNotificationPulse"
+ );
};
Assert.isMainThread();
for (Callback callback : mCallbacks) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index 25d9cc7..544a8a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -60,11 +60,6 @@
import com.android.systemui.util.settings.GlobalSettings;
import com.android.systemui.util.time.SystemClock;
-import kotlinx.coroutines.flow.Flow;
-import kotlinx.coroutines.flow.MutableStateFlow;
-import kotlinx.coroutines.flow.StateFlow;
-import kotlinx.coroutines.flow.StateFlowKt;
-
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashSet;
@@ -75,6 +70,11 @@
import javax.inject.Inject;
+import kotlinx.coroutines.flow.Flow;
+import kotlinx.coroutines.flow.MutableStateFlow;
+import kotlinx.coroutines.flow.StateFlow;
+import kotlinx.coroutines.flow.StateFlowKt;
+
/** A implementation of HeadsUpManager for phone. */
@SysUISingleton
public class HeadsUpManagerPhone extends BaseHeadsUpManager implements
@@ -365,12 +365,14 @@
@Override
public boolean removeNotification(@NonNull String key, boolean releaseImmediately,
- boolean animate) {
+ boolean animate, @NonNull String reason) {
if (animate) {
- return removeNotification(key, releaseImmediately);
+ return removeNotification(key, releaseImmediately,
+ "removeNotification(animate: true), reason: " + reason);
} else {
mAnimationStateHandler.setHeadsUpGoingAwayAnimationsAllowed(false);
- boolean removed = removeNotification(key, releaseImmediately);
+ final boolean removed = removeNotification(key, releaseImmediately,
+ "removeNotification(animate: false), reason: " + reason);
mAnimationStateHandler.setHeadsUpGoingAwayAnimationsAllowed(true);
return removed;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 04604e0..dda02db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -32,6 +32,8 @@
import android.widget.FrameLayout;
import android.widget.LinearLayout;
+import androidx.annotation.NonNull;
+
import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.Dependency;
import com.android.systemui.Flags;
@@ -47,7 +49,6 @@
public class PhoneStatusBarView extends FrameLayout {
private static final String TAG = "PhoneStatusBarView";
- private final StatusBarContentInsetsProvider mContentInsetsProvider;
private final StatusBarWindowController mStatusBarWindowController;
private int mRotationOrientation = -1;
@@ -60,6 +61,10 @@
private int mStatusBarHeight;
@Nullable
private Gefingerpoken mTouchEventHandler;
+ @Nullable
+ private HasCornerCutoutFetcher mHasCornerCutoutFetcher;
+ @Nullable
+ private InsetsFetcher mInsetsFetcher;
private int mDensity;
private float mFontScale;
@@ -70,7 +75,6 @@
public PhoneStatusBarView(Context context, AttributeSet attrs) {
super(context, attrs);
- mContentInsetsProvider = Dependency.get(StatusBarContentInsetsProvider.class);
mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
}
@@ -78,6 +82,14 @@
mTouchEventHandler = handler;
}
+ void setHasCornerCutoutFetcher(@NonNull HasCornerCutoutFetcher cornerCutoutFetcher) {
+ mHasCornerCutoutFetcher = cornerCutoutFetcher;
+ }
+
+ void setInsetsFetcher(@NonNull InsetsFetcher insetsFetcher) {
+ mInsetsFetcher = insetsFetcher;
+ }
+
void init(StatusBarUserChipViewModel viewModel) {
StatusBarUserSwitcherContainer container = findViewById(R.id.user_switcher_container);
StatusBarUserChipViewBinder.bind(container, viewModel);
@@ -270,7 +282,14 @@
return;
}
- boolean hasCornerCutout = mContentInsetsProvider.currentRotationHasCornerCutout();
+ boolean hasCornerCutout;
+ if (mHasCornerCutoutFetcher != null) {
+ hasCornerCutout = mHasCornerCutoutFetcher.fetchHasCornerCutout();
+ } else {
+ Log.e(TAG, "mHasCornerCutoutFetcher unexpectedly null");
+ hasCornerCutout = true;
+ }
+
if (mDisplayCutout == null || mDisplayCutout.isEmpty() || hasCornerCutout) {
mCutoutSpace.setVisibility(View.GONE);
return;
@@ -288,8 +307,12 @@
}
private void updateSafeInsets() {
- Insets insets = mContentInsetsProvider
- .getStatusBarContentInsetsForCurrentRotation();
+ if (mInsetsFetcher == null) {
+ Log.e(TAG, "mInsetsFetcher unexpectedly null");
+ return;
+ }
+
+ Insets insets = mInsetsFetcher.fetchInsets();
setPadding(
insets.left,
insets.top,
@@ -298,6 +321,17 @@
}
private void updateWindowHeight() {
+ if (Flags.statusBarStopUpdatingWindowHeight()) {
+ return;
+ }
mStatusBarWindowController.refreshStatusBarHeight();
}
+
+ interface HasCornerCutoutFetcher {
+ boolean fetchHasCornerCutout();
+ }
+
+ interface InsetsFetcher {
+ Insets fetchInsets();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
index 468a3c3..456265b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
@@ -73,6 +73,7 @@
private val configurationController: ConfigurationController,
private val statusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory,
private val darkIconDispatcher: DarkIconDispatcher,
+ private val statusBarContentInsetsProvider: StatusBarContentInsetsProvider,
) : ViewController<PhoneStatusBarView>(view) {
private lateinit var battery: BatteryMeterView
@@ -155,7 +156,14 @@
}
init {
+ // These should likely be done in `onInit`, not `init`.
mView.setTouchEventHandler(PhoneStatusBarViewTouchHandler())
+ mView.setHasCornerCutoutFetcher {
+ statusBarContentInsetsProvider.currentRotationHasCornerCutout()
+ }
+ mView.setInsetsFetcher {
+ statusBarContentInsetsProvider.getStatusBarContentInsetsForCurrentRotation()
+ }
mView.init(userChipViewModel)
}
@@ -310,6 +318,7 @@
private val configurationController: ConfigurationController,
private val statusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory,
private val darkIconDispatcher: DarkIconDispatcher,
+ private val statusBarContentInsetsProvider: StatusBarContentInsetsProvider,
) {
fun create(view: PhoneStatusBarView): PhoneStatusBarViewController {
val statusBarMoveFromCenterAnimationController =
@@ -335,6 +344,7 @@
configurationController,
statusOverlayHoverListenerFactory,
darkIconDispatcher,
+ statusBarContentInsetsProvider,
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index e92058b..0a6e7f5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -230,7 +230,8 @@
Runnable action = () -> {
mBubblesManagerOptional.ifPresent(bubblesManager ->
bubblesManager.onUserChangedBubble(entry, !entry.isBubble()));
- mHeadsUpManager.removeNotification(entry.getKey(), /* releaseImmediately= */ true);
+ mHeadsUpManager.removeNotification(entry.getKey(), /* releaseImmediately= */ true,
+ /* reason= */ "onNotificationBubbleIconClicked");
};
if (entry.isBubble()) {
// entry is being un-bubbled, no need to unlock
@@ -621,7 +622,8 @@
// In most cases, when FLAG_AUTO_CANCEL is set, the notification will
// become canceled shortly by NoMan, but we can't assume that.
- mHeadsUpManager.removeNotification(key, true /* releaseImmediately */);
+ mHeadsUpManager.removeNotification(key, /* releaseImmediately= */ true,
+ "removeHunAfterClick");
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java
index 3786958..f37393a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BaseHeadsUpManager.java
@@ -40,13 +40,14 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
import com.android.systemui.statusbar.notification.shared.NotificationThrottleHun;
-import com.android.systemui.statusbar.notification.shared.NotificationsHeadsUpRefactor;
import com.android.systemui.statusbar.phone.ExpandHeadsUpOnInlineReply;
import com.android.systemui.util.ListenerSet;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.settings.GlobalSettings;
import com.android.systemui.util.time.SystemClock;
+import org.jetbrains.annotations.NotNull;
+
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -191,12 +192,14 @@
* enough and needs to be kept around.
* @param key the key of the notification to remove
* @param releaseImmediately force a remove regardless of earliest removal time
+ * @param reason reason for removing the notification
* @return true if notification is removed, false otherwise
*/
@Override
- public boolean removeNotification(@NonNull String key, boolean releaseImmediately) {
+ public boolean removeNotification(@NotNull String key, boolean releaseImmediately,
+ @NonNull String reason) {
final boolean isWaiting = mAvalancheController.isWaiting(key);
- mLogger.logRemoveNotification(key, releaseImmediately, isWaiting);
+ mLogger.logRemoveNotification(key, releaseImmediately, isWaiting, reason);
if (mAvalancheController.isWaiting(key)) {
removeEntry(key, "removeNotification (isWaiting)");
@@ -204,6 +207,7 @@
}
HeadsUpEntry headsUpEntry = mHeadsUpEntryMap.get(key);
if (headsUpEntry == null) {
+ mLogger.logNullEntry(key, reason);
return true;
}
if (releaseImmediately) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt
index fcf77d5..04fe6b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt
@@ -96,9 +96,10 @@
*
* @param key the key of the notification to remove
* @param releaseImmediately force a remove regardless of earliest removal time
+ * @param reason reason for removing the notification
* @return true if notification is removed, false otherwise
*/
- fun removeNotification(key: String, releaseImmediately: Boolean): Boolean
+ fun removeNotification(key: String, releaseImmediately: Boolean, reason: String): Boolean
/**
* Try to remove the notification. May not succeed if the notification has not been shown long
@@ -107,9 +108,15 @@
* @param key the key of the notification to remove
* @param releaseImmediately force a remove regardless of earliest removal time
* @param animate if true, animate the removal
+ * @param reason reason for removing the notification
* @return true if notification is removed, false otherwise
*/
- fun removeNotification(key: String, releaseImmediately: Boolean, animate: Boolean): Boolean
+ fun removeNotification(
+ key: String,
+ releaseImmediately: Boolean,
+ animate: Boolean,
+ reason: String
+ ): Boolean
/** Clears all managed notifications. */
fun releaseAllImmediately()
@@ -246,11 +253,16 @@
override fun removeListener(listener: OnHeadsUpChangedListener) {}
- override fun removeNotification(key: String, releaseImmediately: Boolean) = false
-
- override fun removeNotification(key: String, releaseImmediately: Boolean, animate: Boolean) =
+ override fun removeNotification(key: String, releaseImmediately: Boolean, reason: String) =
false
+ override fun removeNotification(
+ key: String,
+ releaseImmediately: Boolean,
+ animate: Boolean,
+ reason: String
+ ) = false
+
override fun setAnimationStateHandler(handler: AnimationStateHandler) {}
override fun setExpanded(entry: NotificationEntry, expanded: Boolean) {}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt
index 80c595f..c6fc547 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt
@@ -16,244 +16,283 @@
package com.android.systemui.statusbar.policy
-import com.android.systemui.log.dagger.NotificationHeadsUpLog
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.LogLevel.INFO
import com.android.systemui.log.core.LogLevel.VERBOSE
+import com.android.systemui.log.dagger.NotificationHeadsUpLog
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.logKey
import javax.inject.Inject
/** Logger for [HeadsUpManager]. */
-class HeadsUpManagerLogger @Inject constructor(
- @NotificationHeadsUpLog private val buffer: LogBuffer
-) {
+class HeadsUpManagerLogger
+@Inject
+constructor(@NotificationHeadsUpLog private val buffer: LogBuffer) {
fun logPackageSnoozed(snoozeKey: String) {
- buffer.log(TAG, INFO, {
- str1 = snoozeKey
- }, {
- "package snoozed $str1"
- })
+ buffer.log(TAG, INFO, { str1 = snoozeKey }, { "package snoozed $str1" })
}
fun logPackageUnsnoozed(snoozeKey: String) {
- buffer.log(TAG, INFO, {
- str1 = snoozeKey
- }, {
- "package unsnoozed $str1"
- })
+ buffer.log(TAG, INFO, { str1 = snoozeKey }, { "package unsnoozed $str1" })
}
fun logIsSnoozedReturned(snoozeKey: String) {
- buffer.log(TAG, INFO, {
- str1 = snoozeKey
- }, {
- "package snoozed when queried $str1"
- })
+ buffer.log(TAG, INFO, { str1 = snoozeKey }, { "package snoozed when queried $str1" })
}
fun logReleaseAllImmediately() {
- buffer.log(TAG, INFO, { }, {
- "release all immediately"
- })
+ buffer.log(TAG, INFO, {}, { "release all immediately" })
}
fun logShowNotificationRequest(entry: NotificationEntry) {
- buffer.log(TAG, INFO, {
- str1 = entry.logKey
- }, {
- "request: show notification $str1"
- })
+ buffer.log(TAG, INFO, { str1 = entry.logKey }, { "request: show notification $str1" })
}
- fun logAvalancheUpdate(caller: String, isEnabled: Boolean, notifEntryKey: String,
- outcome: String) {
- buffer.log(TAG, INFO, {
- str1 = caller
- str2 = notifEntryKey
- str3 = outcome
- bool1 = isEnabled
- }, {
- "$str1\n\t=> AC[isEnabled:$bool1] update: $str2\n\t=> $str3"
- })
+ fun logAvalancheUpdate(
+ caller: String,
+ isEnabled: Boolean,
+ notifEntryKey: String,
+ outcome: String
+ ) {
+ buffer.log(
+ TAG,
+ INFO,
+ {
+ str1 = caller
+ str2 = notifEntryKey
+ str3 = outcome
+ bool1 = isEnabled
+ },
+ { "$str1\n\t=> AC[isEnabled:$bool1] update: $str2\n\t=> $str3" }
+ )
}
- fun logAvalancheDelete(caller: String, isEnabled: Boolean, notifEntryKey: String,
- outcome: String) {
- buffer.log(TAG, INFO, {
- str1 = caller
- str2 = notifEntryKey
- str3 = outcome
- bool1 = isEnabled
- }, {
- "$str1\n\t=> AC[isEnabled:$bool1] delete: $str2\n\t=> $str3"
- })
+ fun logAvalancheDelete(
+ caller: String,
+ isEnabled: Boolean,
+ notifEntryKey: String,
+ outcome: String
+ ) {
+ buffer.log(
+ TAG,
+ INFO,
+ {
+ str1 = caller
+ str2 = notifEntryKey
+ str3 = outcome
+ bool1 = isEnabled
+ },
+ { "$str1\n\t=> AC[isEnabled:$bool1] delete: $str2\n\t=> $str3" }
+ )
}
fun logShowNotification(entry: NotificationEntry) {
- buffer.log(TAG, INFO, {
- str1 = entry.logKey
- }, {
- "show notification $str1"
- })
+ buffer.log(TAG, INFO, { str1 = entry.logKey }, { "show notification $str1" })
}
fun logAutoRemoveScheduled(entry: NotificationEntry, delayMillis: Long, reason: String) {
- buffer.log(TAG, INFO, {
- str1 = entry.logKey
- long1 = delayMillis
- str2 = reason
- }, {
- "schedule auto remove of $str1 in $long1 ms reason: $str2"
- })
+ buffer.log(
+ TAG,
+ INFO,
+ {
+ str1 = entry.logKey
+ long1 = delayMillis
+ str2 = reason
+ },
+ { "schedule auto remove of $str1 in $long1 ms reason: $str2" }
+ )
}
fun logAutoRemoveRequest(entry: NotificationEntry, reason: String) {
- buffer.log(TAG, INFO, {
- str1 = entry.logKey
- str2 = reason
- }, {
- "request: reschedule auto remove of $str1 reason: $str2"
- })
+ buffer.log(
+ TAG,
+ INFO,
+ {
+ str1 = entry.logKey
+ str2 = reason
+ },
+ { "request: reschedule auto remove of $str1 reason: $str2" }
+ )
}
fun logAutoRemoveRescheduled(entry: NotificationEntry, delayMillis: Long, reason: String) {
- buffer.log(TAG, INFO, {
- str1 = entry.logKey
- long1 = delayMillis
- str2 = reason
- }, {
- "reschedule auto remove of $str1 in $long1 ms reason: $str2"
- })
+ buffer.log(
+ TAG,
+ INFO,
+ {
+ str1 = entry.logKey
+ long1 = delayMillis
+ str2 = reason
+ },
+ { "reschedule auto remove of $str1 in $long1 ms reason: $str2" }
+ )
}
fun logAutoRemoveCancelRequest(entry: NotificationEntry, reason: String?) {
- buffer.log(TAG, INFO, {
- str1 = entry.logKey
- str2 = reason ?: "unknown"
- }, {
- "request: cancel auto remove of $str1 reason: $str2"
- })
+ buffer.log(
+ TAG,
+ INFO,
+ {
+ str1 = entry.logKey
+ str2 = reason ?: "unknown"
+ },
+ { "request: cancel auto remove of $str1 reason: $str2" }
+ )
}
fun logAutoRemoveCanceled(entry: NotificationEntry, reason: String?) {
- buffer.log(TAG, INFO, {
- str1 = entry.logKey
- str2 = reason ?: "unknown"
- }, {
- "cancel auto remove of $str1 reason: $str2"
- })
+ buffer.log(
+ TAG,
+ INFO,
+ {
+ str1 = entry.logKey
+ str2 = reason ?: "unknown"
+ },
+ { "cancel auto remove of $str1 reason: $str2" }
+ )
}
fun logRemoveEntryRequest(key: String, reason: String, isWaiting: Boolean) {
- buffer.log(TAG, INFO, {
- str1 = logKey(key)
- str2 = reason
- bool1 = isWaiting
- }, {
- "request: $str2 => remove entry $str1 isWaiting: $isWaiting"
- })
+ buffer.log(
+ TAG,
+ INFO,
+ {
+ str1 = logKey(key)
+ str2 = reason
+ bool1 = isWaiting
+ },
+ { "request: $str2 => remove entry $str1 isWaiting: $isWaiting" }
+ )
}
fun logRemoveEntry(key: String, reason: String, isWaiting: Boolean) {
- buffer.log(TAG, INFO, {
- str1 = logKey(key)
- str2 = reason
- bool1 = isWaiting
- }, {
- "$str2 => remove entry $str1 isWaiting: $isWaiting"
- })
+ buffer.log(
+ TAG,
+ INFO,
+ {
+ str1 = logKey(key)
+ str2 = reason
+ bool1 = isWaiting
+ },
+ { "$str2 => remove entry $str1 isWaiting: $isWaiting" }
+ )
}
fun logUnpinEntryRequest(key: String) {
- buffer.log(TAG, INFO, {
- str1 = logKey(key)
- }, {
- "request: unpin entry $str1"
- })
+ buffer.log(TAG, INFO, { str1 = logKey(key) }, { "request: unpin entry $str1" })
}
fun logUnpinEntry(key: String) {
- buffer.log(TAG, INFO, {
- str1 = logKey(key)
- }, {
- "unpin entry $str1"
- })
+ buffer.log(TAG, INFO, { str1 = logKey(key) }, { "unpin entry $str1" })
}
- fun logRemoveNotification(key: String, releaseImmediately: Boolean, isWaiting: Boolean) {
- buffer.log(TAG, INFO, {
- str1 = logKey(key)
- bool1 = releaseImmediately
- bool2 = isWaiting
- }, {
- "remove notification $str1 releaseImmediately: $bool1 isWaiting: $bool2"
- })
+ fun logRemoveNotification(
+ key: String,
+ releaseImmediately: Boolean,
+ isWaiting: Boolean,
+ reason: String
+ ) {
+ buffer.log(
+ TAG,
+ INFO,
+ {
+ str1 = logKey(key)
+ bool1 = releaseImmediately
+ bool2 = isWaiting
+ str2 = reason
+ },
+ {
+ "remove notification $str1 releaseImmediately: $bool1 isWaiting: $bool2 " +
+ "reason: $str2"
+ }
+ )
+ }
+
+ fun logNullEntry(key: String, reason: String) {
+ buffer.log(
+ TAG,
+ INFO,
+ {
+ str1 = logKey(key)
+ str2 = reason
+ },
+ { "remove notification $str1 when headsUpEntry is null, reason: $str2" }
+ )
}
fun logNotificationActuallyRemoved(entry: NotificationEntry) {
- buffer.log(TAG, INFO, {
- str1 = entry.logKey
- }, {
- "notification removed $str1 "
- })
+ buffer.log(TAG, INFO, { str1 = entry.logKey }, { "notification removed $str1 " })
}
fun logUpdateNotificationRequest(key: String, alert: Boolean, hasEntry: Boolean) {
- buffer.log(TAG, INFO, {
- str1 = logKey(key)
- bool1 = alert
- bool2 = hasEntry
- }, {
- "request: update notification $str1 alert: $bool1 hasEntry: $bool2"
- })
+ buffer.log(
+ TAG,
+ INFO,
+ {
+ str1 = logKey(key)
+ bool1 = alert
+ bool2 = hasEntry
+ },
+ { "request: update notification $str1 alert: $bool1 hasEntry: $bool2" }
+ )
}
fun logUpdateNotification(key: String, alert: Boolean, hasEntry: Boolean) {
- buffer.log(TAG, INFO, {
- str1 = logKey(key)
- bool1 = alert
- bool2 = hasEntry
- }, {
- "update notification $str1 alert: $bool1 hasEntry: $bool2"
- })
+ buffer.log(
+ TAG,
+ INFO,
+ {
+ str1 = logKey(key)
+ bool1 = alert
+ bool2 = hasEntry
+ },
+ { "update notification $str1 alert: $bool1 hasEntry: $bool2" }
+ )
}
fun logUpdateEntry(entry: NotificationEntry, updatePostTime: Boolean, reason: String?) {
- buffer.log(TAG, INFO, {
- str1 = entry.logKey
- bool1 = updatePostTime
- str2 = reason ?: "unknown"
- }, {
- "update entry $str1 updatePostTime: $bool1 reason: $str2"
- })
+ buffer.log(
+ TAG,
+ INFO,
+ {
+ str1 = entry.logKey
+ bool1 = updatePostTime
+ str2 = reason ?: "unknown"
+ },
+ { "update entry $str1 updatePostTime: $bool1 reason: $str2" }
+ )
}
fun logSnoozeLengthChange(packageSnoozeLengthMs: Int) {
- buffer.log(TAG, INFO, {
- int1 = packageSnoozeLengthMs
- }, {
- "snooze length changed: ${int1}ms"
- })
+ buffer.log(
+ TAG,
+ INFO,
+ { int1 = packageSnoozeLengthMs },
+ { "snooze length changed: ${int1}ms" }
+ )
}
fun logSetEntryPinned(entry: NotificationEntry, isPinned: Boolean, reason: String) {
- buffer.log(TAG, VERBOSE, {
- str1 = entry.logKey
- bool1 = isPinned
- str2 = reason
- }, {
- "$str2 => set entry pinned $str1 pinned: $bool1"
- })
+ buffer.log(
+ TAG,
+ VERBOSE,
+ {
+ str1 = entry.logKey
+ bool1 = isPinned
+ str2 = reason
+ },
+ { "$str2 => set entry pinned $str1 pinned: $bool1" }
+ )
}
fun logUpdatePinnedMode(hasPinnedNotification: Boolean) {
- buffer.log(TAG, INFO, {
- bool1 = hasPinnedNotification
- }, {
- "has pinned notification changed to $bool1"
- })
+ buffer.log(
+ TAG,
+ INFO,
+ { bool1 = hasPinnedNotification },
+ { "has pinned notification changed to $bool1" }
+ )
}
}
-private const val TAG = "HeadsUpManager"
\ No newline at end of file
+private const val TAG = "HeadsUpManager"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegate.kt
index 8aa989f..4f7749b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegate.kt
@@ -57,6 +57,7 @@
private val activityStarter: ActivityStarter,
// Using a provider to avoid a circular dependency.
private val viewModel: Provider<ModesDialogViewModel>,
+ private val dialogEventLogger: ModesDialogEventLogger,
@Main private val mainCoroutineContext: CoroutineContext,
) : SystemUIDialog.Delegate {
// NOTE: This should only be accessed/written from the main thread.
@@ -102,7 +103,9 @@
)
}
- private fun openSettings(dialog: SystemUIDialog) {
+ @VisibleForTesting
+ fun openSettings(dialog: SystemUIDialog) {
+ dialogEventLogger.logDialogSettings()
val animationController =
dialogTransitionAnimator.createActivityTransitionController(dialog)
if (animationController == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogEventLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogEventLogger.kt
new file mode 100644
index 0000000..33ed419
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogEventLogger.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 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.policy.ui.dialog
+
+import com.android.internal.logging.UiEventLogger
+import com.android.settingslib.notification.modes.ZenMode
+import com.android.systemui.qs.QSModesEvent
+import javax.inject.Inject
+
+class ModesDialogEventLogger
+@Inject
+constructor(
+ private val uiEventLogger: UiEventLogger,
+) {
+
+ fun logModeOn(mode: ZenMode) {
+ val id =
+ if (mode.isManualDnd) QSModesEvent.QS_MODES_DND_ON else QSModesEvent.QS_MODES_MODE_ON
+ uiEventLogger.log(id, /* uid= */ 0, mode.rule.packageName)
+ }
+
+ fun logModeOff(mode: ZenMode) {
+ val id =
+ if (mode.isManualDnd) QSModesEvent.QS_MODES_DND_OFF else QSModesEvent.QS_MODES_MODE_OFF
+ uiEventLogger.log(id, /* uid= */ 0, mode.rule.packageName)
+ }
+
+ fun logModeSettings(mode: ZenMode) {
+ val id =
+ if (mode.isManualDnd) QSModesEvent.QS_MODES_DND_SETTINGS
+ else QSModesEvent.QS_MODES_MODE_SETTINGS
+ uiEventLogger.log(id, /* uid= */ 0, mode.rule.packageName)
+ }
+
+ fun logOpenDurationDialog(mode: ZenMode) {
+ // should only occur for manual Do Not Disturb.
+ if (!mode.isManualDnd) {
+ return
+ }
+ uiEventLogger.log(QSModesEvent.QS_MODES_DURATION_DIALOG)
+ }
+
+ fun logDialogSettings() {
+ uiEventLogger.log(QSModesEvent.QS_MODES_SETTINGS)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt
index 44b692f..5772099 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModel.kt
@@ -30,6 +30,7 @@
import com.android.systemui.statusbar.phone.SystemUIDialog
import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor
import com.android.systemui.statusbar.policy.ui.dialog.ModesDialogDelegate
+import com.android.systemui.statusbar.policy.ui.dialog.ModesDialogEventLogger
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
@@ -49,6 +50,7 @@
zenModeInteractor: ZenModeInteractor,
@Background val bgDispatcher: CoroutineDispatcher,
private val dialogDelegate: ModesDialogDelegate,
+ private val dialogEventLogger: ModesDialogEventLogger,
) {
private val zenDialogMetricsLogger = QSZenModeDialogMetricsLogger(context)
@@ -94,14 +96,17 @@
if (!mode.rule.isEnabled) {
openSettings(mode)
} else if (mode.isActive) {
+ dialogEventLogger.logModeOff(mode)
zenModeInteractor.deactivateMode(mode)
} else {
if (mode.rule.isManualInvocationAllowed) {
if (zenModeInteractor.shouldAskForZenDuration(mode)) {
+ dialogEventLogger.logOpenDurationDialog(mode)
// NOTE: The dialog handles turning on the mode itself.
val dialog = makeZenModeDialog()
dialog.show()
} else {
+ dialogEventLogger.logModeOn(mode)
zenModeInteractor.activateMode(mode)
}
}
@@ -114,6 +119,7 @@
.flowOn(bgDispatcher)
private fun openSettings(mode: ZenMode) {
+ dialogEventLogger.logModeSettings(mode)
val intent: Intent =
Intent(ACTION_AUTOMATIC_ZEN_RULE_SETTINGS)
.putExtra(EXTRA_AUTOMATIC_ZEN_RULE_ID, mode.id)
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index c62b5e0..7aa415b 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -102,6 +102,7 @@
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
+import android.platform.test.flag.junit.FlagsParameterization;
import android.service.dreams.IDreamManager;
import android.service.trust.TrustAgentService;
import android.telephony.ServiceState;
@@ -111,7 +112,6 @@
import android.testing.TestableLooper;
import android.text.TextUtils;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.android.compose.animation.scene.ObservableTransitionState;
@@ -140,6 +140,7 @@
import com.android.systemui.deviceentry.shared.model.FaceDetectionStatus;
import com.android.systemui.deviceentry.shared.model.FailedFaceAuthenticationStatus;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.SceneContainerFlagParameterizationKt;
import com.android.systemui.kosmos.KosmosJavaAdapter;
import com.android.systemui.log.SessionTracker;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -181,8 +182,11 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
@SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(ParameterizedAndroidJunit4.class)
@TestableLooper.RunWithLooper
public class KeyguardUpdateMonitorTest extends SysuiTestCase {
private static final String PKG_ALLOWING_FP_LISTEN_ON_OCCLUDING_ACTIVITY =
@@ -313,6 +317,16 @@
mFingerprintAuthenticatorsRegisteredCallback;
private final InstanceId mKeyguardInstanceId = InstanceId.fakeInstanceId(999);
+ @Parameters(name = "{0}")
+ public static List<FlagsParameterization> getParams() {
+ return SceneContainerFlagParameterizationKt.parameterizeSceneContainerFlag();
+ }
+
+ public KeyguardUpdateMonitorTest(FlagsParameterization flags) {
+ super();
+ mSetFlagsRule.setFlagsParameterization(flags);
+ }
+
@Before
public void setup() throws RemoteException {
mKosmos = new KosmosJavaAdapter(this);
@@ -2473,11 +2487,11 @@
private void setPrimaryBouncerVisibility(boolean isVisible) {
if (SceneContainerFlag.isEnabled()) {
- when(mSceneInteractor.getCurrentScene()).thenReturn(
- isVisible
- ? MutableStateFlow(Scenes.Bouncer)
- : MutableStateFlow(Scenes.Lockscreen));
- onTransitionStateChanged(new ObservableTransitionState.Idle(Scenes.Bouncer));
+ ObservableTransitionState transitionState = new ObservableTransitionState.Idle(
+ isVisible ? Scenes.Bouncer : Scenes.Lockscreen);
+ when(mSceneInteractor.getTransitionState()).thenReturn(
+ MutableStateFlow(transitionState));
+ onTransitionStateChanged(transitionState);
} else {
sendPrimaryBouncerChanged(isVisible, isVisible);
mTestableLooper.processAllMessages();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorControllerTest.kt
index 3abdf62..cb92b77 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationTransitionAnimatorControllerTest.kt
@@ -91,7 +91,12 @@
assertFalse(isExpandAnimationRunning!!)
verify(headsUpManager)
- .removeNotification(notificationKey, true /* releaseImmediately */, true /* animate */)
+ .removeNotification(
+ notificationKey,
+ /* releaseImmediately= */ true,
+ /* animate= */ true,
+ /* reason= */ "onIntentStarted(willAnimate=false)"
+ )
verify(onFinishAnimationCallback).run()
}
@@ -109,7 +114,12 @@
assertFalse(isExpandAnimationRunning!!)
verify(headsUpManager)
- .removeNotification(notificationKey, true /* releaseImmediately */, true /* animate */)
+ .removeNotification(
+ notificationKey,
+ /* releaseImmediately= */ true,
+ /* animate= */ true,
+ /* reason= */ "onLaunchAnimationCancelled()"
+ )
verify(onFinishAnimationCallback).run()
}
@@ -127,7 +137,12 @@
assertFalse(isExpandAnimationRunning!!)
verify(headsUpManager)
- .removeNotification(notificationKey, true /* releaseImmediately */, false /* animate */)
+ .removeNotification(
+ notificationKey,
+ /* releaseImmediately= */ true,
+ /* animate= */ false,
+ /* reason= */ "onLaunchAnimationEnd()"
+ )
verify(onFinishAnimationCallback).run()
}
@@ -161,12 +176,18 @@
controller.onTransitionAnimationEnd(isExpandingFullyAbove = true)
verify(headsUpManager)
- .removeNotification(summary.key, true /* releaseImmediately */, false /* animate */)
+ .removeNotification(
+ summary.key,
+ /* releaseImmediately= */ true,
+ /* animate= */ false,
+ /* reason= */ "onLaunchAnimationEnd()"
+ )
verify(headsUpManager, never())
.removeNotification(
notification.entry.key,
- true /* releaseImmediately */,
- false /* animate */
+ /* releaseImmediately= */ true,
+ /* animate= */ false,
+ /* reason= */ "onLaunchAnimationEnd()"
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
index 8e9323f..b4f4138 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
@@ -108,30 +108,31 @@
private val executor = FakeExecutor(systemClock)
private val huns: ArrayList<NotificationEntry> = ArrayList()
private lateinit var helper: NotificationGroupTestHelper
+
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
helper = NotificationGroupTestHelper(mContext)
- coordinator = HeadsUpCoordinator(
- logger,
- systemClock,
- headsUpManager,
- headsUpViewBinder,
- visualInterruptionDecisionProvider,
- remoteInputManager,
- launchFullScreenIntentProvider,
- flags,
- headerController,
- executor)
+ coordinator =
+ HeadsUpCoordinator(
+ logger,
+ systemClock,
+ headsUpManager,
+ headsUpViewBinder,
+ visualInterruptionDecisionProvider,
+ remoteInputManager,
+ launchFullScreenIntentProvider,
+ flags,
+ headerController,
+ executor
+ )
coordinator.attach(notifPipeline)
// capture arguments:
collectionListener = withArgCaptor {
verify(notifPipeline).addCollectionListener(capture())
}
- notifPromoter = withArgCaptor {
- verify(notifPipeline).addPromoter(capture())
- }
+ notifPromoter = withArgCaptor { verify(notifPipeline).addPromoter(capture()) }
notifLifetimeExtender = withArgCaptor {
verify(notifPipeline).addNotificationLifetimeExtender(capture())
}
@@ -141,9 +142,7 @@
beforeFinalizeFilterListener = withArgCaptor {
verify(notifPipeline).addOnBeforeFinalizeFilterListener(capture())
}
- onHeadsUpChangedListener = withArgCaptor {
- verify(headsUpManager).addListener(capture())
- }
+ onHeadsUpChangedListener = withArgCaptor { verify(headsUpManager).addListener(capture()) }
actionPressListener = withArgCaptor {
verify(remoteInputManager).addActionPressListener(capture())
}
@@ -187,8 +186,8 @@
assertTrue(notifLifetimeExtender.maybeExtendLifetime(entry, 0))
executor.advanceClockToLast()
executor.runAllReady()
- verify(headsUpManager, times(0)).removeNotification(anyString(), eq(false))
- verify(headsUpManager, times(1)).removeNotification(anyString(), eq(true))
+ verify(headsUpManager, times(0)).removeNotification(anyString(), eq(false), anyString())
+ verify(headsUpManager, times(1)).removeNotification(anyString(), eq(true), anyString())
}
@Test
@@ -203,8 +202,8 @@
executor.advanceClockToLast()
executor.runAllReady()
assertTrue(notifLifetimeExtender.maybeExtendLifetime(entry, 0))
- verify(headsUpManager, times(0)).removeNotification(anyString(), eq(false))
- verify(headsUpManager, times(0)).removeNotification(anyString(), eq(true))
+ verify(headsUpManager, times(0)).removeNotification(anyString(), eq(false), anyString())
+ verify(headsUpManager, times(0)).removeNotification(anyString(), eq(true), anyString())
}
@Test
@@ -217,7 +216,7 @@
notifLifetimeExtender.cancelLifetimeExtension(entry)
executor.advanceClockToLast()
executor.runAllReady()
- verify(headsUpManager, times(0)).removeNotification(anyString(), any())
+ verify(headsUpManager, never()).removeNotification(anyString(), any(), anyString())
}
@Test
@@ -227,14 +226,14 @@
whenever(headsUpManager.canRemoveImmediately(anyString())).thenReturn(false)
whenever(headsUpManager.getEarliestRemovalTime(anyString())).thenReturn(1000L)
- assertTrue(notifLifetimeExtender.maybeExtendLifetime(entry, /* reason = */ 0))
+ assertTrue(notifLifetimeExtender.maybeExtendLifetime(entry, /* reason= */ 0))
actionPressListener.accept(entry)
executor.runAllReady()
verify(endLifetimeExtension, times(1)).onEndLifetimeExtension(notifLifetimeExtender, entry)
- collectionListener.onEntryRemoved(entry, /* reason = */ 0)
- verify(headsUpManager, times(1)).removeNotification(eq(entry.key), any())
+ collectionListener.onEntryRemoved(entry, /* reason= */ 0)
+ verify(headsUpManager, times(1)).removeNotification(eq(entry.key), any(), anyString())
}
@Test
@@ -248,8 +247,8 @@
whenever(headsUpManager.canRemoveImmediately(anyString())).thenReturn(true)
assertFalse(notifLifetimeExtender.maybeExtendLifetime(entry, 0))
- collectionListener.onEntryRemoved(entry, /* reason = */ 0)
- verify(headsUpManager, times(1)).removeNotification(eq(entry.key), any())
+ collectionListener.onEntryRemoved(entry, /* reason= */ 0)
+ verify(headsUpManager, times(1)).removeNotification(eq(entry.key), any(), anyString())
}
@Test
@@ -261,8 +260,8 @@
addHUN(entry)
executor.advanceClockToLast()
executor.runAllReady()
- verify(headsUpManager, times(0)).removeNotification(anyString(), eq(false))
- verify(headsUpManager, times(0)).removeNotification(anyString(), eq(true))
+ verify(headsUpManager, never()).removeNotification(anyString(), eq(false), anyString())
+ verify(headsUpManager, never()).removeNotification(anyString(), eq(true), anyString())
}
@Test
@@ -273,8 +272,8 @@
assertTrue(notifLifetimeExtender.maybeExtendLifetime(entry, 0))
executor.advanceClockToLast()
executor.runAllReady()
- verify(headsUpManager, times(1)).removeNotification(anyString(), eq(false))
- verify(headsUpManager, times(0)).removeNotification(anyString(), eq(true))
+ verify(headsUpManager, times(1)).removeNotification(anyString(), eq(false), anyString())
+ verify(headsUpManager, never()).removeNotification(anyString(), eq(true), anyString())
}
@Test
@@ -326,9 +325,8 @@
// THEN only promote the current HUN, mEntry
assertTrue(notifPromoter.shouldPromoteToTopLevel(entry))
- assertFalse(notifPromoter.shouldPromoteToTopLevel(NotificationEntryBuilder()
- .setPkg("test-package2")
- .build()))
+ val testPackage2 = NotificationEntryBuilder().setPkg("test-package2").build()
+ assertFalse(notifPromoter.shouldPromoteToTopLevel(testPackage2))
}
@Test
@@ -338,9 +336,9 @@
// THEN only section the current HUN, mEntry
assertTrue(notifSectioner.isInSection(entry))
- assertFalse(notifSectioner.isInSection(NotificationEntryBuilder()
- .setPkg("test-package")
- .build()))
+ assertFalse(
+ notifSectioner.isInSection(NotificationEntryBuilder().setPkg("test-package").build())
+ )
}
@Test
@@ -350,10 +348,12 @@
// THEN only the current HUN, mEntry, should be lifetimeExtended
assertTrue(notifLifetimeExtender.maybeExtendLifetime(entry, /* cancellationReason */ 0))
- assertFalse(notifLifetimeExtender.maybeExtendLifetime(
- NotificationEntryBuilder()
- .setPkg("test-package")
- .build(), /* cancellationReason */ 0))
+ assertFalse(
+ notifLifetimeExtender.maybeExtendLifetime(
+ NotificationEntryBuilder().setPkg("test-package").build(),
+ /* reason= */ 0
+ )
+ )
}
@Test
@@ -366,8 +366,9 @@
beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(entry))
verify(headsUpManager, never()).showNotification(entry)
withArgCaptor<BindCallback> {
- verify(headsUpViewBinder).bindHeadsUpView(eq(entry), capture())
- }.onBindFinished(entry)
+ verify(headsUpViewBinder).bindHeadsUpView(eq(entry), capture())
+ }
+ .onBindFinished(entry)
// THEN we tell the HeadsUpManager to show the notification
verify(headsUpManager).showNotification(entry)
@@ -430,7 +431,7 @@
whenever(remoteInputManager.isSpinning(any())).thenReturn(false)
// THEN heads up manager should remove the entry
- verify(headsUpManager).removeNotification(entry.key, false)
+ verify(headsUpManager).removeNotification(eq(entry.key), eq(false), anyString())
}
private fun addHUN(entry: NotificationEntry) {
@@ -545,19 +546,22 @@
collectionListener.onEntryAdded(groupSibling1)
collectionListener.onEntryAdded(groupSibling2)
- val beforeTransformGroup = GroupEntryBuilder()
- .setSummary(groupSummary)
- .setChildren(listOf(groupSibling1, groupPriority, groupSibling2))
- .build()
+ val beforeTransformGroup =
+ GroupEntryBuilder()
+ .setSummary(groupSummary)
+ .setChildren(listOf(groupSibling1, groupPriority, groupSibling2))
+ .build()
beforeTransformGroupsListener.onBeforeTransformGroups(listOf(beforeTransformGroup))
verify(headsUpViewBinder, never()).bindHeadsUpView(any(), any())
- val afterTransformGroup = GroupEntryBuilder()
- .setSummary(groupSummary)
- .setChildren(listOf(groupSibling1, groupSibling2))
- .build()
- beforeFinalizeFilterListener
- .onBeforeFinalizeFilter(listOf(groupPriority, afterTransformGroup))
+ val afterTransformGroup =
+ GroupEntryBuilder()
+ .setSummary(groupSummary)
+ .setChildren(listOf(groupSibling1, groupSibling2))
+ .build()
+ beforeFinalizeFilterListener.onBeforeFinalizeFilter(
+ listOf(groupPriority, afterTransformGroup)
+ )
verify(headsUpViewBinder, never()).bindHeadsUpView(eq(groupSummary), any())
finishBind(groupPriority)
@@ -583,19 +587,22 @@
collectionListener.onEntryUpdated(groupSibling1)
collectionListener.onEntryUpdated(groupSibling2)
- val beforeTransformGroup = GroupEntryBuilder()
- .setSummary(groupSummary)
- .setChildren(listOf(groupSibling1, groupPriority, groupSibling2))
- .build()
+ val beforeTransformGroup =
+ GroupEntryBuilder()
+ .setSummary(groupSummary)
+ .setChildren(listOf(groupSibling1, groupPriority, groupSibling2))
+ .build()
beforeTransformGroupsListener.onBeforeTransformGroups(listOf(beforeTransformGroup))
verify(headsUpViewBinder, never()).bindHeadsUpView(any(), any())
- val afterTransformGroup = GroupEntryBuilder()
- .setSummary(groupSummary)
- .setChildren(listOf(groupSibling1, groupSibling2))
- .build()
- beforeFinalizeFilterListener
- .onBeforeFinalizeFilter(listOf(groupPriority, afterTransformGroup))
+ val afterTransformGroup =
+ GroupEntryBuilder()
+ .setSummary(groupSummary)
+ .setChildren(listOf(groupSibling1, groupSibling2))
+ .build()
+ beforeFinalizeFilterListener.onBeforeFinalizeFilter(
+ listOf(groupPriority, afterTransformGroup)
+ )
verify(headsUpViewBinder, never()).bindHeadsUpView(eq(groupSummary), any())
finishBind(groupPriority)
@@ -618,19 +625,22 @@
collectionListener.onEntryUpdated(groupSummary)
collectionListener.onEntryUpdated(groupPriority)
- val beforeTransformGroup = GroupEntryBuilder()
- .setSummary(groupSummary)
- .setChildren(listOf(groupSibling1, groupPriority, groupSibling2))
- .build()
+ val beforeTransformGroup =
+ GroupEntryBuilder()
+ .setSummary(groupSummary)
+ .setChildren(listOf(groupSibling1, groupPriority, groupSibling2))
+ .build()
beforeTransformGroupsListener.onBeforeTransformGroups(listOf(beforeTransformGroup))
verify(headsUpViewBinder, never()).bindHeadsUpView(any(), any())
- val afterTransformGroup = GroupEntryBuilder()
- .setSummary(groupSummary)
- .setChildren(listOf(groupSibling1, groupSibling2))
- .build()
- beforeFinalizeFilterListener
- .onBeforeFinalizeFilter(listOf(groupPriority, afterTransformGroup))
+ val afterTransformGroup =
+ GroupEntryBuilder()
+ .setSummary(groupSummary)
+ .setChildren(listOf(groupSibling1, groupSibling2))
+ .build()
+ beforeFinalizeFilterListener.onBeforeFinalizeFilter(
+ listOf(groupPriority, afterTransformGroup)
+ )
verify(headsUpViewBinder, never()).bindHeadsUpView(eq(groupSummary), any())
finishBind(groupPriority)
@@ -654,19 +664,22 @@
collectionListener.onEntryUpdated(groupSibling1)
collectionListener.onEntryUpdated(groupSibling2)
- val beforeTransformGroup = GroupEntryBuilder()
- .setSummary(groupSummary)
- .setChildren(listOf(groupSibling1, groupPriority, groupSibling2))
- .build()
+ val beforeTransformGroup =
+ GroupEntryBuilder()
+ .setSummary(groupSummary)
+ .setChildren(listOf(groupSibling1, groupPriority, groupSibling2))
+ .build()
beforeTransformGroupsListener.onBeforeTransformGroups(listOf(beforeTransformGroup))
verify(headsUpViewBinder, never()).bindHeadsUpView(any(), any())
- val afterTransformGroup = GroupEntryBuilder()
- .setSummary(groupSummary)
- .setChildren(listOf(groupSibling1, groupSibling2))
- .build()
- beforeFinalizeFilterListener
- .onBeforeFinalizeFilter(listOf(groupPriority, afterTransformGroup))
+ val afterTransformGroup =
+ GroupEntryBuilder()
+ .setSummary(groupSummary)
+ .setChildren(listOf(groupSibling1, groupSibling2))
+ .build()
+ beforeFinalizeFilterListener.onBeforeFinalizeFilter(
+ listOf(groupPriority, afterTransformGroup)
+ )
finishBind(groupSummary)
verify(headsUpViewBinder, never()).bindHeadsUpView(eq(groupPriority), any())
@@ -688,10 +701,11 @@
collectionListener.onEntryAdded(groupSummary)
collectionListener.onEntryAdded(groupSibling1)
collectionListener.onEntryAdded(groupSibling2)
- val groupEntry = GroupEntryBuilder()
- .setSummary(groupSummary)
- .setChildren(listOf(groupSibling1, groupSibling2))
- .build()
+ val groupEntry =
+ GroupEntryBuilder()
+ .setSummary(groupSummary)
+ .setChildren(listOf(groupSibling1, groupSibling2))
+ .build()
beforeTransformGroupsListener.onBeforeTransformGroups(listOf(groupEntry))
verify(headsUpViewBinder, never()).bindHeadsUpView(any(), any())
beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry))
@@ -708,16 +722,16 @@
@Test
fun testNoTransferTwoChildAlert_withGroupAlertAll() {
setShouldHeadsUp(groupSummary)
- whenever(notifPipeline.allNotifs)
- .thenReturn(listOf(groupSummary, groupChild1, groupChild2))
+ whenever(notifPipeline.allNotifs).thenReturn(listOf(groupSummary, groupChild1, groupChild2))
collectionListener.onEntryAdded(groupSummary)
collectionListener.onEntryAdded(groupChild1)
collectionListener.onEntryAdded(groupChild2)
- val groupEntry = GroupEntryBuilder()
- .setSummary(groupSummary)
- .setChildren(listOf(groupChild1, groupChild2))
- .build()
+ val groupEntry =
+ GroupEntryBuilder()
+ .setSummary(groupSummary)
+ .setChildren(listOf(groupChild1, groupChild2))
+ .build()
beforeTransformGroupsListener.onBeforeTransformGroups(listOf(groupEntry))
verify(headsUpViewBinder, never()).bindHeadsUpView(any(), any())
beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry))
@@ -742,10 +756,11 @@
collectionListener.onEntryAdded(groupSummary)
collectionListener.onEntryAdded(groupChild1)
collectionListener.onEntryAdded(groupChild2)
- val groupEntry = GroupEntryBuilder()
- .setSummary(groupSummary)
- .setChildren(listOf(groupChild1, groupChild2))
- .build()
+ val groupEntry =
+ GroupEntryBuilder()
+ .setSummary(groupSummary)
+ .setChildren(listOf(groupChild1, groupChild2))
+ .build()
beforeTransformGroupsListener.onBeforeTransformGroups(listOf(groupEntry))
verify(headsUpViewBinder, never()).bindHeadsUpView(any(), any())
beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry))
@@ -1045,9 +1060,7 @@
.thenReturn(DecisionImpl.of(should))
}
- private fun setDefaultShouldFullScreen(
- originalDecision: FullScreenIntentDecision
- ) {
+ private fun setDefaultShouldFullScreen(originalDecision: FullScreenIntentDecision) {
val provider = visualInterruptionDecisionProvider
whenever(provider.makeUnloggedFullScreenIntentDecision(any())).thenAnswer {
val entry: NotificationEntry = it.getArgument(0)
@@ -1059,11 +1072,8 @@
entry: NotificationEntry,
originalDecision: FullScreenIntentDecision
) {
- whenever(
- visualInterruptionDecisionProvider.makeUnloggedFullScreenIntentDecision(entry)
- ).thenAnswer {
- FullScreenIntentDecisionImpl(entry, originalDecision)
- }
+ whenever(visualInterruptionDecisionProvider.makeUnloggedFullScreenIntentDecision(entry))
+ .thenAnswer { FullScreenIntentDecisionImpl(entry, originalDecision) }
}
private fun verifyLoggedFullScreenIntentDecision(
@@ -1089,7 +1099,8 @@
private fun finishBind(entry: NotificationEntry) {
verify(headsUpManager, never()).showNotification(entry)
withArgCaptor<BindCallback> {
- verify(headsUpViewBinder).bindHeadsUpView(eq(entry), capture())
- }.onBindFinished(entry)
+ verify(headsUpViewBinder).bindHeadsUpView(eq(entry), capture())
+ }
+ .onBindFinished(entry)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
index 30e7247..70ac31d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
@@ -391,6 +391,7 @@
configurationController,
mStatusOverlayHoverListenerFactory,
fakeDarkIconDispatcher,
+ mock(StatusBarContentInsetsProvider::class.java),
)
.create(view)
.also { it.init() }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
index ed5ec7b2..648ddf8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
@@ -32,6 +32,7 @@
import android.view.WindowInsets
import android.widget.FrameLayout
import androidx.test.filters.SmallTest
+import com.android.systemui.Flags.FLAG_STATUS_BAR_STOP_UPDATING_WINDOW_HEIGHT
import com.android.systemui.Flags.FLAG_STATUS_BAR_SWIPE_OVER_CHIP
import com.android.systemui.Gefingerpoken
import com.android.systemui.SysuiTestCase
@@ -42,6 +43,7 @@
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
+import org.mockito.Mockito.never
import org.mockito.Mockito.spy
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
@@ -54,21 +56,14 @@
private val systemIconsContainer: View
get() = view.requireViewById(R.id.system_icons)
- private val contentInsetsProvider = mock<StatusBarContentInsetsProvider>()
private val windowController = mock<StatusBarWindowController>()
@Before
fun setUp() {
- mDependency.injectTestDependency(
- StatusBarContentInsetsProvider::class.java,
- contentInsetsProvider
- )
mDependency.injectTestDependency(StatusBarWindowController::class.java, windowController)
context.ensureTestableResources()
view = spy(createStatusBarView())
whenever(view.rootWindowInsets).thenReturn(emptyWindowInsets())
- whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
- .thenReturn(Insets.NONE)
}
@Test
@@ -183,21 +178,40 @@
}
@Test
- fun onAttachedToWindow_updatesWindowHeight() {
+ @DisableFlags(FLAG_STATUS_BAR_STOP_UPDATING_WINDOW_HEIGHT)
+ fun onAttachedToWindow_flagOff_updatesWindowHeight() {
view.onAttachedToWindow()
verify(windowController).refreshStatusBarHeight()
}
@Test
- fun onConfigurationChanged_updatesWindowHeight() {
+ @EnableFlags(FLAG_STATUS_BAR_STOP_UPDATING_WINDOW_HEIGHT)
+ fun onAttachedToWindow_flagOn_doesNotUpdateWindowHeight() {
+ view.onAttachedToWindow()
+
+ verify(windowController, never()).refreshStatusBarHeight()
+ }
+
+ @Test
+ @DisableFlags(FLAG_STATUS_BAR_STOP_UPDATING_WINDOW_HEIGHT)
+ fun onConfigurationChanged_flagOff_updatesWindowHeight() {
view.onConfigurationChanged(Configuration())
verify(windowController).refreshStatusBarHeight()
}
@Test
- fun onConfigurationChanged_multipleCalls_updatesWindowHeightMultipleTimes() {
+ @EnableFlags(FLAG_STATUS_BAR_STOP_UPDATING_WINDOW_HEIGHT)
+ fun onConfigurationChanged_flagOn_doesNotUpdateWindowHeight() {
+ view.onConfigurationChanged(Configuration())
+
+ verify(windowController, never()).refreshStatusBarHeight()
+ }
+
+ @Test
+ @DisableFlags(FLAG_STATUS_BAR_STOP_UPDATING_WINDOW_HEIGHT)
+ fun onConfigurationChanged_multipleCalls_flagOff_updatesWindowHeightMultipleTimes() {
view.onConfigurationChanged(Configuration())
view.onConfigurationChanged(Configuration())
view.onConfigurationChanged(Configuration())
@@ -207,10 +221,20 @@
}
@Test
+ @EnableFlags(FLAG_STATUS_BAR_STOP_UPDATING_WINDOW_HEIGHT)
+ fun onConfigurationChanged_multipleCalls_flagOn_neverUpdatesWindowHeight() {
+ view.onConfigurationChanged(Configuration())
+ view.onConfigurationChanged(Configuration())
+ view.onConfigurationChanged(Configuration())
+ view.onConfigurationChanged(Configuration())
+
+ verify(windowController, never()).refreshStatusBarHeight()
+ }
+
+ @Test
fun onAttachedToWindow_updatesLeftTopRightPaddingsBasedOnInsets() {
val insets = Insets.of(/* left= */ 10, /* top= */ 20, /* right= */ 30, /* bottom= */ 40)
- whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
- .thenReturn(insets)
+ view.setInsetsFetcher { insets }
view.onAttachedToWindow()
@@ -221,10 +245,23 @@
}
@Test
+ fun onAttachedToWindow_noInsetsFetcher_noCrash() {
+ // Don't call `PhoneStatusBarView.setInsetsFetcher`
+
+ // WHEN the view is attached
+ view.onAttachedToWindow()
+
+ // THEN there's no crash, and the padding stays as it was
+ assertThat(view.paddingLeft).isEqualTo(0)
+ assertThat(view.paddingTop).isEqualTo(0)
+ assertThat(view.paddingRight).isEqualTo(0)
+ assertThat(view.paddingBottom).isEqualTo(0)
+ }
+
+ @Test
fun onConfigurationChanged_updatesLeftTopRightPaddingsBasedOnInsets() {
val insets = Insets.of(/* left= */ 40, /* top= */ 30, /* right= */ 20, /* bottom= */ 10)
- whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
- .thenReturn(insets)
+ view.setInsetsFetcher { insets }
view.onConfigurationChanged(Configuration())
@@ -235,17 +272,31 @@
}
@Test
+ fun onConfigurationChanged_noInsetsFetcher_noCrash() {
+ // Don't call `PhoneStatusBarView.setInsetsFetcher`
+
+ // WHEN the view is attached
+ view.onConfigurationChanged(Configuration())
+
+ // THEN there's no crash, and the padding stays as it was
+ assertThat(view.paddingLeft).isEqualTo(0)
+ assertThat(view.paddingTop).isEqualTo(0)
+ assertThat(view.paddingRight).isEqualTo(0)
+ assertThat(view.paddingBottom).isEqualTo(0)
+ }
+
+ @Test
fun onConfigurationChanged_noRelevantChange_doesNotUpdateInsets() {
val previousInsets =
Insets.of(/* left= */ 40, /* top= */ 30, /* right= */ 20, /* bottom= */ 10)
- whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
- .thenReturn(previousInsets)
+ view.setInsetsFetcher { previousInsets }
+
context.orCreateTestableResources.overrideConfiguration(Configuration())
view.onAttachedToWindow()
val newInsets = Insets.NONE
- whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
- .thenReturn(newInsets)
+ view.setInsetsFetcher { newInsets }
+
view.onConfigurationChanged(Configuration())
assertThat(view.paddingLeft).isEqualTo(previousInsets.left)
@@ -258,16 +309,14 @@
fun onConfigurationChanged_densityChanged_updatesInsets() {
val previousInsets =
Insets.of(/* left= */ 40, /* top= */ 30, /* right= */ 20, /* bottom= */ 10)
- whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
- .thenReturn(previousInsets)
+ view.setInsetsFetcher { previousInsets }
val configuration = Configuration()
configuration.densityDpi = 123
context.orCreateTestableResources.overrideConfiguration(configuration)
view.onAttachedToWindow()
val newInsets = Insets.NONE
- whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
- .thenReturn(newInsets)
+ view.setInsetsFetcher { newInsets }
configuration.densityDpi = 456
view.onConfigurationChanged(configuration)
@@ -281,16 +330,14 @@
fun onConfigurationChanged_fontScaleChanged_updatesInsets() {
val previousInsets =
Insets.of(/* left= */ 40, /* top= */ 30, /* right= */ 20, /* bottom= */ 10)
- whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
- .thenReturn(previousInsets)
+ view.setInsetsFetcher { previousInsets }
val configuration = Configuration()
configuration.fontScale = 1f
context.orCreateTestableResources.overrideConfiguration(configuration)
view.onAttachedToWindow()
val newInsets = Insets.NONE
- whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
- .thenReturn(newInsets)
+ view.setInsetsFetcher { newInsets }
configuration.fontScale = 2f
view.onConfigurationChanged(configuration)
@@ -316,8 +363,7 @@
@Test
fun onApplyWindowInsets_updatesLeftTopRightPaddingsBasedOnInsets() {
val insets = Insets.of(/* left= */ 90, /* top= */ 10, /* right= */ 45, /* bottom= */ 50)
- whenever(contentInsetsProvider.getStatusBarContentInsetsForCurrentRotation())
- .thenReturn(insets)
+ view.setInsetsFetcher { insets }
view.onApplyWindowInsets(WindowInsets(Rect()))
@@ -358,7 +404,7 @@
/* typeVisibilityMap = */ booleanArrayOf(),
/* isRound = */ false,
/* forceConsumingTypes = */ 0,
- /* forceConsumingCaptionBar = */ false,
+ /* forceConsumingOpaqueCaptionBar = */ false,
/* suppressScrimTypes = */ 0,
/* displayCutout = */ DisplayCutout.NO_CUTOUT,
/* roundedCorners = */ RoundedCorners.NO_ROUNDED_CORNERS,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index 9fa392f..7a34e94 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -434,7 +434,11 @@
// Then
verify(mBubblesManager).onUserChangedBubble(entry, false);
- verify(mHeadsUpManager).removeNotification(entry.getKey(), true);
+ verify(mHeadsUpManager).removeNotification(
+ entry.getKey(),
+ /* releaseImmediately= */ true,
+ /* reason= */ "onNotificationBubbleIconClicked"
+ );
verifyNoMoreInteractions(mContentIntent);
verifyNoMoreInteractions(mShadeController);
@@ -456,7 +460,11 @@
// Then
verify(mBubblesManager).onUserChangedBubble(entry, true);
- verify(mHeadsUpManager).removeNotification(entry.getKey(), true);
+ verify(mHeadsUpManager).removeNotification(
+ entry.getKey(),
+ /* releaseImmediately= */ true,
+ /* reason= */ "onNotificationBubbleIconClicked"
+ );
verify(mContentIntent, atLeastOnce()).isActivity();
verifyNoMoreInteractions(mContentIntent);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateTest.kt
index bf0a39b..06b3b57 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateTest.kt
@@ -57,6 +57,7 @@
private val activityStarter = kosmos.activityStarter
private val mockDialogTransitionAnimator = kosmos.mockDialogTransitionAnimator
private val mockAnimationController = kosmos.mockActivityTransitionAnimatorController
+ private val mockDialogEventLogger = kosmos.mockModesDialogEventLogger
private lateinit var underTest: ModesDialogDelegate
@Before
@@ -75,6 +76,7 @@
mockDialogTransitionAnimator,
activityStarter,
{ kosmos.modesDialogViewModel },
+ mockDialogEventLogger,
kosmos.mainCoroutineContext,
)
}
@@ -121,4 +123,12 @@
assertThat(underTest.currentDialog).isNull()
}
+
+ @Test
+ fun openSettings_logsEvent() =
+ testScope.runTest {
+ val dialog: SystemUIDialog = mock()
+ underTest.openSettings(dialog)
+ verify(mockDialogEventLogger).logDialogSettings()
+ }
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorKosmos.kt
index ee48c10..2ab8221 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalSceneInteractorKosmos.kt
@@ -17,6 +17,7 @@
package com.android.systemui.communal.domain.interactor
import com.android.systemui.communal.data.repository.communalSceneRepository
+import com.android.systemui.communal.shared.log.communalSceneLogger
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.applicationCoroutineScope
@@ -24,6 +25,7 @@
Kosmos.Fixture {
CommunalSceneInteractor(
applicationScope = applicationCoroutineScope,
- communalSceneRepository = communalSceneRepository,
+ repository = communalSceneRepository,
+ logger = communalSceneLogger,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/shared/log/CommunalSceneLoggerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/shared/log/CommunalSceneLoggerKosmos.kt
new file mode 100644
index 0000000..b560ee8
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/shared/log/CommunalSceneLoggerKosmos.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2024 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.communal.shared.log
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.log.logcatLogBuffer
+
+val Kosmos.communalSceneLogger: CommunalSceneLogger by
+ Kosmos.Fixture { CommunalSceneLogger(logcatLogBuffer("CommunalSceneLogger")) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorKosmos.kt
index f162594..64ae051 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorKosmos.kt
@@ -16,6 +16,7 @@
package com.android.systemui.keyguard.domain.interactor
+import com.android.systemui.communal.domain.interactor.communalSceneInteractor
import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository
@@ -38,6 +39,7 @@
mainDispatcher = testDispatcher,
keyguardInteractor = keyguardInteractor,
glanceableHubTransitions = glanceableHubTransitions,
+ communalSceneInteractor = communalSceneInteractor,
communalSettingsInteractor = communalSettingsInteractor,
powerInteractor = powerInteractor,
keyguardOcclusionInteractor = keyguardOcclusionInteractor,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelKosmos.kt
index 450dcc2..d06bab2 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelKosmos.kt
@@ -19,13 +19,11 @@
import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
-import com.android.systemui.util.mockito.mock
import kotlinx.coroutines.ExperimentalCoroutinesApi
@ExperimentalCoroutinesApi
val Kosmos.dreamingToLockscreenTransitionViewModel by Fixture {
DreamingToLockscreenTransitionViewModel(
- fromDreamingTransitionInteractor = mock(),
animationFlow = keyguardTransitionAnimationFlow,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateKosmos.kt
index 99bb479..932e768 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogDelegateKosmos.kt
@@ -33,6 +33,7 @@
dialogTransitionAnimator,
activityStarter,
{ modesDialogViewModel },
+ modesDialogEventLogger,
mainCoroutineContext,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogEventLoggerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogEventLoggerKosmos.kt
new file mode 100644
index 0000000..24e7a87
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogEventLoggerKosmos.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2024 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.policy.ui.dialog
+
+import com.android.internal.logging.uiEventLogger
+import com.android.systemui.kosmos.Kosmos
+import org.mockito.kotlin.mock
+
+var Kosmos.modesDialogEventLogger by Kosmos.Fixture { ModesDialogEventLogger(uiEventLogger) }
+var Kosmos.mockModesDialogEventLogger by Kosmos.Fixture { mock<ModesDialogEventLogger>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogEventLoggerTest.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogEventLoggerTest.kt
new file mode 100644
index 0000000..5146f77
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/ModesDialogEventLoggerTest.kt
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2024 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.policy.ui.dialog
+
+import android.testing.TestableLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.testing.UiEventLoggerFake
+import com.android.settingslib.notification.modes.TestModeBuilder
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.qs.QSModesEvent
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@TestableLooper.RunWithLooper
+class ModesDialogEventLoggerTest : SysuiTestCase() {
+
+ private val uiEventLogger = UiEventLoggerFake()
+ private val underTest = ModesDialogEventLogger(uiEventLogger)
+
+ @Test
+ fun testLogModeOn_manual() {
+ underTest.logModeOn(TestModeBuilder.MANUAL_DND_INACTIVE)
+
+ assertThat(uiEventLogger.numLogs()).isEqualTo(1)
+ uiEventLogger[0].match(QSModesEvent.QS_MODES_DND_ON, "android")
+ }
+
+ @Test
+ fun testLogModeOff_manual() {
+ underTest.logModeOff(TestModeBuilder.MANUAL_DND_ACTIVE)
+
+ assertThat(uiEventLogger.numLogs()).isEqualTo(1)
+ uiEventLogger[0].match(QSModesEvent.QS_MODES_DND_OFF, "android")
+ }
+
+ @Test
+ fun testLogModeSettings_manual() {
+ underTest.logModeSettings(TestModeBuilder.MANUAL_DND_ACTIVE)
+
+ assertThat(uiEventLogger.numLogs()).isEqualTo(1)
+ uiEventLogger[0].match(QSModesEvent.QS_MODES_DND_SETTINGS, "android")
+ }
+
+ @Test
+ fun testLogModeOn_automatic() {
+ underTest.logModeOn(TestModeBuilder().setActive(true).setPackage("pkg1").build())
+
+ assertThat(uiEventLogger.numLogs()).isEqualTo(1)
+ uiEventLogger[0].match(QSModesEvent.QS_MODES_MODE_ON, "pkg1")
+ }
+
+ @Test
+ fun testLogModeOff_automatic() {
+ underTest.logModeOff(TestModeBuilder().setActive(false).setPackage("pkg2").build())
+
+ assertThat(uiEventLogger.numLogs()).isEqualTo(1)
+ uiEventLogger[0].match(QSModesEvent.QS_MODES_MODE_OFF, "pkg2")
+ }
+
+ @Test
+ fun testLogModeSettings_automatic() {
+ underTest.logModeSettings(TestModeBuilder().setPackage("pkg3").build())
+
+ assertThat(uiEventLogger.numLogs()).isEqualTo(1)
+ uiEventLogger[0].match(QSModesEvent.QS_MODES_MODE_SETTINGS, "pkg3")
+ }
+
+ @Test
+ fun testLogOpenDurationDialog_manual() {
+ underTest.logOpenDurationDialog(TestModeBuilder.MANUAL_DND_INACTIVE)
+
+ assertThat(uiEventLogger.numLogs()).isEqualTo(1)
+ // package not logged for duration dialog as it only applies to manual mode
+ uiEventLogger[0].match(QSModesEvent.QS_MODES_DURATION_DIALOG, null)
+ }
+
+ @Test
+ fun testLogOpenDurationDialog_automatic_doesNotLog() {
+ underTest.logOpenDurationDialog(
+ TestModeBuilder().setActive(false).setPackage("mypkg").build()
+ )
+
+ // ignore calls to open dialog on something other than the manual rule (shouldn't happen)
+ assertThat(uiEventLogger.numLogs()).isEqualTo(0)
+ }
+
+ @Test
+ fun testLogDialogSettings() {
+ underTest.logDialogSettings()
+ assertThat(uiEventLogger.numLogs()).isEqualTo(1)
+ uiEventLogger[0].match(QSModesEvent.QS_MODES_SETTINGS, null)
+ }
+
+ private fun UiEventLoggerFake.FakeUiEvent.match(event: QSModesEvent, modePackage: String?) {
+ assertThat(eventId).isEqualTo(event.id)
+ assertThat(packageName).isEqualTo(modePackage)
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelKosmos.kt
index 00020f8..3571a73 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelKosmos.kt
@@ -21,6 +21,7 @@
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.statusbar.policy.domain.interactor.zenModeInteractor
import com.android.systemui.statusbar.policy.ui.dialog.modesDialogDelegate
+import com.android.systemui.statusbar.policy.ui.dialog.modesDialogEventLogger
import javax.inject.Provider
val Kosmos.modesDialogViewModel: ModesDialogViewModel by
@@ -30,5 +31,6 @@
zenModeInteractor,
testDispatcher,
Provider { modesDialogDelegate }.get(),
+ modesDialogEventLogger,
)
}
diff --git a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
index 2c4bc7c..531fa45 100644
--- a/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
+++ b/packages/services/CameraExtensionsProxy/src/com/android/cameraextensions/CameraExtensionsProxyService.java
@@ -78,8 +78,8 @@
import android.util.Size;
import android.view.Surface;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import androidx.camera.extensions.impl.AutoImageCaptureExtenderImpl;
import androidx.camera.extensions.impl.AutoPreviewExtenderImpl;
import androidx.camera.extensions.impl.BeautyImageCaptureExtenderImpl;
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
index b052d23..5c6f99a 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
@@ -16,8 +16,6 @@
package com.android.server.accessibility.magnification;
-import static android.view.InputDevice.SOURCE_MOUSE;
-import static android.view.InputDevice.SOURCE_STYLUS;
import static android.view.InputDevice.SOURCE_TOUCHSCREEN;
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
@@ -342,8 +340,12 @@
cancelFling();
}
handleTouchEventWith(mCurrentState, event, rawEvent, policyFlags);
- } else if (Flags.enableMagnificationFollowsMouse()
- && (event.getSource() == SOURCE_MOUSE || event.getSource() == SOURCE_STYLUS)) {
+ }
+ }
+
+ @Override
+ void handleMouseOrStylusEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ if (Flags.enableMagnificationFollowsMouse()) {
if (mFullScreenMagnificationController.isActivated(mDisplayId)) {
// TODO(b/354696546): Allow mouse/stylus to activate whichever display they are
// over, rather than only interacting with the current display.
@@ -351,8 +353,6 @@
// Send through the mouse/stylus event handler.
mMouseEventHandler.onEvent(event, mDisplayId);
}
- // Dispatch to normal event handling flow.
- dispatchTransformedEvent(event, rawEvent, policyFlags);
}
}
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGestureHandler.java
index 08411c2..446123f 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationGestureHandler.java
@@ -127,49 +127,41 @@
if (DEBUG_EVENT_STREAM) {
storeEventInto(mDebugInputEventHistory, event);
}
- if (shouldDispatchTransformedEvent(event)) {
- dispatchTransformedEvent(event, rawEvent, policyFlags);
- } else {
- onMotionEventInternal(event, rawEvent, policyFlags);
+ switch (event.getSource()) {
+ case SOURCE_TOUCHSCREEN: {
+ if (magnificationShortcutExists()) {
+ // Observe touchscreen events while magnification activation is detected.
+ onMotionEventInternal(event, rawEvent, policyFlags);
- final int action = event.getAction();
- if (action == MotionEvent.ACTION_DOWN) {
- mCallback.onTouchInteractionStart(mDisplayId, getMode());
- } else if (action == ACTION_UP || action == ACTION_CANCEL) {
- mCallback.onTouchInteractionEnd(mDisplayId, getMode());
+ final int action = event.getAction();
+ if (action == MotionEvent.ACTION_DOWN) {
+ mCallback.onTouchInteractionStart(mDisplayId, getMode());
+ } else if (action == ACTION_UP || action == ACTION_CANCEL) {
+ mCallback.onTouchInteractionEnd(mDisplayId, getMode());
+ }
+ // Return early: Do not dispatch event through normal eventing
+ // flow, it has been fully consumed by the magnifier.
+ return;
+ }
+ } break;
+ case SOURCE_MOUSE:
+ case SOURCE_STYLUS: {
+ if (magnificationShortcutExists() && Flags.enableMagnificationFollowsMouse()) {
+ handleMouseOrStylusEvent(event, rawEvent, policyFlags);
+ }
}
+ break;
+ default:
+ break;
}
+ // Dispatch event through normal eventing flow.
+ dispatchTransformedEvent(event, rawEvent, policyFlags);
}
- /**
- * Some touchscreen, mouse and stylus events may modify magnifier state. Checks for whether the
- * event should not be dispatched to the magnifier.
- *
- * @param event The event to check.
- * @return `true` if the event should be sent through the normal event flow or `false` if it
- * should be observed by magnifier.
- */
- private boolean shouldDispatchTransformedEvent(MotionEvent event) {
- if (event.getSource() == SOURCE_TOUCHSCREEN) {
- if (mDetectSingleFingerTripleTap
- || mDetectTwoFingerTripleTap
- || mDetectShortcutTrigger) {
- // Observe touchscreen events while magnification activation is detected.
- return false;
- }
- }
- if (Flags.enableMagnificationFollowsMouse()) {
- if (event.isFromSource(SOURCE_MOUSE) || event.isFromSource(SOURCE_STYLUS)) {
- // Note that mouse events include other mouse-like pointing devices
- // such as touchpads and pointing sticks.
- // Observe any mouse or stylus movement.
- // We observe all movement to ensure that events continue to come in order,
- // even though only some movement types actually move the viewport.
- return false;
- }
- }
- // Magnification dispatches (ignores) all other events
- return true;
+ private boolean magnificationShortcutExists() {
+ return (mDetectSingleFingerTripleTap
+ || mDetectTwoFingerTripleTap
+ || mDetectShortcutTrigger);
}
final void dispatchTransformedEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
@@ -202,6 +194,13 @@
abstract void onMotionEventInternal(MotionEvent event, MotionEvent rawEvent, int policyFlags);
/**
+ * Called when this MagnificationGestureHandler should handle a mouse or stylus motion event,
+ * but not re-dispatch it when completed.
+ */
+ abstract void handleMouseOrStylusEvent(
+ MotionEvent event, MotionEvent rawEvent, int policyFlags);
+
+ /**
* Called when the shortcut target is magnification.
*/
public void notifyShortcutTriggered() {
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
index 1818cdd..a841404 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
@@ -147,9 +147,13 @@
}
@Override
+ void handleMouseOrStylusEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ // Window Magnification viewport doesn't move with mouse events (yet).
+ }
+
+ @Override
void onMotionEventInternal(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
if (event.getSource() != SOURCE_TOUCHSCREEN) {
- // Window Magnification viewport doesn't move with mouse events (yet).
return;
}
// To keep InputEventConsistencyVerifiers within GestureDetectors happy.
diff --git a/services/core/java/com/android/server/notification/NotificationChannelExtractor.java b/services/core/java/com/android/server/notification/NotificationChannelExtractor.java
index 1938642..e2889fa 100644
--- a/services/core/java/com/android/server/notification/NotificationChannelExtractor.java
+++ b/services/core/java/com/android/server/notification/NotificationChannelExtractor.java
@@ -29,8 +29,8 @@
import android.media.AudioAttributes;
import android.os.Binder;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.util.Slog;
+
import com.android.internal.compat.IPlatformCompat;
/**
@@ -79,6 +79,11 @@
if (restrictAudioAttributesCall() || restrictAudioAttributesAlarm()
|| restrictAudioAttributesMedia()) {
AudioAttributes attributes = record.getChannel().getAudioAttributes();
+ if (attributes == null) {
+ if (DBG) Slog.d(TAG, "missing AudioAttributes");
+ return null;
+ }
+
boolean updateAttributes = false;
if (restrictAudioAttributesCall()
&& !record.getNotification().isStyle(Notification.CallStyle.class)
diff --git a/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java b/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java
index eccbffb..0761087 100644
--- a/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java
+++ b/services/core/java/com/android/server/vibrator/HapticFeedbackVibrationProvider.java
@@ -364,10 +364,7 @@
if ((privFlags & HapticFeedbackConstants.PRIVATE_FLAG_APPLY_INPUT_METHOD_SETTINGS) == 0) {
return TOUCH_VIBRATION_ATTRIBUTES;
}
- return new VibrationAttributes.Builder(IME_FEEDBACK_VIBRATION_ATTRIBUTES)
- // TODO(b/332661766): Remove CATEGORY_KEYBOARD logic
- .setCategory(VibrationAttributes.CATEGORY_KEYBOARD)
- .build();
+ return IME_FEEDBACK_VIBRATION_ATTRIBUTES;
}
@Nullable
diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java
index 5c567da..aa4b9f3 100644
--- a/services/core/java/com/android/server/vibrator/Vibration.java
+++ b/services/core/java/com/android/server/vibrator/Vibration.java
@@ -282,12 +282,6 @@
VibrationScaler.scaleLevelToString(mScaleLevel), mAdaptiveScale,
Long.toBinaryString(mCallerInfo.attrs.getFlags()),
mCallerInfo.attrs.usageToString());
- // Optional, most vibrations have category unknown so skip them to simplify the logs
- String categoryStr =
- mCallerInfo.attrs.getCategory() != VibrationAttributes.CATEGORY_UNKNOWN
- ? " | category=" + VibrationAttributes.categoryToString(
- mCallerInfo.attrs.getCategory())
- : "";
// Optional, most vibrations should not be defined via AudioAttributes
// so skip them to simplify the logs
String audioUsageStr =
@@ -302,7 +296,7 @@
" | played: %s | original: %s",
mPlayedEffect == null ? null : mPlayedEffect.toDebugString(),
mOriginalEffect == null ? null : mOriginalEffect.toDebugString());
- pw.println(timingsStr + paramStr + categoryStr + audioUsageStr + callerStr + effectStr);
+ pw.println(timingsStr + paramStr + audioUsageStr + callerStr + effectStr);
}
/** Write this info into given {@link PrintWriter}. */
@@ -335,7 +329,6 @@
final VibrationAttributes attrs = mCallerInfo.attrs;
proto.write(VibrationAttributesProto.USAGE, attrs.getUsage());
proto.write(VibrationAttributesProto.AUDIO_USAGE, attrs.getAudioUsage());
- proto.write(VibrationAttributesProto.CATEGORY, attrs.getCategory());
proto.write(VibrationAttributesProto.FLAGS, attrs.getFlags());
proto.end(attrsToken);
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 329d11b..3a40943 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -1780,11 +1780,6 @@
if (resuming != null) {
// We do not want to trigger auto-PiP upon launch of a translucent activity.
final boolean resumingOccludesParent = resuming.occludesParent();
- // Resuming the new resume activity only if the previous activity can't go into Pip
- // since we want to give Pip activities a chance to enter Pip before resuming the
- // next activity.
- final boolean lastResumedCanPip = prev.checkEnterPictureInPictureState(
- "shouldAutoPipWhilePausing", userLeaving);
if (ActivityTaskManagerService.isPip2ExperimentEnabled()) {
// If a new task is being launched, then mark the existing top activity as
@@ -1794,6 +1789,12 @@
Task.enableEnterPipOnTaskSwitch(prev, resuming.getTask(),
resuming, resuming.getOptions());
}
+
+ // Resuming the new resume activity only if the previous activity can't go into Pip
+ // since we want to give Pip activities a chance to enter Pip before resuming the
+ // next activity.
+ final boolean lastResumedCanPip = prev.checkEnterPictureInPictureState(
+ "shouldAutoPipWhilePausing", userLeaving);
if (prev.supportsEnterPipOnTaskSwitch && userLeaving
&& resumingOccludesParent && lastResumedCanPip
&& prev.pictureInPictureArgs.isAutoEnterEnabled()) {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationGestureHandlerTest.java
index 3931580..d80a1f0 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationGestureHandlerTest.java
@@ -18,13 +18,20 @@
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_HOVER_MOVE;
import static android.view.MotionEvent.ACTION_UP;
+import static junit.framework.Assert.assertFalse;
+
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.testng.AssertJUnit.assertTrue;
import android.annotation.NonNull;
+import android.platform.test.annotations.RequiresFlagsDisabled;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.provider.Settings;
import android.view.InputDevice;
import android.view.MotionEvent;
@@ -32,8 +39,10 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.server.accessibility.AccessibilityTraceManager;
+import com.android.server.accessibility.Flags;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -45,6 +54,9 @@
@RunWith(AndroidJUnit4.class)
public class MagnificationGestureHandlerTest {
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
private TestMagnificationGestureHandler mMgh;
private static final int DISPLAY_0 = 0;
private static final int FULLSCREEN_MODE =
@@ -81,6 +93,66 @@
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE)
+ public void onMotionEvent_isFromMouse_handleMouseOrStylusEvent() {
+ final MotionEvent mouseEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, 0, 0, 0);
+ mouseEvent.setSource(InputDevice.SOURCE_MOUSE);
+
+ mMgh.onMotionEvent(mouseEvent, mouseEvent, /* policyFlags= */ 0);
+
+ try {
+ assertTrue(mMgh.mIsHandleMouseOrStylusEventCalled);
+ } finally {
+ mouseEvent.recycle();
+ }
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE)
+ public void onMotionEvent_isFromStylus_handleMouseOrStylusEvent() {
+ final MotionEvent stylusEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, 0, 0, 0);
+ stylusEvent.setSource(InputDevice.SOURCE_STYLUS);
+
+ mMgh.onMotionEvent(stylusEvent, stylusEvent, /* policyFlags= */ 0);
+
+ try {
+ assertTrue(mMgh.mIsHandleMouseOrStylusEventCalled);
+ } finally {
+ stylusEvent.recycle();
+ }
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE)
+ public void onMotionEvent_isFromMouse_handleMouseOrStylusEventNotCalled() {
+ final MotionEvent mouseEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, 0, 0, 0);
+ mouseEvent.setSource(InputDevice.SOURCE_MOUSE);
+
+ mMgh.onMotionEvent(mouseEvent, mouseEvent, /* policyFlags= */ 0);
+
+ try {
+ assertFalse(mMgh.mIsHandleMouseOrStylusEventCalled);
+ } finally {
+ mouseEvent.recycle();
+ }
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_ENABLE_MAGNIFICATION_FOLLOWS_MOUSE)
+ public void onMotionEvent_isFromStylus_handleMouseOrStylusEventNotCalled() {
+ final MotionEvent stylusEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, 0, 0, 0);
+ stylusEvent.setSource(InputDevice.SOURCE_STYLUS);
+
+ mMgh.onMotionEvent(stylusEvent, stylusEvent, /* policyFlags= */ 0);
+
+ try {
+ assertFalse(mMgh.mIsHandleMouseOrStylusEventCalled);
+ } finally {
+ stylusEvent.recycle();
+ }
+ }
+
+ @Test
public void onMotionEvent_downEvent_handleInteractionStart() {
final MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0);
downEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
@@ -125,6 +197,7 @@
private static class TestMagnificationGestureHandler extends MagnificationGestureHandler {
boolean mIsInternalMethodCalled = false;
+ boolean mIsHandleMouseOrStylusEventCalled = false;
TestMagnificationGestureHandler(int displayId, boolean detectSingleFingerTripleTap,
boolean detectTwoFingerTripleTap,
@@ -135,6 +208,11 @@
}
@Override
+ void handleMouseOrStylusEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ mIsHandleMouseOrStylusEventCalled = true;
+ }
+
+ @Override
void onMotionEventInternal(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
mIsInternalMethodCalled = true;
}
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java b/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java
index 240bd1e..8797e63 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/HapticFeedbackVibrationProviderTest.java
@@ -16,8 +16,6 @@
package com.android.server.vibrator;
-import static android.os.VibrationAttributes.CATEGORY_KEYBOARD;
-import static android.os.VibrationAttributes.CATEGORY_UNKNOWN;
import static android.os.VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY;
import static android.os.VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF;
import static android.os.VibrationAttributes.USAGE_IME_FEEDBACK;
@@ -255,7 +253,7 @@
}
@Test
- public void testKeyboardHaptic_fixAmplitude_keyboardCategoryOn_keyboardVibrationReturned() {
+ public void testKeyboardHaptic_fixAmplitude_keyboardVibrationReturned() {
mockVibratorPrimitiveSupport(PRIMITIVE_CLICK, PRIMITIVE_TICK);
mockKeyboardVibrationFixedAmplitude(KEYBOARD_VIBRATION_FIXED_AMPLITUDE);
@@ -330,7 +328,7 @@
}
@Test
- public void testVibrationAttribute_keyboardCategoryOn_notIme_useTouchUsage() {
+ public void testVibrationAttribute_notIme_useTouchUsage() {
HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations();
for (int effectId : KEYBOARD_FEEDBACK_CONSTANTS) {
@@ -338,13 +336,11 @@
effectId, /* flags */ 0, /* privFlags */ 0);
assertWithMessage("Expected USAGE_TOUCH for effect " + effectId)
.that(attrs.getUsage()).isEqualTo(USAGE_TOUCH);
- assertWithMessage("Expected CATEGORY_KEYBOARD for effect " + effectId)
- .that(attrs.getCategory()).isEqualTo(CATEGORY_UNKNOWN);
}
}
@Test
- public void testVibrationAttribute_keyboardCategoryOn_isIme_useImeFeedbackUsage() {
+ public void testVibrationAttribute_isIme_useImeFeedbackUsage() {
HapticFeedbackVibrationProvider hapticProvider = createProviderWithDefaultCustomizations();
for (int effectId : KEYBOARD_FEEDBACK_CONSTANTS) {
@@ -353,8 +349,6 @@
HapticFeedbackConstants.PRIVATE_FLAG_APPLY_INPUT_METHOD_SETTINGS);
assertWithMessage("Expected USAGE_IME_FEEDBACK for effect " + effectId)
.that(attrs.getUsage()).isEqualTo(USAGE_IME_FEEDBACK);
- assertWithMessage("Expected CATEGORY_KEYBOARD for effect " + effectId)
- .that(attrs.getCategory()).isEqualTo(CATEGORY_KEYBOARD);
}
}
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibrationSettingsTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibrationSettingsTest.java
index 6f06050..38cd49d 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibrationSettingsTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibrationSettingsTest.java
@@ -610,7 +610,6 @@
assertVibrationIgnoredForAttributes(
new VibrationAttributes.Builder()
.setUsage(USAGE_IME_FEEDBACK)
- .setCategory(VibrationAttributes.CATEGORY_KEYBOARD)
.build(),
Vibration.Status.IGNORED_FOR_SETTINGS);
@@ -619,7 +618,6 @@
assertVibrationNotIgnoredForAttributes(
new VibrationAttributes.Builder()
.setUsage(USAGE_IME_FEEDBACK)
- .setCategory(VibrationAttributes.CATEGORY_KEYBOARD)
.setFlags(VibrationAttributes.FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF)
.build());
}
@@ -637,7 +635,6 @@
assertVibrationNotIgnoredForAttributes(
new VibrationAttributes.Builder()
.setUsage(USAGE_IME_FEEDBACK)
- .setCategory(VibrationAttributes.CATEGORY_KEYBOARD)
.build());
}
@@ -654,7 +651,6 @@
assertVibrationIgnoredForAttributes(
new VibrationAttributes.Builder()
.setUsage(USAGE_IME_FEEDBACK)
- .setCategory(VibrationAttributes.CATEGORY_KEYBOARD)
.build(),
Vibration.Status.IGNORED_FOR_SETTINGS);
}
diff --git a/tests/Internal/AndroidTest.xml b/tests/Internal/AndroidTest.xml
index 7b67e9e..2d6c650e 100644
--- a/tests/Internal/AndroidTest.xml
+++ b/tests/Internal/AndroidTest.xml
@@ -26,4 +26,12 @@
<option name="package" value="com.android.internal.tests" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
</test>
+
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="pull-pattern-keys" value="perfetto_file_path"/>
+ <option name="directory-keys"
+ value="/data/user/0/com.android.internal.tests/files"/>
+ <option name="collect-on-run-ended-only" value="true"/>
+ <option name="clean-up" value="true"/>
+ </metrics_collector>
</configuration>
\ No newline at end of file
diff --git a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java b/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
index ecaab12..4b745b2 100644
--- a/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
+++ b/tests/Internal/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
@@ -29,7 +29,6 @@
import static org.mockito.Mockito.when;
import static java.io.File.createTempFile;
-import static java.nio.file.Files.createTempDirectory;
import android.content.Context;
import android.os.SystemClock;
@@ -45,6 +44,7 @@
import android.util.proto.ProtoInputStream;
import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
import com.android.internal.protolog.common.IProtoLogGroup;
import com.android.internal.protolog.common.LogDataType;
@@ -77,7 +77,8 @@
@Presubmit
@RunWith(JUnit4.class)
public class PerfettoProtoLogImplTest {
- private final File mTracingDirectory = createTempDirectory("temp").toFile();
+ private final File mTracingDirectory = InstrumentationRegistry.getInstrumentation()
+ .getTargetContext().getFilesDir();
private final ResultWriter mWriter = new ResultWriter()
.forScenario(new ScenarioBuilder()
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
index 36bfbef..c510eee 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
@@ -334,13 +334,14 @@
entry: ZipEntry,
out: ZipOutputStream,
) {
- BufferedInputStream(inZip.getInputStream(entry)).use { bis ->
+ // TODO: It seems like copying entries this way is _very_ slow,
+ // even with out.setLevel(0). Look for other ways to do it.
+
+ inZip.getInputStream(entry).use { ins ->
// Copy unknown entries as is to the impl out. (but not to the stub out.)
val outEntry = ZipEntry(entry.name)
out.putNextEntry(outEntry)
- while (bis.available() > 0) {
- out.write(bis.read())
- }
+ ins.transferTo(out)
out.closeEntry()
}
}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt
index ee4a06f..fcdf824 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt
@@ -121,7 +121,7 @@
return level.ordinal <= maxLogLevel.ordinal
}
- private fun println(level: LogLevel, message: String) {
+ fun println(level: LogLevel, message: String) {
printers.forEach {
if (it.logLevel.ordinal >= level.ordinal) {
it.println(level, indent, message)
@@ -129,7 +129,7 @@
}
}
- private fun println(level: LogLevel, format: String, vararg args: Any?) {
+ fun println(level: LogLevel, format: String, vararg args: Any?) {
if (isEnabled(level)) {
println(level, String.format(format, *args))
}
@@ -185,14 +185,29 @@
println(LogLevel.Debug, format, *args)
}
- inline fun <T> iTime(message: String, block: () -> T): T {
+ inline fun <T> logTime(level: LogLevel, message: String, block: () -> T): T {
val start = System.currentTimeMillis()
- val ret = block()
- val end = System.currentTimeMillis()
+ try {
+ return block()
+ } finally {
+ val end = System.currentTimeMillis()
+ if (isEnabled(level)) {
+ println(level,
+ String.format("%s: took %.1f second(s).", message, (end - start) / 1000.0))
+ }
+ }
+ }
- log.i("%s: took %.1f second(s).", message, (end - start) / 1000.0)
+ inline fun <T> iTime(message: String, block: () -> T): T {
+ return logTime(LogLevel.Info, message, block)
+ }
- return ret
+ inline fun <T> vTime(message: String, block: () -> T): T {
+ return logTime(LogLevel.Verbose, message, block)
+ }
+
+ inline fun <T> dTime(message: String, block: () -> T): T {
+ return logTime(LogLevel.Debug, message, block)
}
inline fun forVerbose(block: () -> Unit) {
diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
index aa53005..2285880 100644
--- a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
@@ -26,7 +26,6 @@
import com.github.javaparser.ast.Modifier
import com.github.javaparser.ast.NodeList
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration
-import com.github.javaparser.ast.body.InitializerDeclaration
import com.github.javaparser.ast.expr.ArrayAccessExpr
import com.github.javaparser.ast.expr.ArrayCreationExpr
import com.github.javaparser.ast.expr.ArrayInitializerExpr
@@ -42,7 +41,10 @@
import com.github.javaparser.ast.expr.ObjectCreationExpr
import com.github.javaparser.ast.expr.SimpleName
import com.github.javaparser.ast.expr.StringLiteralExpr
+import com.github.javaparser.ast.expr.VariableDeclarationExpr
import com.github.javaparser.ast.stmt.BlockStmt
+import com.github.javaparser.ast.stmt.ReturnStmt
+import com.github.javaparser.ast.type.ClassOrInterfaceType
import java.io.File
import java.io.FileInputStream
import java.io.FileNotFoundException
@@ -195,6 +197,7 @@
groups: Map<String, LogGroup>,
protoLogGroupsClassName: String
) {
+ var needsCreateLogGroupsMap = false
classDeclaration.fields.forEach { field ->
field.getAnnotationByClass(ProtoLogToolInjected::class.java)
.ifPresent { annotationExpr ->
@@ -222,33 +225,10 @@
} ?: NullLiteralExpr())
}
ProtoLogToolInjected.Value.LOG_GROUPS.name -> {
- val initializerBlockStmt = BlockStmt()
- for (group in groups) {
- initializerBlockStmt.addStatement(
- MethodCallExpr()
- .setName("put")
- .setArguments(
- NodeList(StringLiteralExpr(group.key),
- FieldAccessExpr()
- .setScope(
- NameExpr(
- protoLogGroupsClassName
- ))
- .setName(group.value.name)))
- )
- group.key
- }
-
- val treeMapCreation = ObjectCreationExpr()
- .setType("TreeMap<String, IProtoLogGroup>")
- .setAnonymousClassBody(NodeList(
- InitializerDeclaration().setBody(
- initializerBlockStmt
- )
- ))
-
+ needsCreateLogGroupsMap = true
field.setFinal(true)
- field.variables.first().setInitializer(treeMapCreation)
+ field.variables.first().setInitializer(
+ MethodCallExpr().setName("createLogGroupsMap"))
}
ProtoLogToolInjected.Value.CACHE_UPDATER.name -> {
field.setFinal(true)
@@ -261,6 +241,45 @@
}
}
}
+
+ if (needsCreateLogGroupsMap) {
+ val body = BlockStmt()
+ body.addStatement(AssignExpr(
+ VariableDeclarationExpr(
+ ClassOrInterfaceType("TreeMap<String, IProtoLogGroup>"),
+ "result"
+ ),
+ ObjectCreationExpr().setType("TreeMap<String, IProtoLogGroup>"),
+ AssignExpr.Operator.ASSIGN
+ ))
+ for (group in groups) {
+ body.addStatement(
+ MethodCallExpr(
+ NameExpr("result"),
+ "put",
+ NodeList(
+ StringLiteralExpr(group.key),
+ FieldAccessExpr()
+ .setScope(
+ NameExpr(
+ protoLogGroupsClassName
+ ))
+ .setName(group.value.name)
+ )
+ )
+ )
+ }
+ body.addStatement(ReturnStmt(NameExpr("result")))
+
+ val method = classDeclaration.addMethod(
+ "createLogGroupsMap",
+ Modifier.Keyword.PRIVATE,
+ Modifier.Keyword.STATIC,
+ Modifier.Keyword.FINAL
+ )
+ method.setType("TreeMap<String, IProtoLogGroup>")
+ method.setBody(body)
+ }
}
private fun injectCacheClass(