Merge "Run protolog perf tests in postsubmit" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index b4127c5..3c5686b 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -26,6 +26,7 @@
"android.app.flags-aconfig-java",
"android.app.ondeviceintelligence-aconfig-java",
"android.app.smartspace.flags-aconfig-java",
+ "android.app.supervision.flags-aconfig-java",
"android.app.usage.flags-aconfig-java",
"android.app.wearable.flags-aconfig-java",
"android.appwidget.flags-aconfig-java",
@@ -1212,6 +1213,21 @@
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+// Supervision
+aconfig_declarations {
+ name: "android.app.supervision.flags-aconfig",
+ exportable: true,
+ package: "android.app.supervision.flags",
+ container: "system",
+ srcs: ["core/java/android/app/supervision/flags.aconfig"],
+}
+
+java_aconfig_library {
+ name: "android.app.supervision.flags-aconfig-java",
+ aconfig_declarations: "android.app.supervision.flags-aconfig",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
// SurfaceFlinger
java_aconfig_library {
name: "surfaceflinger_flags_java_lib",
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index e1e63cc..5413c66 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -3694,9 +3694,11 @@
method public int getMinDelay();
method @NonNull public String getName();
method public float getPower();
+ method @FlaggedApi("android.companion.virtualdevice.flags.device_aware_display_power") public int getReportingMode();
method public float getResolution();
method public int getType();
method @Nullable public String getVendor();
+ method @FlaggedApi("android.companion.virtualdevice.flags.device_aware_display_power") public boolean isWakeUpSensor();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.companion.virtual.sensor.VirtualSensorConfig> CREATOR;
}
@@ -3710,8 +3712,10 @@
method @NonNull public android.companion.virtual.sensor.VirtualSensorConfig.Builder setMaximumRange(float);
method @NonNull public android.companion.virtual.sensor.VirtualSensorConfig.Builder setMinDelay(int);
method @NonNull public android.companion.virtual.sensor.VirtualSensorConfig.Builder setPower(float);
+ method @FlaggedApi("android.companion.virtualdevice.flags.device_aware_display_power") @NonNull public android.companion.virtual.sensor.VirtualSensorConfig.Builder setReportingMode(int);
method @NonNull public android.companion.virtual.sensor.VirtualSensorConfig.Builder setResolution(float);
method @NonNull public android.companion.virtual.sensor.VirtualSensorConfig.Builder setVendor(@Nullable String);
+ method @FlaggedApi("android.companion.virtualdevice.flags.device_aware_display_power") @NonNull public android.companion.virtual.sensor.VirtualSensorConfig.Builder setWakeUpSensor(boolean);
}
public interface VirtualSensorDirectChannelCallback {
@@ -8083,6 +8087,7 @@
public class Tuner implements java.lang.AutoCloseable {
ctor @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public Tuner(@NonNull android.content.Context, @Nullable String, int);
method public int applyFrontend(@NonNull android.media.tv.tuner.frontend.FrontendInfo);
+ method @FlaggedApi("android.media.tv.flags.tuner_w_apis") @RequiresPermission(allOf={"android.permission.TUNER_RESOURCE_ACCESS", "android.permission.ACCESS_TV_TUNER"}) public int applyFrontendByType(int);
method public int cancelScanning();
method public int cancelTuning();
method public void clearOnTuneEventListener();
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index cb38cf2..8b3ee24 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -48,6 +48,8 @@
import android.app.search.SearchUiManager;
import android.app.slice.SliceManager;
import android.app.smartspace.SmartspaceManager;
+import android.app.supervision.ISupervisionManager;
+import android.app.supervision.SupervisionManager;
import android.app.time.TimeManager;
import android.app.timedetector.TimeDetector;
import android.app.timedetector.TimeDetectorImpl;
@@ -1703,6 +1705,21 @@
return new E2eeContactKeysManager(ctx);
}});
+ registerService(Context.SUPERVISION_SERVICE, SupervisionManager.class,
+ new CachedServiceFetcher<>() {
+ @Override
+ public SupervisionManager createService(ContextImpl ctx)
+ throws ServiceNotFoundException {
+ if (!android.app.supervision.flags.Flags.supervisionApi()) {
+ throw new ServiceNotFoundException(
+ "SupervisionManager is not supported");
+ }
+ IBinder iBinder = ServiceManager.getServiceOrThrow(
+ Context.SUPERVISION_SERVICE);
+ ISupervisionManager service = ISupervisionManager.Stub.asInterface(iBinder);
+ return new SupervisionManager(ctx, service);
+ }
+ });
// DO NOT do a flag check like this unless the flag is read-only.
// (because this code is executed during preload in zygote.)
// If the flag is mutable, the check should be inside CachedServiceFetcher.
diff --git a/core/java/android/app/supervision/ISupervisionManager.aidl b/core/java/android/app/supervision/ISupervisionManager.aidl
new file mode 100644
index 0000000..8d25cad
--- /dev/null
+++ b/core/java/android/app/supervision/ISupervisionManager.aidl
@@ -0,0 +1,25 @@
+/**
+ * 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 android.app.supervision;
+
+/**
+ * Internal IPC interface to the supervision service.
+ * {@hide}
+ */
+interface ISupervisionManager {
+ boolean isSupervisionEnabled();
+}
diff --git a/core/java/android/app/supervision/SupervisionManager.java b/core/java/android/app/supervision/SupervisionManager.java
new file mode 100644
index 0000000..8611a92
--- /dev/null
+++ b/core/java/android/app/supervision/SupervisionManager.java
@@ -0,0 +1,57 @@
+/*
+ * 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 android.app.supervision;
+
+import android.annotation.SystemService;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.content.Context;
+import android.os.RemoteException;
+
+/**
+ * Service for handling parental supervision.
+ *
+ * @hide
+ */
+@SystemService(Context.SUPERVISION_SERVICE)
+public class SupervisionManager {
+ private final Context mContext;
+ private final ISupervisionManager mService;
+
+ /**
+ * @hide
+ */
+ @UnsupportedAppUsage
+ public SupervisionManager(Context context, ISupervisionManager service) {
+ mContext = context;
+ mService = service;
+ }
+
+ /**
+ * Returns whether the device is supervised.
+ *
+ * @hide
+ */
+ public boolean isSupervisionEnabled() {
+ try {
+ return mService.isSupervisionEnabled();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+
+}
diff --git a/core/java/android/app/supervision/flags.aconfig b/core/java/android/app/supervision/flags.aconfig
new file mode 100644
index 0000000..bcb5b36
--- /dev/null
+++ b/core/java/android/app/supervision/flags.aconfig
@@ -0,0 +1,10 @@
+package: "android.app.supervision.flags"
+container: "system"
+
+flag {
+ name: "supervision_api"
+ is_exported: true
+ namespace: "supervision"
+ description: "Flag to enable the SupervisionService"
+ bug: "340351729"
+}
\ No newline at end of file
diff --git a/core/java/android/companion/virtual/flags/flags.aconfig b/core/java/android/companion/virtual/flags/flags.aconfig
index c3c3f0e..b4c36e1 100644
--- a/core/java/android/companion/virtual/flags/flags.aconfig
+++ b/core/java/android/companion/virtual/flags/flags.aconfig
@@ -103,3 +103,10 @@
description: "Expose multiple surface for the virtual camera owner for different stream resolution"
bug: "341083465"
}
+
+flag {
+ namespace: "virtual_devices"
+ name: "device_aware_display_power"
+ description: "Device awareness in power and display APIs"
+ bug: "285020111"
+}
diff --git a/core/java/android/companion/virtual/sensor/VirtualSensorConfig.java b/core/java/android/companion/virtual/sensor/VirtualSensorConfig.java
index 21ad914..82f183f 100644
--- a/core/java/android/companion/virtual/sensor/VirtualSensorConfig.java
+++ b/core/java/android/companion/virtual/sensor/VirtualSensorConfig.java
@@ -17,12 +17,14 @@
package android.companion.virtual.sensor;
+import android.annotation.FlaggedApi;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
+import android.companion.virtualdevice.flags.Flags;
import android.hardware.Sensor;
import android.hardware.SensorDirectChannel;
import android.os.Parcel;
@@ -42,6 +44,13 @@
public final class VirtualSensorConfig implements Parcelable {
private static final String TAG = "VirtualSensorConfig";
+ // Defined in sensors.h
+ private static final int FLAG_WAKE_UP_SENSOR = 1;
+
+ // Mask for the reporting mode, bit 2, 3, 4.
+ private static final int REPORTING_MODE_MASK = 0xE;
+ private static final int REPORTING_MODE_SHIFT = 1;
+
// Mask for direct mode highest rate level, bit 7, 8, 9.
private static final int DIRECT_REPORT_MASK = 0x380;
private static final int DIRECT_REPORT_SHIFT = 7;
@@ -193,8 +202,7 @@
@SensorDirectChannel.RateLevel
public int getHighestDirectReportRateLevel() {
int rateLevel = ((mFlags & DIRECT_REPORT_MASK) >> DIRECT_REPORT_SHIFT);
- return rateLevel <= SensorDirectChannel.RATE_VERY_FAST
- ? rateLevel : SensorDirectChannel.RATE_VERY_FAST;
+ return Math.min(rateLevel, SensorDirectChannel.RATE_VERY_FAST);
}
/**
@@ -215,6 +223,28 @@
}
/**
+ * Returns whether the sensor is a wake-up sensor.
+ *
+ * @see Builder#setWakeUpSensor(boolean)
+ * @see Sensor#isWakeUpSensor()
+ */
+ @FlaggedApi(Flags.FLAG_DEVICE_AWARE_DISPLAY_POWER)
+ public boolean isWakeUpSensor() {
+ return (mFlags & FLAG_WAKE_UP_SENSOR) > 0;
+ }
+
+ /**
+ * Returns the reporting mode of this sensor.
+ *
+ * @see Builder#setReportingMode(int)
+ * @see Sensor#getReportingMode()
+ */
+ @FlaggedApi(Flags.FLAG_DEVICE_AWARE_DISPLAY_POWER)
+ public int getReportingMode() {
+ return ((mFlags & REPORTING_MODE_MASK) >> REPORTING_MODE_SHIFT);
+ }
+
+ /**
* Returns the sensor flags.
*
* @hide
@@ -383,6 +413,45 @@
}
return this;
}
+
+ /**
+ * Sets whether this sensor is a wake up sensor.
+ *
+ * @see Sensor#isWakeUpSensor()
+ */
+ @FlaggedApi(Flags.FLAG_DEVICE_AWARE_DISPLAY_POWER)
+ @NonNull
+ public VirtualSensorConfig.Builder setWakeUpSensor(boolean wakeUpSensor) {
+ if (wakeUpSensor) {
+ mFlags |= FLAG_WAKE_UP_SENSOR;
+ } else {
+ mFlags &= ~FLAG_WAKE_UP_SENSOR;
+ }
+ return this;
+ }
+
+ /**
+ * Sets the reporting mode of this sensor.
+ *
+ * @throws IllegalArgumentException if the reporting mode is not one of
+ * {@link Sensor#REPORTING_MODE_CONTINUOUS}, {@link Sensor#REPORTING_MODE_ON_CHANGE},
+ * {@link Sensor#REPORTING_MODE_ONE_SHOT}, or
+ * {@link Sensor#REPORTING_MODE_SPECIAL_TRIGGER}.
+ *
+ * @see Sensor#getReportingMode()
+ */
+ @FlaggedApi(Flags.FLAG_DEVICE_AWARE_DISPLAY_POWER)
+ @NonNull
+ public VirtualSensorConfig.Builder setReportingMode(int reportingMode) {
+ if (reportingMode != Sensor.REPORTING_MODE_CONTINUOUS
+ && reportingMode != Sensor.REPORTING_MODE_ON_CHANGE
+ && reportingMode != Sensor.REPORTING_MODE_ONE_SHOT
+ && reportingMode != Sensor.REPORTING_MODE_SPECIAL_TRIGGER) {
+ throw new IllegalArgumentException("Invalid reporting mode: " + reportingMode);
+ }
+ mFlags |= reportingMode << REPORTING_MODE_SHIFT;
+ return this;
+ }
}
@NonNull
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 9c711bc..3bf0f032 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -6711,6 +6711,16 @@
public static final String PROTOLOG_CONFIGURATION_SERVICE = "protolog_configuration";
/**
+ * Use with {@link #getSystemService(String)} to retrieve a
+ * {@link android.app.supervision.SupervisionManager}.
+ *
+ * @see #getSystemService(String)
+ * @see android.app.supervision.SupervisionManager
+ * @hide
+ */
+ public static final String SUPERVISION_SERVICE = "supervision";
+
+ /**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
*
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index b7556df..4bc3dbe 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -708,9 +708,16 @@
*
* @hide
*/
+ @android.ravenwood.annotation.RavenwoodReplace
@SystemApi(client = SystemApi.Client.PRIVILEGED_APPS)
public final native void markVintfStability();
+ /** @hide */
+ private void markVintfStability$ravenwood() {
+ // This is not useful for Ravenwood which uses local binder.
+ // TODO(b/361785059): Use real native libbinder.
+ }
+
/**
* Use a VINTF-stability binder w/o VINTF requirements. Should be called
* on a binder before it is sent out of process.
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 0e02627..0e1625a 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -4388,14 +4388,7 @@
mReportNextDraw = false;
mLastReportNextDrawReason = null;
mActiveSurfaceSyncGroup = null;
- if (mHasPendingTransactions) {
- // TODO: We shouldn't ever actually hit this, it means mPendingTransaction wasn't
- // merged with a sync group or BLASTBufferQueue before making it to this point
- // But better a one or two frame flicker than steady-state broken from dropping
- // whatever is in this transaction
- mPendingTransaction.apply();
- mHasPendingTransactions = false;
- }
+ mHasPendingTransactions = false;
mSyncBuffer = false;
if (isInWMSRequestedSync()) {
mWmsRequestSyncGroup.markSyncReady();
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index 4f84817..217bca7 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -225,3 +225,13 @@
description: "Adds a minimize button the the caption bar"
bug: "356843241"
}
+
+flag {
+ name: "skip_compat_ui_education_in_desktop_mode"
+ namespace: "lse_desktop_experience"
+ description: "Ignore Compat UI educations when in Desktop Mode."
+ bug: "357062954"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/core/java/com/android/internal/accessibility/util/ShortcutUtils.java b/core/java/com/android/internal/accessibility/util/ShortcutUtils.java
index 1c26687..2e0ff3d 100644
--- a/core/java/com/android/internal/accessibility/util/ShortcutUtils.java
+++ b/core/java/com/android/internal/accessibility/util/ShortcutUtils.java
@@ -34,6 +34,7 @@
import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.NonNull;
+import android.annotation.SuppressLint;
import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.Context;
@@ -176,24 +177,19 @@
* @param type The shortcut type.
* @return Mapping key in Settings.
*/
+ @SuppressLint("SwitchIntDef")
public static String convertToKey(@UserShortcutType int type) {
- switch (type) {
- case SOFTWARE:
- return Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS;
- case GESTURE:
- return Settings.Secure.ACCESSIBILITY_GESTURE_TARGETS;
- case HARDWARE:
- return Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
- case TRIPLETAP:
- return Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED;
- case TWOFINGER_DOUBLETAP:
- return Settings.Secure.ACCESSIBILITY_MAGNIFICATION_TWO_FINGER_TRIPLE_TAP_ENABLED;
- case QUICK_SETTINGS:
- return Settings.Secure.ACCESSIBILITY_QS_TARGETS;
- default:
- throw new IllegalArgumentException(
- "Unsupported user shortcut type: " + type);
- }
+ return switch (type) {
+ case SOFTWARE -> Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS;
+ case GESTURE -> Settings.Secure.ACCESSIBILITY_GESTURE_TARGETS;
+ case HARDWARE -> Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
+ case TRIPLETAP -> Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED;
+ case TWOFINGER_DOUBLETAP ->
+ Settings.Secure.ACCESSIBILITY_MAGNIFICATION_TWO_FINGER_TRIPLE_TAP_ENABLED;
+ case QUICK_SETTINGS -> Settings.Secure.ACCESSIBILITY_QS_TARGETS;
+ default -> throw new IllegalArgumentException(
+ "Unsupported user shortcut type: " + type);
+ };
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
index c2ee223..972b78f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
@@ -39,6 +39,7 @@
import android.view.accessibility.AccessibilityManager;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.window.flags.Flags;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayController.OnDisplaysChangedListener;
@@ -67,6 +68,7 @@
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
+import java.util.function.IntPredicate;
import java.util.function.Predicate;
/**
@@ -189,6 +191,9 @@
@NonNull
private final CompatUIStatusManager mCompatUIStatusManager;
+ @NonNull
+ private final IntPredicate mInDesktopModePredicate;
+
public CompatUIController(@NonNull Context context,
@NonNull ShellInit shellInit,
@NonNull ShellController shellController,
@@ -202,7 +207,8 @@
@NonNull CompatUIConfiguration compatUIConfiguration,
@NonNull CompatUIShellCommandHandler compatUIShellCommandHandler,
@NonNull AccessibilityManager accessibilityManager,
- @NonNull CompatUIStatusManager compatUIStatusManager) {
+ @NonNull CompatUIStatusManager compatUIStatusManager,
+ @NonNull IntPredicate isDesktopModeEnablePredicate) {
mContext = context;
mShellController = shellController;
mDisplayController = displayController;
@@ -218,6 +224,7 @@
mDisappearTimeSupplier = flags -> accessibilityManager.getRecommendedTimeoutMillis(
DISAPPEAR_DELAY_MS, flags);
mCompatUIStatusManager = compatUIStatusManager;
+ mInDesktopModePredicate = isDesktopModeEnablePredicate;
shellInit.addInitCallback(this::onInit, this);
}
@@ -251,7 +258,9 @@
updateActiveTaskInfo(taskInfo);
}
- if (taskInfo.configuration == null || taskListener == null) {
+ // We close all the Compat UI educations in case we're in desktop mode.
+ if (taskInfo.configuration == null || taskListener == null
+ || isInDesktopMode(taskInfo.displayId)) {
// Null token means the current foreground activity is not in compatibility mode.
removeLayouts(taskInfo.taskId);
return;
@@ -350,7 +359,6 @@
mOnInsetsChangedListeners.remove(displayId);
}
-
@Override
public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
updateDisplayLayout(displayId);
@@ -692,7 +700,8 @@
mContext.startActivityAsUser(intent, userHandle);
}
- private void removeLayouts(int taskId) {
+ @VisibleForTesting
+ void removeLayouts(int taskId) {
final CompatUIWindowManager compatLayout = mActiveCompatLayouts.get(taskId);
if (compatLayout != null) {
compatLayout.release();
@@ -825,4 +834,9 @@
boolean mHasShownCameraCompatHint;
boolean mHasShownUserAspectRatioSettingsButtonHint;
}
+
+ private boolean isInDesktopMode(int displayId) {
+ return Flags.skipCompatUiEducationInDesktopMode()
+ && mInDesktopModePredicate.test(displayId);
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index 98536bf..42937c1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -137,6 +137,7 @@
import dagger.Provides;
import java.util.Optional;
+import java.util.function.IntPredicate;
/**
* Provides basic dependencies from {@link com.android.wm.shell}, these dependencies are only
@@ -261,6 +262,7 @@
Lazy<CompatUIShellCommandHandler> compatUIShellCommandHandler,
Lazy<AccessibilityManager> accessibilityManager,
CompatUIRepository compatUIRepository,
+ Optional<DesktopModeTaskRepository> desktopModeTaskRepository,
@NonNull CompatUIState compatUIState,
@NonNull CompatUIComponentIdGenerator componentIdGenerator,
@NonNull CompatUIComponentFactory compatUIComponentFactory,
@@ -273,6 +275,10 @@
new DefaultCompatUIHandler(compatUIRepository, compatUIState,
componentIdGenerator, compatUIComponentFactory, mainExecutor));
}
+ final IntPredicate inDesktopModePredicate =
+ desktopModeTaskRepository.<IntPredicate>map(modeTaskRepository -> displayId ->
+ modeTaskRepository.getVisibleTaskCount(displayId) > 0)
+ .orElseGet(() -> displayId -> false);
return Optional.of(
new CompatUIController(
context,
@@ -288,7 +294,8 @@
compatUIConfiguration.get(),
compatUIShellCommandHandler.get(),
accessibilityManager.get(),
- compatUIStatusManager));
+ compatUIStatusManager,
+ inDesktopModePredicate));
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellCoroutinesModule.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellCoroutinesModule.kt
index a489c4f..423fe57 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellCoroutinesModule.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellCoroutinesModule.kt
@@ -16,6 +16,7 @@
package com.android.wm.shell.dagger
+import android.os.Handler
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.shared.annotations.ShellBackgroundThread
import com.android.wm.shell.shared.annotations.ShellMainThread
@@ -24,22 +25,37 @@
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.MainCoroutineDispatcher
import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.android.asCoroutineDispatcher
import kotlinx.coroutines.asCoroutineDispatcher
-/** Providers for various WmShell-specific coroutines-related constructs. */
+/**
+ * Providers for various WmShell-specific coroutines-related constructs.
+ *
+ * Providers of [MainCoroutineDispatcher] intentionally creates the dispatcher with a [Handler]
+ * backing it instead of a [ShellExecutor] because [ShellExecutor.asCoroutineDispatcher] will
+ * create a [CoroutineDispatcher] whose [CoroutineDispatcher.isDispatchNeeded] is effectively never
+ * dispatching. This is because even if dispatched, the backing [ShellExecutor.execute] always runs
+ * the [Runnable] immediately if called from the same thread, whereas
+ * [Handler.asCoroutineDispatcher] will create a [MainCoroutineDispatcher] that correctly
+ * dispatches (queues) when [CoroutineDispatcher.isDispatchNeeded] is true using [Handler.post].
+ * For callers that do need a non-dispatching version, [MainCoroutineDispatcher.immediate] is
+ * available.
+ */
@Module
class WMShellCoroutinesModule {
@Provides
@ShellMainThread
- fun provideMainDispatcher(@ShellMainThread mainExecutor: ShellExecutor): CoroutineDispatcher =
- mainExecutor.asCoroutineDispatcher()
+ fun provideMainDispatcher(
+ @ShellMainThread mainHandler: Handler
+ ): MainCoroutineDispatcher = mainHandler.asCoroutineDispatcher()
@Provides
@ShellBackgroundThread
fun provideBackgroundDispatcher(
- @ShellBackgroundThread backgroundExecutor: ShellExecutor
- ): CoroutineDispatcher = backgroundExecutor.asCoroutineDispatcher()
+ @ShellBackgroundThread backgroundHandler: Handler
+ ): MainCoroutineDispatcher = backgroundHandler.asCoroutineDispatcher()
@Provides
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/docs/debugging.md b/libs/WindowManager/Shell/src/com/android/wm/shell/docs/debugging.md
index 84f6af41..72d1a76 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/docs/debugging.md
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/docs/debugging.md
@@ -27,10 +27,13 @@
traces in Winscope)
### Kotlin
+Kotlin protologging is supported but not as optimized as in Java.
-Protolog tool does not yet have support for Kotlin code (see [b/168581922](https://b.corp.google.com/issues/168581922)).
-For logging in Kotlin, use the [KtProtoLog](/libs/WindowManager/Shell/src/com/android/wm/shell/util/KtProtoLog.kt)
-class which has a similar API to the Java ProtoLog class.
+The Protolog tool does not yet have support for Kotlin code ([b/168581922](https://b.corp.google.com/issues/168581922)).
+
+What this implies is that ProtoLogs are not pre-processed to extract the static strings out when used in Kotlin. So,
+there is no memory gain when using ProtoLogging in Kotlin. The logs will still be traced to Perfetto, but with a subtly
+worse performance due to the additional string interning that needs to be done at run time instead of at build time.
### Enabling ProtoLog command line logging
Run these commands to enable protologs (in logcat) for WM Core ([list of all core tags](/core/java/com/android/internal/protolog/ProtoLogGroup.java)):
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 95f864a..8921ceb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -21,6 +21,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
import static android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -684,6 +685,7 @@
setSideStagePosition(splitPosition, wct);
options1 = options1 != null ? options1 : new Bundle();
addActivityOptions(options1, mSideStage);
+ prepareTasksForSplitScreen(new int[] {taskId1, taskId2}, wct);
wct.startTask(taskId1, options1);
startWithTask(wct, taskId2, options2, snapPosition, remoteTransition, instanceId);
@@ -714,6 +716,7 @@
options1 = options1 != null ? options1 : new Bundle();
addActivityOptions(options1, mSideStage);
wct.sendPendingIntent(pendingIntent, fillInIntent, options1);
+ prepareTasksForSplitScreen(new int[] {taskId}, wct);
startWithTask(wct, taskId, options2, snapPosition, remoteTransition, instanceId);
}
@@ -757,11 +760,30 @@
options1 = options1 != null ? options1 : new Bundle();
addActivityOptions(options1, mSideStage);
wct.startShortcut(mContext.getPackageName(), shortcutInfo, options1);
+ prepareTasksForSplitScreen(new int[] {taskId}, wct);
startWithTask(wct, taskId, options2, snapPosition, remoteTransition, instanceId);
}
/**
+ * Prepares the tasks whose IDs are provided in `taskIds` for split screen by clearing their
+ * bounds and windowing mode so that they can inherit the bounds and the windowing mode of
+ * their root stages.
+ *
+ * @param taskIds an array of task IDs whose bounds will be cleared.
+ * @param wct transaction to clear the bounds on the tasks.
+ */
+ private void prepareTasksForSplitScreen(int[] taskIds, WindowContainerTransaction wct) {
+ for (int taskId : taskIds) {
+ ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId);
+ if (task != null) {
+ wct.setWindowingMode(task.token, WINDOWING_MODE_UNDEFINED)
+ .setBounds(task.token, null);
+ }
+ }
+ }
+
+ /**
* Starts with the second task to a split pair in one transition.
*
* @param wct transaction to start the first task
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
index b39cf19..d5287e7 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
@@ -35,9 +35,12 @@
import android.app.TaskInfo;
import android.content.Context;
import android.content.res.Configuration;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.RequiresFlagsDisabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.testing.AndroidTestingRunner;
import android.view.InsetsSource;
import android.view.InsetsState;
@@ -90,6 +93,9 @@
public final CheckFlagsRule mCheckFlagsRule =
DeviceFlagsValueProvider.createCheckFlagsRule();
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
private CompatUIController mController;
private ShellInit mShellInit;
@Mock
@@ -122,7 +128,6 @@
private CompatUIConfiguration mCompatUIConfiguration;
@Mock
private CompatUIShellCommandHandler mCompatUIShellCommandHandler;
-
@Mock
private AccessibilityManager mAccessibilityManager;
@@ -132,6 +137,8 @@
@NonNull
private CompatUIStatusManager mCompatUIStatusManager;
+ private boolean mInDesktopModePredicateResult;
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
@@ -157,7 +164,7 @@
mMockDisplayController, mMockDisplayInsetsController, mMockImeController,
mMockSyncQueue, mMockExecutor, mMockTransitionsLazy, mDockStateReader,
mCompatUIConfiguration, mCompatUIShellCommandHandler, mAccessibilityManager,
- mCompatUIStatusManager) {
+ mCompatUIStatusManager, i -> mInDesktopModePredicateResult) {
@Override
CompatUIWindowManager createCompatUiWindowManager(Context context, TaskInfo taskInfo,
ShellTaskOrganizer.TaskListener taskListener) {
@@ -685,6 +692,7 @@
}
@Test
+ @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
public void testLetterboxEduLayout_notCreatedWhenLetterboxEducationIsDisabled() {
TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
taskInfo.appCompatTaskInfo.setLetterboxEducationEnabled(false);
@@ -695,6 +703,34 @@
eq(mMockTaskListener));
}
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
+ @EnableFlags(Flags.FLAG_SKIP_COMPAT_UI_EDUCATION_IN_DESKTOP_MODE)
+ public void testUpdateActiveTaskInfo_removeAllComponentWhenInDesktopModeFlagEnabled() {
+ mInDesktopModePredicateResult = false;
+ TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
+ mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
+ verify(mController, never()).removeLayouts(taskInfo.taskId);
+
+ mInDesktopModePredicateResult = true;
+ mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
+ verify(mController).removeLayouts(taskInfo.taskId);
+ }
+
+ @Test
+ @RequiresFlagsDisabled(Flags.FLAG_APP_COMPAT_UI_FRAMEWORK)
+ @DisableFlags(Flags.FLAG_SKIP_COMPAT_UI_EDUCATION_IN_DESKTOP_MODE)
+ public void testUpdateActiveTaskInfo_removeAllComponentWhenInDesktopModeFlagDisabled() {
+ mInDesktopModePredicateResult = false;
+ TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID, /* hasSizeCompat= */ true);
+ mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
+ verify(mController, never()).removeLayouts(taskInfo.taskId);
+
+ mInDesktopModePredicateResult = true;
+ mController.onCompatInfoChanged(new CompatUIInfo(taskInfo, mMockTaskListener));
+ verify(mController, never()).removeLayouts(taskInfo.taskId);
+ }
+
private static TaskInfo createTaskInfo(int displayId, int taskId, boolean hasSizeCompat) {
return createTaskInfo(displayId, taskId, hasSizeCompat, /* isVisible */ false,
/* isFocused */ false, /* isTopActivityTransparent */ false);
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 2c71ee0..d14275f 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -18,6 +18,7 @@
import android.annotation.BytesLong;
import android.annotation.CallbackExecutor;
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
@@ -32,6 +33,7 @@
import android.hardware.tv.tuner.FrontendScanType;
import android.media.MediaCodec;
import android.media.tv.TvInputService;
+import android.media.tv.flags.Flags;
import android.media.tv.tuner.dvr.DvrPlayback;
import android.media.tv.tuner.dvr.DvrRecorder;
import android.media.tv.tuner.dvr.OnPlaybackStatusChangedListener;
@@ -2529,6 +2531,50 @@
}
/**
+ * Request a frontend by frontend type.
+ *
+ * <p> This API is used if the applications want to select a frontend with desired type when
+ * there are multiple frontends of the same type is there before {@link tune}. The applied
+ * frontend will be one of the not in-use frontend. If all frontends are in-use, this API will
+ * reclaim and apply the frontend owned by the lowest priority client if current client has
+ * higher priority. Otherwise, this API will not apply any frontend and return
+ * {@link #RESULT_UNAVAILABLE}.
+ *
+ * @param desiredFrontendType the Type of the desired fronted. Should be one of
+ * {@link android.media.tv.tuner.frontend.FrontendSettings.Type}
+ * @return result status of open operation.
+ */
+ @Result
+ @FlaggedApi(Flags.FLAG_TUNER_W_APIS)
+ @RequiresPermission(
+ allOf = {"android.permission.TUNER_RESOURCE_ACCESS", "android.permission.ACCESS_TV_TUNER"})
+ public int applyFrontendByType(@FrontendSettings.Type int desiredFrontendType) {
+ mFrontendLock.lock();
+ try {
+ if (mFeOwnerTuner != null) {
+ Log.e(TAG, "Operation connot be done by sharee of tuner");
+ return RESULT_INVALID_STATE;
+ }
+ if (mFrontendHandle != null) {
+ Log.e(TAG, "A frontend has been opened before");
+ return RESULT_INVALID_STATE;
+ }
+
+ mDesiredFrontendId = null;
+ mFrontendType = desiredFrontendType;
+ if (DEBUG) {
+ Log.d(TAG, "Applying frontend with type " + mFrontendType);
+ }
+ if (!checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND, mFrontendLock)) {
+ return RESULT_UNAVAILABLE;
+ }
+ return RESULT_SUCCESS;
+ } finally {
+ mFrontendLock.unlock();
+ }
+ }
+
+ /**
* Open a shared filter instance.
*
* @param context the context of the caller.
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/OWNERS b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/OWNERS
new file mode 100644
index 0000000..134a56e
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/OWNERS
@@ -0,0 +1 @@
+include /packages/SettingsLib/src/com/android/settingslib/bluetooth/OWNERS
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index a129ac1..8a1d81b 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -1120,16 +1120,6 @@
}
flag {
- name: "glanceable_hub_back_gesture"
- namespace: "systemui"
- description: "Enables back gesture on the glanceable hub"
- bug: "346331399"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "glanceable_hub_allow_keyguard_when_dreaming"
namespace: "systemui"
description: "Allows users to exit dream to keyguard with glanceable hub enabled"
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
index 872bef2..ed12776 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
@@ -31,7 +31,6 @@
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
-import com.android.compose.animation.scene.Back
import com.android.compose.animation.scene.ContentKey
import com.android.compose.animation.scene.Edge
import com.android.compose.animation.scene.ElementKey
@@ -47,7 +46,6 @@
import com.android.compose.animation.scene.transitions
import com.android.compose.theme.LocalAndroidColorScheme
import com.android.internal.R.attr.focusable
-import com.android.systemui.Flags.glanceableHubBackGesture
import com.android.systemui.communal.shared.model.CommunalBackgroundType
import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.communal.shared.model.CommunalTransitionKeys
@@ -198,15 +196,7 @@
Box(modifier = Modifier.fillMaxSize())
}
- val userActions =
- if (glanceableHubBackGesture()) {
- mapOf(
- Swipe(SwipeDirection.End) to CommunalScenes.Blank,
- Back to CommunalScenes.Blank,
- )
- } else {
- mapOf(Swipe(SwipeDirection.End) to CommunalScenes.Blank)
- }
+ val userActions = mapOf(Swipe(SwipeDirection.End) to CommunalScenes.Blank)
scene(CommunalScenes.Communal, userActions = userActions) {
CommunalScene(
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
index d5874d1..e17cb31 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
@@ -16,6 +16,8 @@
package com.android.systemui.scene.ui.composable
+import androidx.compose.foundation.gestures.awaitEachGesture
+import androidx.compose.foundation.gestures.awaitFirstDown
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Text
@@ -28,6 +30,7 @@
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.pointer.pointerInput
import com.android.compose.animation.scene.MutableSceneTransitionLayoutState
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.SceneTransitionLayout
@@ -100,7 +103,13 @@
}
Box(
- modifier = Modifier.fillMaxSize(),
+ modifier =
+ Modifier.fillMaxSize().pointerInput(Unit) {
+ awaitEachGesture {
+ awaitFirstDown(false)
+ viewModel.onSceneContainerUserInputStarted()
+ }
+ },
) {
SceneTransitionLayout(state = state, modifier = modifier.fillMaxSize()) {
sceneByKey.forEach { (sceneKey, composableScene) ->
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt
index d850f17..65236f0 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt
@@ -30,8 +30,6 @@
import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.EnableSceneContainer
-import com.android.systemui.flags.Flags.REFACTOR_GETCURRENTUSER
-import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.kosmos.testScope
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
@@ -90,8 +88,6 @@
.thenReturn(needsEmergencyAffordance)
whenever(telecomManager.isInCall).thenReturn(false)
- kosmos.fakeFeatureFlagsClassic.set(REFACTOR_GETCURRENTUSER, true)
-
kosmos.fakeTelephonyRepository.setHasTelephonyRadio(true)
kosmos.telecomManager = telecomManager
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
index c633816..5b987b3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
@@ -175,10 +175,7 @@
emergencyAffordanceManager = kosmos.emergencyAffordanceManager
whenever(emergencyAffordanceManager.needsEmergencyAffordance()).thenReturn(true)
- kosmos.fakeFeatureFlagsClassic.apply {
- set(Flags.NEW_NETWORK_SLICE_UI, false)
- set(Flags.REFACTOR_GETCURRENTUSER, true)
- }
+ kosmos.fakeFeatureFlagsClassic.apply { set(Flags.NEW_NETWORK_SLICE_UI, false) }
mobileConnectionsRepository = kosmos.fakeMobileConnectionsRepository
mobileConnectionsRepository.isAnySimSecure.value = false
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
index e3a69a9..35cefa6 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
@@ -401,10 +401,10 @@
underTest.setVisible(false, "reason")
val isVisible by collectLastValue(underTest.isVisible)
assertThat(isVisible).isFalse()
- underTest.onRemoteUserInteractionStarted("reason")
+ underTest.onRemoteUserInputStarted("reason")
assertThat(isVisible).isTrue()
- underTest.onUserInteractionFinished()
+ underTest.onUserInputFinished()
assertThat(isVisible).isFalse()
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
index f856c55..832e7b1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModelTest.kt
@@ -237,7 +237,7 @@
sceneInteractor.setVisible(false, "reason")
runCurrent()
assertThat(underTest.isVisible).isFalse()
- sceneInteractor.onRemoteUserInteractionStarted("reason")
+ sceneInteractor.onRemoteUserInputStarted("reason")
runCurrent()
assertThat(underTest.isVisible).isTrue()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModelTest.kt
index 6a88664..8b97739 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModelTest.kt
@@ -22,6 +22,8 @@
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
@@ -83,4 +85,69 @@
)
assertThat(isKeyguardOccluded).isFalse()
}
+
+ @Test
+ fun transitionFromOccludedToDreamingTransitionRemainsTrue() =
+ testScope.runTest {
+ val isKeyguardOccluded by collectLastValue(underTest.isKeyguardOccluded)
+ assertThat(isKeyguardOccluded).isFalse()
+
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ TransitionStep(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.DREAMING,
+ value = 0f,
+ transitionState = TransitionState.STARTED,
+ ),
+ TransitionStep(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.DREAMING,
+ value = 0.5f,
+ transitionState = TransitionState.RUNNING,
+ ),
+ ),
+ testScope,
+ )
+ assertThat(isKeyguardOccluded).isFalse()
+
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.DREAMING,
+ value = 1f,
+ transitionState = TransitionState.FINISHED,
+ ),
+ )
+ assertThat(isKeyguardOccluded).isTrue()
+
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ TransitionStep(
+ from = KeyguardState.DREAMING,
+ to = KeyguardState.OCCLUDED,
+ value = 0f,
+ transitionState = TransitionState.STARTED,
+ ),
+ TransitionStep(
+ from = KeyguardState.DREAMING,
+ to = KeyguardState.OCCLUDED,
+ value = 0.5f,
+ transitionState = TransitionState.RUNNING,
+ ),
+ ),
+ testScope,
+ )
+ assertThat(isKeyguardOccluded).isTrue()
+
+ keyguardTransitionRepository.sendTransitionStep(
+ TransitionStep(
+ from = KeyguardState.DREAMING,
+ to = KeyguardState.OCCLUDED,
+ value = 1f,
+ transitionState = TransitionState.FINISHED,
+ ),
+ )
+ assertThat(isKeyguardOccluded).isTrue()
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorTest.kt
index 1356e93..06a2c5a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorTest.kt
@@ -21,6 +21,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds
import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimRounding
@@ -84,4 +85,48 @@
)
)
}
+
+ @Test
+ fun shouldCloseGuts_userInputOngoing_currentGestureInGuts() =
+ testScope.runTest {
+ val shouldCloseGuts by collectLastValue(underTest.shouldCloseGuts)
+
+ kosmos.sceneInteractor.onSceneContainerUserInputStarted()
+ underTest.setCurrentGestureInGuts(true)
+
+ assertThat(shouldCloseGuts).isFalse()
+ }
+
+ @Test
+ fun shouldCloseGuts_userInputOngoing_currentGestureNotInGuts() =
+ testScope.runTest {
+ val shouldCloseGuts by collectLastValue(underTest.shouldCloseGuts)
+
+ kosmos.sceneInteractor.onSceneContainerUserInputStarted()
+ underTest.setCurrentGestureInGuts(false)
+
+ assertThat(shouldCloseGuts).isTrue()
+ }
+
+ @Test
+ fun shouldCloseGuts_userInputNotOngoing_currentGestureInGuts() =
+ testScope.runTest {
+ val shouldCloseGuts by collectLastValue(underTest.shouldCloseGuts)
+
+ kosmos.sceneInteractor.onUserInputFinished()
+ underTest.setCurrentGestureInGuts(true)
+
+ assertThat(shouldCloseGuts).isFalse()
+ }
+
+ @Test
+ fun shouldCloseGuts_userInputNotOngoing_currentGestureNotInGuts() =
+ testScope.runTest {
+ val shouldCloseGuts by collectLastValue(underTest.shouldCloseGuts)
+
+ kosmos.sceneInteractor.onUserInputFinished()
+ underTest.setCurrentGestureInGuts(false)
+
+ assertThat(shouldCloseGuts).isFalse()
+ }
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
index 4ef1f93..121577e 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
@@ -342,8 +342,7 @@
// the keyguard)
if ((sysuiStateFlags & SYSUI_STATE_BOUNCER_SHOWING) != 0
|| (sysuiStateFlags & SYSUI_STATE_DIALOG_SHOWING) != 0
- || (sysuiStateFlags & SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING) != 0
- || (sysuiStateFlags & SYSUI_STATE_COMMUNAL_HUB_SHOWING) != 0) {
+ || (sysuiStateFlags & SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING) != 0) {
return false;
}
if ((sysuiStateFlags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 60fff28..9b45fa4 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -483,22 +483,6 @@
@VisibleForTesting
SparseArray<BiometricAuthenticated> mUserFingerprintAuthenticated = new SparseArray<>();
- private static int sCurrentUser;
-
- @Deprecated
- public synchronized static void setCurrentUser(int currentUser) {
- sCurrentUser = currentUser;
- }
-
- /**
- * @deprecated This can potentially return unexpected values in a multi user scenario
- * as this state is managed by another component. Consider using {@link SelectedUserInteractor}.
- */
- @Deprecated
- public synchronized static int getCurrentUser() {
- return sCurrentUser;
- }
-
@Override
public void onTrustChanged(boolean enabled, boolean newlyUnlocked, int userId, int flags,
List<String> trustGrantedMessages) {
@@ -969,7 +953,7 @@
mHandler.removeCallbacks(mFpCancelNotReceived);
}
try {
- final int userId = mSelectedUserInteractor.getSelectedUserId(true);
+ final int userId = mSelectedUserInteractor.getSelectedUserId();
if (userId != authUserId) {
mLogger.logFingerprintAuthForWrongUser(authUserId);
return;
@@ -1220,7 +1204,7 @@
mLogger.d("Aborted successful auth because device is going to sleep.");
return;
}
- final int userId = mSelectedUserInteractor.getSelectedUserId(true);
+ final int userId = mSelectedUserInteractor.getSelectedUserId();
if (userId != authUserId) {
mLogger.logFaceAuthForWrongUser(authUserId);
return;
@@ -2462,7 +2446,7 @@
updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
mTaskStackChangeListeners.registerTaskStackListener(mTaskStackListener);
- int user = mSelectedUserInteractor.getSelectedUserId(true);
+ int user = mSelectedUserInteractor.getSelectedUserId();
boolean isUserUnlocked = mUserManager.isUserUnlocked(user);
mLogger.logUserUnlockedInitialState(user, isUserUnlocked);
mUserIsUnlocked.put(user, isUserUnlocked);
@@ -4081,7 +4065,7 @@
pw.println(" " + subId + "=" + mServiceStates.get(subId));
}
if (isFingerprintSupported()) {
- final int userId = mSelectedUserInteractor.getSelectedUserId(true);
+ final int userId = mSelectedUserInteractor.getSelectedUserId();
final int strongAuthFlags = mStrongAuthTracker.getStrongAuthForUser(userId);
BiometricAuthenticated fingerprint = mUserFingerprintAuthenticated.get(userId);
pw.println(" Fingerprint state (user=" + userId + ")");
@@ -4124,7 +4108,7 @@
mFingerprintListenBuffer.toList()
).printTableData(pw);
} else if (mFpm != null && mFingerprintSensorProperties.isEmpty()) {
- final int userId = mSelectedUserInteractor.getSelectedUserId(true);
+ final int userId = mSelectedUserInteractor.getSelectedUserId();
pw.println(" Fingerprint state (user=" + userId + ")");
pw.println(" mFingerprintSensorProperties.isEmpty="
+ mFingerprintSensorProperties.isEmpty());
@@ -4137,7 +4121,7 @@
mFingerprintListenBuffer.toList()
).printTableData(pw);
}
- final int userId = mSelectedUserInteractor.getSelectedUserId(true);
+ final int userId = mSelectedUserInteractor.getSelectedUserId();
final int strongAuthFlags = mStrongAuthTracker.getStrongAuthForUser(userId);
pw.println(" authSinceBoot="
+ getStrongAuthTracker().hasUserAuthenticatedSinceBoot());
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityGestureTargetsObserver.java b/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityGestureTargetsObserver.java
new file mode 100644
index 0000000..c944878
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/AccessibilityGestureTargetsObserver.java
@@ -0,0 +1,67 @@
+/*
+ * 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.accessibility;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import androidx.annotation.MainThread;
+import androidx.annotation.Nullable;
+
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.settings.UserTracker;
+
+import javax.inject.Inject;
+
+/**
+ * Controller for tracking the current accessibility gesture list.
+ *
+ * @see Settings.Secure#ACCESSIBILITY_GESTURE_TARGETS
+ */
+@MainThread
+@SysUISingleton
+public class AccessibilityGestureTargetsObserver extends
+ SecureSettingsContentObserver<AccessibilityGestureTargetsObserver.TargetsChangedListener> {
+
+ /** Listener for accessibility gesture targets changes. */
+ public interface TargetsChangedListener {
+
+ /**
+ * Called when accessibility gesture targets changes.
+ *
+ * @param targets Current content of {@link Settings.Secure#ACCESSIBILITY_GESTURE_TARGETS}
+ */
+ void onAccessibilityGestureTargetsChanged(String targets);
+ }
+
+ @Inject
+ public AccessibilityGestureTargetsObserver(Context context, UserTracker userTracker) {
+ super(context, userTracker, Settings.Secure.ACCESSIBILITY_GESTURE_TARGETS);
+ }
+
+ @Override
+ void onValueChanged(TargetsChangedListener listener, String value) {
+ listener.onAccessibilityGestureTargetsChanged(value);
+ }
+
+ /** Returns the current string from settings key
+ * {@link Settings.Secure#ACCESSIBILITY_GESTURE_TARGETS}. */
+ @Nullable
+ public String getCurrentAccessibilityGestureTargets() {
+ return getSettingsValue();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt b/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
index 6757edb..b2d02ed 100644
--- a/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
@@ -120,7 +120,7 @@
Intent.FLAG_ACTIVITY_NEW_TASK,
null,
activityOptions.toBundle(),
- selectedUserInteractor.getSelectedUserId(true),
+ selectedUserInteractor.getSelectedUserId(),
)
} catch (e: RemoteException) {
Log.w("CameraGestureHelper", "Unable to start camera activity", e)
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/EditTextActivity.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/EditTextActivity.java
index a43447f..aae21b9 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/EditTextActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/EditTextActivity.java
@@ -66,7 +66,8 @@
@Override
public WindowInsets onApplyWindowInsets(@NonNull View view,
@NonNull WindowInsets windowInsets) {
- Insets insets = windowInsets.getInsets(WindowInsets.Type.systemBars());
+ Insets insets = windowInsets.getInsets(
+ WindowInsets.Type.systemBars() | WindowInsets.Type.ime());
ViewGroup.MarginLayoutParams layoutParams =
(ViewGroup.MarginLayoutParams) view.getLayoutParams();
layoutParams.leftMargin = insets.left;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index e07b5c2..21922ff 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -256,7 +256,7 @@
Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE,
mConfig.wakeScreenGestureAvailable()
&& mConfig.alwaysOnEnabled(
- mSelectedUserInteractor.getSelectedUserId(true)),
+ mSelectedUserInteractor.getSelectedUserId()),
DozeLog.REASON_SENSOR_WAKE_UP_PRESENCE,
false /* reports touch coordinates */,
false /* touchscreen */
@@ -297,7 +297,7 @@
private boolean udfpsLongPressConfigured() {
return mUdfpsEnrolled
- && (mConfig.alwaysOnEnabled(mSelectedUserInteractor.getSelectedUserId(true))
+ && (mConfig.alwaysOnEnabled(mSelectedUserInteractor.getSelectedUserId())
|| mScreenOffUdfpsEnabled);
}
@@ -477,7 +477,7 @@
private final ContentObserver mSettingsObserver = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange, Collection<Uri> uris, int flags, int userId) {
- if (userId != mSelectedUserInteractor.getSelectedUserId(true)) {
+ if (userId != mSelectedUserInteractor.getSelectedUserId()) {
return;
}
for (TriggerSensor s : mTriggerSensors) {
@@ -703,13 +703,13 @@
}
protected boolean enabledBySetting() {
- if (!mConfig.enabled(mSelectedUserInteractor.getSelectedUserId(true))) {
+ if (!mConfig.enabled(mSelectedUserInteractor.getSelectedUserId())) {
return false;
} else if (TextUtils.isEmpty(mSetting)) {
return true;
}
return mSecureSettings.getIntForUser(mSetting, mSettingDefault ? 1 : 0,
- mSelectedUserInteractor.getSelectedUserId(true)) != 0;
+ mSelectedUserInteractor.getSelectedUserId()) != 0;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 4a9f741..dd08d32 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -251,7 +251,7 @@
return;
}
mNotificationPulseTime = SystemClock.elapsedRealtime();
- if (!mConfig.pulseOnNotificationEnabled(mSelectedUserInteractor.getSelectedUserId(true))) {
+ if (!mConfig.pulseOnNotificationEnabled(mSelectedUserInteractor.getSelectedUserId())) {
runIfNotNull(onPulseSuppressedListener);
mDozeLog.tracePulseDropped("pulseOnNotificationsDisabled");
return;
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 4d75d66..bb73f56 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -55,19 +55,13 @@
// TODO(b/254512624): Tracking Bug
@JvmField
val NOTIFICATION_DRAG_TO_CONTENTS =
- resourceBooleanFlag(
- R.bool.config_notificationToContents,
- "notification_drag_to_contents"
- )
+ resourceBooleanFlag(R.bool.config_notificationToContents, "notification_drag_to_contents")
// TODO(b/280783617): Tracking Bug
@Keep
@JvmField
val BUILDER_EXTRAS_OVERRIDE =
- sysPropBooleanFlag(
- "persist.sysui.notification.builder_extras_override",
- default = true
- )
+ sysPropBooleanFlag("persist.sysui.notification.builder_extras_override", default = true)
// 200 - keyguard/lockscreen
// ** Flag retired **
@@ -81,10 +75,7 @@
// TODO(b/254512676): Tracking Bug
@JvmField
val LOCKSCREEN_CUSTOM_CLOCKS =
- resourceBooleanFlag(
- R.bool.config_enableLockScreenCustomClocks,
- "lockscreen_custom_clocks"
- )
+ resourceBooleanFlag(R.bool.config_enableLockScreenCustomClocks, "lockscreen_custom_clocks")
/**
* Whether the clock on a wide lock screen should use the new "stepping" animation for moving
@@ -99,10 +90,6 @@
// TODO(b/255607168): Tracking Bug
@JvmField val DOZING_MIGRATION_1 = unreleasedFlag("dozing_migration_1")
- // TODO(b/305984787):
- @JvmField
- val REFACTOR_GETCURRENTUSER = unreleasedFlag("refactor_getcurrentuser", teamfood = true)
-
/** Flag to control the revamp of keyguard biometrics progress animation */
// TODO(b/244313043): Tracking bug
@JvmField val BIOMETRICS_ANIMATION_REVAMP = unreleasedFlag("biometrics_animation_revamp")
@@ -125,13 +112,11 @@
/** Whether the long-press gesture to open wallpaper picker is enabled. */
// TODO(b/266242192): Tracking Bug
- @JvmField
- val LOCK_SCREEN_LONG_PRESS_ENABLED = releasedFlag("lock_screen_long_press_enabled")
+ @JvmField val LOCK_SCREEN_LONG_PRESS_ENABLED = releasedFlag("lock_screen_long_press_enabled")
/** Inflate and bind views upon emitting a blueprint value . */
// TODO(b/297365780): Tracking Bug
- @JvmField
- val LAZY_INFLATE_KEYGUARD = releasedFlag("lazy_inflate_keyguard")
+ @JvmField val LAZY_INFLATE_KEYGUARD = releasedFlag("lazy_inflate_keyguard")
/** Enables UI updates for AI wallpapers in the wallpaper picker. */
// TODO(b/267722622): Tracking Bug
@@ -145,8 +130,7 @@
/** Add "Apply" button to wall paper picker's grid preview page. */
// TODO(b/294866904): Tracking bug.
@JvmField
- val WALLPAPER_PICKER_GRID_APPLY_BUTTON =
- unreleasedFlag("wallpaper_picker_grid_apply_button")
+ val WALLPAPER_PICKER_GRID_APPLY_BUTTON = unreleasedFlag("wallpaper_picker_grid_apply_button")
/** Flag meant to guard the talkback fix for the KeyguardIndicationTextView */
// TODO(b/286563884): Tracking bug
@@ -190,10 +174,7 @@
// TODO(b/254512383): Tracking Bug
@JvmField
val FULL_SCREEN_USER_SWITCHER =
- resourceBooleanFlag(
- R.bool.config_enableFullscreenUserSwitcher,
- "full_screen_user_switcher"
- )
+ resourceBooleanFlag(R.bool.config_enableFullscreenUserSwitcher, "full_screen_user_switcher")
// TODO(b/244064524): Tracking Bug
@JvmField val QS_SECONDARY_DATA_SUB_INFO = releasedFlag("qs_secondary_data_sub_info")
@@ -212,16 +193,15 @@
@JvmField val NEW_NETWORK_SLICE_UI = releasedFlag("new_network_slice_ui")
// TODO(b/311222557): Tracking bug
- val ROAMING_INDICATOR_VIA_DISPLAY_INFO =
- releasedFlag("roaming_indicator_via_display_info")
+ val ROAMING_INDICATOR_VIA_DISPLAY_INFO = releasedFlag("roaming_indicator_via_display_info")
// TODO(b/308138154): Tracking bug
val FILTER_PROVISIONING_NETWORK_SUBSCRIPTIONS =
releasedFlag("filter_provisioning_network_subscriptions")
// TODO(b/293863612): Tracking Bug
- @JvmField val INCOMPATIBLE_CHARGING_BATTERY_ICON =
- releasedFlag("incompatible_charging_battery_icon")
+ @JvmField
+ val INCOMPATIBLE_CHARGING_BATTERY_ICON = releasedFlag("incompatible_charging_battery_icon")
// TODO(b/293585143): Tracking Bug
val INSTANT_TETHER = releasedFlag("instant_tether")
@@ -230,8 +210,7 @@
val WIFI_SECONDARY_NETWORKS = releasedFlag("wifi_secondary_networks")
// TODO(b/290676905): Tracking Bug
- val NEW_SHADE_CARRIER_GROUP_MOBILE_ICONS =
- releasedFlag("new_shade_carrier_group_mobile_icons")
+ val NEW_SHADE_CARRIER_GROUP_MOBILE_ICONS = releasedFlag("new_shade_carrier_group_mobile_icons")
// 800 - general visual/theme
@JvmField val MONET = resourceBooleanFlag(R.bool.flag_monet, "monet")
@@ -280,8 +259,7 @@
// TODO(b/273509374): Tracking Bug
@JvmField
- val ALWAYS_SHOW_HOME_CONTROLS_ON_DREAMS =
- releasedFlag("always_show_home_controls_on_dreams")
+ val ALWAYS_SHOW_HOME_CONTROLS_ON_DREAMS = releasedFlag("always_show_home_controls_on_dreams")
// 1100 - windowing
@Keep
@@ -304,9 +282,7 @@
)
// TODO(b/293252410) : Tracking Bug
- @JvmField
- val LOCKSCREEN_ENABLE_LANDSCAPE =
- unreleasedFlag("lockscreen.enable_landscape")
+ @JvmField val LOCKSCREEN_ENABLE_LANDSCAPE = unreleasedFlag("lockscreen.enable_landscape")
// 1200 - predictive back
@Keep
@@ -327,8 +303,7 @@
val QUICK_TAP_IN_PCC = releasedFlag("quick_tap_in_pcc")
// TODO(b/261979569): Tracking Bug
- val QUICK_TAP_FLOW_FRAMEWORK =
- unreleasedFlag("quick_tap_flow_framework", teamfood = false)
+ val QUICK_TAP_FLOW_FRAMEWORK = unreleasedFlag("quick_tap_flow_framework", teamfood = false)
// 1500 - chooser aka sharesheet
@@ -364,14 +339,12 @@
// TODO(b/265764985): Tracking Bug
@Keep
@JvmField
- val ENABLE_DARK_VIGNETTE_WHEN_FOLDING =
- unreleasedFlag("enable_dark_vignette_when_folding")
+ val ENABLE_DARK_VIGNETTE_WHEN_FOLDING = unreleasedFlag("enable_dark_vignette_when_folding")
// TODO(b/265764985): Tracking Bug
@Keep
@JvmField
- val ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS =
- unreleasedFlag("enable_unfold_status_bar_animations")
+ val ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS = unreleasedFlag("enable_unfold_status_bar_animations")
// TODO(b/316157842): Tracking Bug
// Adds extra delay to notifications measure
@@ -415,28 +388,26 @@
unreleasedFlag("bigpicture_notification_lazy_loading")
// TODO(b/283740863): Tracking Bug
- @JvmField
- val ENABLE_NEW_PRIVACY_DIALOG = releasedFlag("enable_new_privacy_dialog")
+ @JvmField val ENABLE_NEW_PRIVACY_DIALOG = releasedFlag("enable_new_privacy_dialog")
// TODO(b/302144438): Tracking Bug
- @JvmField val DECOUPLE_REMOTE_INPUT_DELEGATE_AND_CALLBACK_UPDATE =
- unreleasedFlag("decouple_remote_input_delegate_and_callback_update")
+ @JvmField
+ val DECOUPLE_REMOTE_INPUT_DELEGATE_AND_CALLBACK_UPDATE =
+ unreleasedFlag("decouple_remote_input_delegate_and_callback_update")
/** TODO(b/296223317): Enables the new keyguard presentation containing a clock. */
@JvmField
val ENABLE_CLOCK_KEYGUARD_PRESENTATION = releasedFlag("enable_clock_keyguard_presentation")
/** Enable the share wifi button in Quick Settings internet dialog. */
- @JvmField
- val SHARE_WIFI_QS_BUTTON = releasedFlag("share_wifi_qs_button")
+ @JvmField val SHARE_WIFI_QS_BUTTON = releasedFlag("share_wifi_qs_button")
/** Enable showing a dialog when clicking on Quick Settings bluetooth tile. */
- @JvmField
- val BLUETOOTH_QS_TILE_DIALOG = releasedFlag("bluetooth_qs_tile_dialog")
+ @JvmField val BLUETOOTH_QS_TILE_DIALOG = releasedFlag("bluetooth_qs_tile_dialog")
// TODO(b/300995746): Tracking Bug
/** A resource flag for whether the communal service is enabled. */
@JvmField
- val COMMUNAL_SERVICE_ENABLED = resourceBooleanFlag(R.bool.config_communalServiceEnabled,
- "communal_service_enabled")
+ val COMMUNAL_SERVICE_ENABLED =
+ resourceBooleanFlag(R.bool.config_communalServiceEnabled, "communal_service_enabled")
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 871d046..0feb5ec 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -35,8 +35,6 @@
import static android.view.WindowManager.TransitionOldType;
import static android.view.WindowManager.TransitionType;
-import static com.android.systemui.Flags.refactorGetCurrentUser;
-
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
@@ -79,6 +77,7 @@
import com.android.systemui.dagger.qualifiers.Application;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.keyguard.domain.interactor.KeyguardDismissInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardEnabledInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardWakeDirectlyToGoneInteractor;
@@ -319,6 +318,7 @@
private final WindowManagerOcclusionManager mWmOcclusionManager;
private final KeyguardEnabledInteractor mKeyguardEnabledInteractor;
private final KeyguardWakeDirectlyToGoneInteractor mKeyguardWakeDirectlyToGoneInteractor;
+ private final KeyguardDismissInteractor mKeyguardDismissInteractor;
private final Lazy<FoldGracePeriodProvider> mFoldGracePeriodProvider = new Lazy<>() {
@Override
public FoldGracePeriodProvider get() {
@@ -346,7 +346,8 @@
KeyguardInteractor keyguardInteractor,
KeyguardEnabledInteractor keyguardEnabledInteractor,
Lazy<KeyguardStateCallbackStartable> keyguardStateCallbackStartableLazy,
- KeyguardWakeDirectlyToGoneInteractor keyguardWakeDirectlyToGoneInteractor) {
+ KeyguardWakeDirectlyToGoneInteractor keyguardWakeDirectlyToGoneInteractor,
+ KeyguardDismissInteractor keyguardDismissInteractor) {
super();
mKeyguardViewMediator = keyguardViewMediator;
mKeyguardLifecyclesDispatcher = keyguardLifecyclesDispatcher;
@@ -375,6 +376,7 @@
mWmOcclusionManager = windowManagerOcclusionManager;
mKeyguardEnabledInteractor = keyguardEnabledInteractor;
mKeyguardWakeDirectlyToGoneInteractor = keyguardWakeDirectlyToGoneInteractor;
+ mKeyguardDismissInteractor = keyguardDismissInteractor;
}
@Override
@@ -482,7 +484,11 @@
public void dismiss(IKeyguardDismissCallback callback, CharSequence message) {
trace("dismiss message=" + message);
checkPermission();
- mKeyguardViewMediator.dismiss(callback, message);
+ if (KeyguardWmStateRefactor.isEnabled()) {
+ mKeyguardDismissInteractor.dismissKeyguardWithCallback(callback);
+ } else {
+ mKeyguardViewMediator.dismiss(callback, message);
+ }
}
@Override // Binder interface
@@ -672,9 +678,6 @@
public void setCurrentUser(int userId) {
trace("Deprecated/NOT USED: setCurrentUser userId=" + userId);
checkPermission();
- if (!refactorGetCurrentUser()) {
- mKeyguardViewMediator.setCurrentUser(userId);
- }
}
@Override // Binder interface
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 17c5977..8c82900 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -41,7 +41,6 @@
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE;
import static com.android.systemui.DejankUtils.whitelistIpcs;
import static com.android.systemui.Flags.notifyPowerManagerUserActivityBackground;
-import static com.android.systemui.Flags.refactorGetCurrentUser;
import static com.android.systemui.Flags.relockWithPowerButtonImmediately;
import static com.android.systemui.Flags.translucentOccludingActivityFix;
import static com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel.DREAMING_ANIMATION_DURATION_MS;
@@ -626,11 +625,9 @@
@Override
public void onUserSwitching(int userId) {
- if (DEBUG) Log.d(TAG, String.format("onUserSwitching %d", userId));
+ Log.d(TAG, String.format("onUserSwitching %d", userId));
synchronized (KeyguardViewMediator.this) {
- if (refactorGetCurrentUser()) {
- notifyTrustedChangedLocked(mUpdateMonitor.getUserHasTrust(userId));
- }
+ notifyTrustedChangedLocked(mUpdateMonitor.getUserHasTrust(userId));
resetKeyguardDonePendingLocked();
dismiss(null /* callback */, null /* message */);
adjustStatusBarLocked();
@@ -639,7 +636,7 @@
@Override
public void onUserSwitchComplete(int userId) {
- if (DEBUG) Log.d(TAG, String.format("onUserSwitchComplete %d", userId));
+ Log.d(TAG, String.format("onUserSwitchComplete %d", userId));
// We are calling dismiss again and with a delay as there are race conditions
// in some scenarios caused by async layout listeners
mHandler.postDelayed(() -> dismiss(null /* callback */, null /* message */), 500);
@@ -1580,10 +1577,6 @@
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
- if (!refactorGetCurrentUser()) {
- KeyguardUpdateMonitor.setCurrentUser(mUserTracker.getUserId());
- }
-
// Assume keyguard is showing (unless it's disabled) until we know for sure, unless Keyguard
// is disabled.
if (isKeyguardServiceEnabled()) {
@@ -2546,19 +2539,6 @@
}
/**
- * Update the newUserId. Call while holding WindowManagerService lock.
- * NOTE: Should only be called by KeyguardViewMediator in response to the user id changing.
- *
- * @param newUserId The id of the incoming user.
- */
- public void setCurrentUser(int newUserId) {
- KeyguardUpdateMonitor.setCurrentUser(newUserId);
- synchronized (this) {
- notifyTrustedChangedLocked(mUpdateMonitor.getUserHasTrust(newUserId));
- }
- }
-
- /**
* This broadcast receiver should be registered with the SystemUI permission.
*/
private final BroadcastReceiver mDelayedLockBroadcastReceiver = new BroadcastReceiver() {
@@ -3553,7 +3533,7 @@
try {
mStatusBarService.disableForUser(flags, mStatusBarDisableToken,
mContext.getPackageName(),
- mSelectedUserInteractor.getSelectedUserId(true));
+ mSelectedUserInteractor.getSelectedUserId());
} catch (RemoteException e) {
Log.d(TAG, "Failed to force clear flags", e);
}
@@ -3591,7 +3571,7 @@
try {
mStatusBarService.disableForUser(flags, mStatusBarDisableToken,
mContext.getPackageName(),
- mSelectedUserInteractor.getSelectedUserId(true));
+ mSelectedUserInteractor.getSelectedUserId());
} catch (RemoteException e) {
Log.d(TAG, "Failed to set disable flags: " + flags, e);
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractor.kt
index 628e912..d7e6bdb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractor.kt
@@ -16,9 +16,13 @@
package com.android.systemui.keyguard.domain.interactor
+import com.android.internal.policy.IKeyguardDismissCallback
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.keyguard.data.repository.TrustRepository
import com.android.systemui.keyguard.shared.model.DismissAction
@@ -28,23 +32,30 @@
import com.android.systemui.util.kotlin.Utils.Companion.toQuad
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
/** Encapsulates business logic for requesting the keyguard to dismiss/finish/done. */
@SysUISingleton
class KeyguardDismissInteractor
@Inject
constructor(
- trustRepository: TrustRepository,
+ @Main private val mainDispatcher: CoroutineDispatcher,
+ @Application private val scope: CoroutineScope,
private val keyguardRepository: KeyguardRepository,
- primaryBouncerInteractor: PrimaryBouncerInteractor,
+ private val primaryBouncerInteractor: PrimaryBouncerInteractor,
+ private val selectedUserInteractor: SelectedUserInteractor,
+ private val dismissCallbackRegistry: DismissCallbackRegistry,
+ trustRepository: TrustRepository,
alternateBouncerInteractor: AlternateBouncerInteractor,
powerInteractor: PowerInteractor,
- private val selectedUserInteractor: SelectedUserInteractor,
) {
/*
* Updates when a biometric has authenticated the device and is requesting to dismiss
@@ -127,4 +138,29 @@
suspend fun setKeyguardDone(keyguardDoneTiming: KeyguardDone) {
keyguardRepository.setKeyguardDone(keyguardDoneTiming)
}
+
+ /**
+ * Dismiss the keyguard (or show the bouncer) and invoke the provided callback once dismissed.
+ *
+ * TODO(b/358412565): Support dismiss messages.
+ */
+ fun dismissKeyguardWithCallback(
+ callback: IKeyguardDismissCallback?,
+ ) {
+ scope.launch {
+ withContext(mainDispatcher) {
+ if (callback != null) {
+ dismissCallbackRegistry.addCallback(callback)
+ }
+
+ // This will either show the bouncer, or dismiss the keyguard if insecure.
+ // We currently need to request showing the primary bouncer in order to start a
+ // transition to PRIMARY_BOUNCER. Once we refactor that so that starting the
+ // transition is what causes the bouncer to show, we can remove this entire method,
+ // and simply ask KeyguardTransitionInteractor to transition to a bouncer state or
+ // dismiss keyguard.
+ primaryBouncerInteractor.show(true)
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
index 31b0bf7..d9c48fa 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionCoreStartable.kt
@@ -28,6 +28,7 @@
private val interactors: Set<TransitionInteractor>,
private val auditLogger: KeyguardTransitionAuditLogger,
private val bootInteractor: KeyguardTransitionBootInteractor,
+ private val statusBarDisableFlagsInteractor: StatusBarDisableFlagsInteractor,
) : CoreStartable {
override fun start() {
@@ -53,6 +54,7 @@
}
auditLogger.start()
bootInteractor.start()
+ statusBarDisableFlagsInteractor.start()
}
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StatusBarDisableFlagsInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StatusBarDisableFlagsInteractor.kt
new file mode 100644
index 0000000..47818cb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/StatusBarDisableFlagsInteractor.kt
@@ -0,0 +1,157 @@
+/*
+ * 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.keyguard.domain.interactor
+
+import android.annotation.SuppressLint
+import android.app.StatusBarManager
+import android.content.Context
+import android.os.Binder
+import android.os.IBinder
+import android.os.RemoteException
+import android.provider.DeviceConfig
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags
+import com.android.internal.statusbar.IStatusBarService
+import com.android.systemui.CoreStartable
+import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.deviceconfig.domain.interactor.DeviceConfigInteractor
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
+import com.android.systemui.keyguard.KeyguardWmStateRefactor
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.navigation.domain.interactor.NavigationInteractor
+import com.android.systemui.power.domain.interactor.PowerInteractor
+import com.android.systemui.power.shared.model.WakeSleepReason
+import com.android.systemui.power.shared.model.WakefulnessModel
+import com.android.systemui.user.domain.interactor.SelectedUserInteractor
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+/**
+ * Logic around StatusBarService#disableForUser, which is used to disable the home and recents
+ * button in certain device states.
+ *
+ * TODO(b/362313975): Remove post-Flexiglass, this duplicates StatusBarStartable logic.
+ */
+@SysUISingleton
+class StatusBarDisableFlagsInteractor
+@Inject
+constructor(
+ @Application private val scope: CoroutineScope,
+ @Application private val applicationContext: Context,
+ @Background private val backgroundDispatcher: CoroutineDispatcher,
+ private val deviceEntryFaceAuthInteractor: DeviceEntryFaceAuthInteractor,
+ private val statusBarService: IStatusBarService,
+ keyguardTransitionInteractor: KeyguardTransitionInteractor,
+ selectedUserInteractor: SelectedUserInteractor,
+ deviceConfigInteractor: DeviceConfigInteractor,
+ navigationInteractor: NavigationInteractor,
+ authenticationInteractor: AuthenticationInteractor,
+ powerInteractor: PowerInteractor,
+) : CoreStartable {
+
+ private val disableToken: IBinder = Binder()
+
+ private val disableFlagsForUserId =
+ combine(
+ selectedUserInteractor.selectedUser,
+ keyguardTransitionInteractor.startedKeyguardState,
+ deviceConfigInteractor.property(
+ namespace = DeviceConfig.NAMESPACE_SYSTEMUI,
+ name = SystemUiDeviceConfigFlags.NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN,
+ default = true,
+ ),
+ navigationInteractor.isGesturalMode,
+ authenticationInteractor.authenticationMethod,
+ powerInteractor.detailedWakefulness,
+ ) { values ->
+ val selectedUserId = values[0] as Int
+ val startedState = values[1] as KeyguardState
+ val isShowHomeOverLockscreen = values[2] as Boolean
+ val isGesturalMode = values[3] as Boolean
+ val authenticationMethod = values[4] as AuthenticationMethodModel
+ val wakefulnessModel = values[5] as WakefulnessModel
+ val isOccluded = startedState == KeyguardState.OCCLUDED
+
+ val hideHomeAndRecentsForBouncer =
+ startedState == KeyguardState.PRIMARY_BOUNCER ||
+ startedState == KeyguardState.ALTERNATE_BOUNCER
+ val isKeyguardShowing = startedState != KeyguardState.GONE
+ val isPowerGestureIntercepted =
+ with(wakefulnessModel) {
+ isAwake() &&
+ powerButtonLaunchGestureTriggered &&
+ lastSleepReason == WakeSleepReason.POWER_BUTTON
+ }
+
+ var flags = StatusBarManager.DISABLE_NONE
+
+ if (hideHomeAndRecentsForBouncer || (isKeyguardShowing && !isOccluded)) {
+ if (!isShowHomeOverLockscreen || !isGesturalMode) {
+ flags = flags or StatusBarManager.DISABLE_HOME
+ }
+ flags = flags or StatusBarManager.DISABLE_RECENT
+ }
+
+ if (
+ isPowerGestureIntercepted &&
+ isOccluded &&
+ authenticationMethod.isSecure &&
+ deviceEntryFaceAuthInteractor.isFaceAuthEnabledAndEnrolled()
+ ) {
+ flags = flags or StatusBarManager.DISABLE_RECENT
+ }
+
+ selectedUserId to flags
+ }
+ .distinctUntilChanged()
+
+ @SuppressLint("WrongConstant", "NonInjectedService")
+ override fun start() {
+ if (!KeyguardWmStateRefactor.isEnabled) {
+ return
+ }
+
+ scope.launch {
+ disableFlagsForUserId.collect { (selectedUserId, flags) ->
+ if (applicationContext.getSystemService(Context.STATUS_BAR_SERVICE) == null) {
+ return@collect
+ }
+
+ withContext(backgroundDispatcher) {
+ try {
+ statusBarService.disableForUser(
+ flags,
+ disableToken,
+ applicationContext.packageName,
+ selectedUserId,
+ )
+ } catch (e: RemoteException) {
+ e.printStackTrace()
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/MediaDomainModule.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/MediaDomainModule.kt
index 9c29bab..ed5080d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/MediaDomainModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/MediaDomainModule.kt
@@ -22,7 +22,7 @@
import com.android.systemui.media.controls.domain.pipeline.MediaDataManager
import com.android.systemui.media.controls.domain.pipeline.MediaDataProcessor
import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor
-import com.android.systemui.media.controls.util.MediaFlags
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
import dagger.Binds
import dagger.Module
import dagger.Provides
@@ -51,9 +51,8 @@
fun providesMediaDataManager(
legacyProvider: Provider<LegacyMediaDataManagerImpl>,
newProvider: Provider<MediaCarouselInteractor>,
- mediaFlags: MediaFlags,
): MediaDataManager {
- return if (mediaFlags.isSceneContainerEnabled()) {
+ return if (SceneContainerFlag.isEnabled) {
newProvider.get()
} else {
legacyProvider.get()
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt
index 9e2804e..916f8b2 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt
@@ -91,6 +91,7 @@
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.BcSmartspaceDataPlugin
import com.android.systemui.res.R
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.statusbar.NotificationMediaManager.isConnectingState
import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState
import com.android.systemui.statusbar.notification.row.HybridGroupManager
@@ -272,7 +273,7 @@
}
override fun start() {
- if (!mediaFlags.isSceneContainerEnabled()) {
+ if (!SceneContainerFlag.isEnabled) {
return
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt
index 9d7160c..270ab72 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt
@@ -105,7 +105,7 @@
val currentMedia: StateFlow<List<MediaCommonModel>> = mediaFilterRepository.currentMedia
override fun start() {
- if (!mediaFlags.isSceneContainerEnabled()) {
+ if (!SceneContainerFlag.isEnabled) {
return
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
index fb2bbde..19cdee7 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
@@ -220,7 +220,7 @@
private val animationScaleObserver: ContentObserver =
object : ContentObserver(executor, 0) {
override fun onChange(selfChange: Boolean) {
- if (!mediaFlags.isSceneContainerEnabled()) {
+ if (!SceneContainerFlag.isEnabled) {
MediaPlayerData.players().forEach { it.updateAnimatorDurationScale() }
} else {
controllerById.values.forEach { it.updateAnimatorDurationScale() }
@@ -350,7 +350,7 @@
inflateSettingsButton()
mediaContent = mediaCarousel.requireViewById(R.id.media_carousel)
configurationController.addCallback(configListener)
- if (!mediaFlags.isSceneContainerEnabled()) {
+ if (!SceneContainerFlag.isEnabled) {
setUpListeners()
} else {
val visualStabilityCallback = OnReorderingAllowedListener {
@@ -391,7 +391,7 @@
listenForAnyStateToGoneKeyguardTransition(this)
listenForAnyStateToLockscreenTransition(this)
- if (!mediaFlags.isSceneContainerEnabled()) return@repeatOnLifecycle
+ if (!SceneContainerFlag.isEnabled) return@repeatOnLifecycle
listenForMediaItemsChanges(this)
}
}
@@ -733,7 +733,7 @@
when (commonViewModel) {
is MediaCommonViewModel.MediaControl -> {
val viewHolder = MediaViewHolder.create(LayoutInflater.from(context), mediaContent)
- if (mediaFlags.isSceneContainerEnabled()) {
+ if (SceneContainerFlag.isEnabled) {
viewController.widthInSceneContainerPx = widthInSceneContainerPx
viewController.heightInSceneContainerPx = heightInSceneContainerPx
}
@@ -965,7 +965,7 @@
.elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex)
if (existingPlayer == null) {
val newPlayer = mediaControlPanelFactory.get()
- if (mediaFlags.isSceneContainerEnabled()) {
+ if (SceneContainerFlag.isEnabled) {
newPlayer.mediaViewController.widthInSceneContainerPx = widthInSceneContainerPx
newPlayer.mediaViewController.heightInSceneContainerPx =
heightInSceneContainerPx
@@ -1140,7 +1140,7 @@
}
private fun updatePlayers(recreateMedia: Boolean) {
- if (mediaFlags.isSceneContainerEnabled()) {
+ if (SceneContainerFlag.isEnabled) {
updateMediaPlayers(recreateMedia)
return
}
@@ -1240,7 +1240,7 @@
currentStartLocation = startLocation
currentEndLocation = endLocation
currentTransitionProgress = progress
- if (!mediaFlags.isSceneContainerEnabled()) {
+ if (!SceneContainerFlag.isEnabled) {
for (mediaPlayer in MediaPlayerData.players()) {
updateViewControllerToState(mediaPlayer.mediaViewController, immediately)
}
@@ -1300,7 +1300,7 @@
/** Update listening to seekbar. */
private fun updateSeekbarListening(visibleToUser: Boolean) {
- if (!mediaFlags.isSceneContainerEnabled()) {
+ if (!SceneContainerFlag.isEnabled) {
for (player in MediaPlayerData.players()) {
player.setListening(visibleToUser && currentlyExpanded)
}
@@ -1313,7 +1313,7 @@
private fun updateCarouselDimensions() {
var width = 0
var height = 0
- if (!mediaFlags.isSceneContainerEnabled()) {
+ if (!SceneContainerFlag.isEnabled) {
for (mediaPlayer in MediaPlayerData.players()) {
val controller = mediaPlayer.mediaViewController
// When transitioning the view to gone, the view gets smaller, but the translation
@@ -1405,7 +1405,7 @@
!mediaManager.hasActiveMediaOrRecommendation() &&
desiredHostState.showsOnlyActiveMedia
- if (!mediaFlags.isSceneContainerEnabled()) {
+ if (!SceneContainerFlag.isEnabled) {
for (mediaPlayer in MediaPlayerData.players()) {
if (animate) {
mediaPlayer.mediaViewController.animatePendingStateChange(
@@ -1445,7 +1445,7 @@
}
fun closeGuts(immediate: Boolean = true) {
- if (!mediaFlags.isSceneContainerEnabled()) {
+ if (!SceneContainerFlag.isEnabled) {
MediaPlayerData.players().forEach { it.closeGuts(immediate) }
} else {
controllerById.values.forEach { it.closeGuts(immediate) }
@@ -1596,7 +1596,7 @@
@VisibleForTesting
fun onSwipeToDismiss() {
- if (mediaFlags.isSceneContainerEnabled()) {
+ if (SceneContainerFlag.isEnabled) {
mediaCarouselViewModel.onSwipeToDismiss(currentEndLocation)
return
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
index addb014..87610cf 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
@@ -111,7 +111,6 @@
import com.android.systemui.media.controls.ui.view.RecommendationViewHolder;
import com.android.systemui.media.controls.ui.viewmodel.SeekBarViewModel;
import com.android.systemui.media.controls.util.MediaDataUtils;
-import com.android.systemui.media.controls.util.MediaFlags;
import com.android.systemui.media.controls.util.MediaUiEventLogger;
import com.android.systemui.media.controls.util.SmallHash;
import com.android.systemui.media.dialog.MediaOutputDialogManager;
@@ -120,6 +119,7 @@
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.res.R;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -209,7 +209,6 @@
static final long TURBULENCE_NOISE_PLAY_DURATION = 7500L;
private final SeekBarViewModel mSeekBarViewModel;
- private final MediaFlags mMediaFlags;
private final CommunalSceneInteractor mCommunalSceneInteractor;
private SeekBarObserver mSeekBarObserver;
protected final Executor mBackgroundExecutor;
@@ -323,8 +322,7 @@
CommunalSceneInteractor communalSceneInteractor,
NotificationLockscreenUserManager lockscreenUserManager,
BroadcastDialogController broadcastDialogController,
- GlobalSettings globalSettings,
- MediaFlags mediaFlags
+ GlobalSettings globalSettings
) {
mContext = context;
mBackgroundExecutor = backgroundExecutor;
@@ -343,7 +341,6 @@
mActivityIntentHelper = activityIntentHelper;
mLockscreenUserManager = lockscreenUserManager;
mBroadcastDialogController = broadcastDialogController;
- mMediaFlags = mediaFlags;
mCommunalSceneInteractor = communalSceneInteractor;
mSeekBarViewModel.setLogSeek(() -> {
@@ -641,7 +638,7 @@
// State refresh interferes with the translation animation, only run it if it's not running.
if (!mMetadataAnimationHandler.isRunning()) {
// Don't refresh in scene framework, because it will calculate with invalid layout sizes
- if (!mMediaFlags.isSceneContainerEnabled()) {
+ if (!SceneContainerFlag.isEnabled()) {
mMediaViewController.refreshState();
}
}
@@ -909,7 +906,7 @@
// Capture width & height from views in foreground for artwork scaling in background
int width = mMediaViewHolder.getAlbumView().getMeasuredWidth();
int height = mMediaViewHolder.getAlbumView().getMeasuredHeight();
- if (mMediaFlags.isSceneContainerEnabled() && (width <= 0 || height <= 0)) {
+ if (SceneContainerFlag.isEnabled() && (width <= 0 || height <= 0)) {
// TODO(b/312714128): ensure we have a valid size before setting background
width = mMediaViewController.getWidthInSceneContainerPx();
height = mMediaViewController.getHeightInSceneContainerPx();
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
index 091b886..a9d2a54 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt
@@ -46,10 +46,10 @@
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.media.controls.domain.pipeline.MediaDataManager
import com.android.systemui.media.controls.ui.view.MediaHost
-import com.android.systemui.media.controls.util.MediaFlags
import com.android.systemui.media.dream.MediaDreamComplication
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.res.R
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.CrossFadeHelper
import com.android.systemui.statusbar.StatusBarState
@@ -119,7 +119,6 @@
@Application private val coroutineScope: CoroutineScope,
private val splitShadeStateController: SplitShadeStateController,
private val logger: MediaViewLogger,
- private val mediaFlags: MediaFlags,
) {
/** Track the media player setting status on lock screen. */
@@ -1111,7 +1110,7 @@
private fun updateHostAttachment() =
traceSection("MediaHierarchyManager#updateHostAttachment") {
- if (mediaFlags.isSceneContainerEnabled()) {
+ if (SceneContainerFlag.isEnabled) {
// No need to manage transition states - just update the desired location directly
logger.logMediaHostAttachment(desiredLocation)
mediaCarouselController.onDesiredLocationChanged(
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt
index 584908f..e57de09 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt
@@ -46,8 +46,8 @@
import com.android.systemui.media.controls.ui.view.RecommendationViewHolder
import com.android.systemui.media.controls.ui.viewmodel.MediaControlViewModel
import com.android.systemui.media.controls.ui.viewmodel.SeekBarViewModel
-import com.android.systemui.media.controls.util.MediaFlags
import com.android.systemui.res.R
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.surfaceeffects.PaintDrawCallback
import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect
@@ -82,7 +82,6 @@
private val logger: MediaViewLogger,
private val seekBarViewModel: SeekBarViewModel,
@Main private val mainExecutor: DelayableExecutor,
- private val mediaFlags: MediaFlags,
private val globalSettings: GlobalSettings,
) {
@@ -125,7 +124,7 @@
set(value) {
if (field != value) {
field = value
- if (!mediaFlags.isSceneContainerEnabled()) return
+ if (!SceneContainerFlag.isEnabled) return
locationChangeListener(value)
}
}
@@ -212,7 +211,7 @@
private val scrubbingChangeListener =
object : SeekBarViewModel.ScrubbingChangeListener {
override fun onScrubbingChanged(scrubbing: Boolean) {
- if (!mediaFlags.isSceneContainerEnabled()) return
+ if (!SceneContainerFlag.isEnabled) return
if (isScrubbing == scrubbing) return
isScrubbing = scrubbing
updateDisplayForScrubbingChange()
@@ -222,7 +221,7 @@
private val enabledChangeListener =
object : SeekBarViewModel.EnabledChangeListener {
override fun onEnabledChanged(enabled: Boolean) {
- if (!mediaFlags.isSceneContainerEnabled()) return
+ if (!SceneContainerFlag.isEnabled) return
if (isSeekBarEnabled == enabled) return
isSeekBarEnabled = enabled
MediaControlViewBinder.updateSeekBarVisibility(expandedLayout, isSeekBarEnabled)
@@ -238,7 +237,7 @@
* @param listening True when player should be active. Otherwise, false.
*/
fun setListening(listening: Boolean) {
- if (!mediaFlags.isSceneContainerEnabled()) return
+ if (!SceneContainerFlag.isEnabled) return
seekBarViewModel.listening = listening
}
@@ -272,7 +271,7 @@
)
)
}
- if (mediaFlags.isSceneContainerEnabled()) {
+ if (SceneContainerFlag.isEnabled) {
if (
this@MediaViewController::recsConfigurationChangeListener.isInitialized
) {
@@ -344,7 +343,7 @@
* Notify this controller that the view has been removed and all listeners should be destroyed
*/
fun onDestroy() {
- if (mediaFlags.isSceneContainerEnabled()) {
+ if (SceneContainerFlag.isEnabled) {
if (this::seekBarObserver.isInitialized) {
seekBarViewModel.progress.removeObserver(seekBarObserver)
}
@@ -565,7 +564,7 @@
state: MediaHostState?,
isGutsAnimation: Boolean = false
): TransitionViewState? {
- if (mediaFlags.isSceneContainerEnabled()) {
+ if (SceneContainerFlag.isEnabled) {
return obtainSceneContainerViewState()
}
@@ -667,7 +666,7 @@
}
fun attachPlayer(mediaViewHolder: MediaViewHolder) {
- if (!mediaFlags.isSceneContainerEnabled()) return
+ if (!SceneContainerFlag.isEnabled) return
this.mediaViewHolder = mediaViewHolder
// Setting up seek bar.
@@ -741,7 +740,7 @@
}
fun updateAnimatorDurationScale() {
- if (!mediaFlags.isSceneContainerEnabled()) return
+ if (!SceneContainerFlag.isEnabled) return
if (this::seekBarObserver.isInitialized) {
seekBarObserver.animationEnabled =
globalSettings.getFloat(Settings.Global.ANIMATOR_DURATION_SCALE, 1f) > 0f
@@ -801,7 +800,7 @@
}
fun attachRecommendations(recommendationViewHolder: RecommendationViewHolder) {
- if (!mediaFlags.isSceneContainerEnabled()) return
+ if (!SceneContainerFlag.isEnabled) return
this.recommendationViewHolder = recommendationViewHolder
attach(recommendationViewHolder.recommendations, TYPE.RECOMMENDATION)
@@ -810,13 +809,13 @@
}
fun bindSeekBar(onSeek: () -> Unit, onBindSeekBar: (SeekBarViewModel) -> Unit) {
- if (!mediaFlags.isSceneContainerEnabled()) return
+ if (!SceneContainerFlag.isEnabled) return
seekBarViewModel.logSeek = onSeek
onBindSeekBar(seekBarViewModel)
}
fun setUpTurbulenceNoise() {
- if (!mediaFlags.isSceneContainerEnabled()) return
+ if (!SceneContainerFlag.isEnabled) return
mediaViewHolder!!.let {
if (!this::turbulenceNoiseAnimationConfig.isInitialized) {
turbulenceNoiseAnimationConfig =
@@ -1049,7 +1048,7 @@
*/
private fun obtainViewStateForLocation(@MediaLocation location: Int): TransitionViewState? {
val mediaHostState = mediaHostStatesManager.mediaHostStates[location] ?: return null
- if (mediaFlags.isSceneContainerEnabled()) {
+ if (SceneContainerFlag.isEnabled) {
return obtainSceneContainerViewState()
}
@@ -1080,7 +1079,7 @@
/** Clear all existing measurements and refresh the state to match the view. */
fun refreshState() =
traceSection("MediaViewController#refreshState") {
- if (mediaFlags.isSceneContainerEnabled()) {
+ if (SceneContainerFlag.isEnabled) {
// We don't need to recreate measurements for scene container, since it's a known
// size. Just get the view state and update the layout controller
obtainSceneContainerViewState()?.let {
@@ -1169,13 +1168,13 @@
}
fun setUpPrevButtonInfo(isAvailable: Boolean, notVisibleValue: Int = ConstraintSet.GONE) {
- if (!mediaFlags.isSceneContainerEnabled()) return
+ if (!SceneContainerFlag.isEnabled) return
isPrevButtonAvailable = isAvailable
prevNotVisibleValue = notVisibleValue
}
fun setUpNextButtonInfo(isAvailable: Boolean, notVisibleValue: Int = ConstraintSet.GONE) {
- if (!mediaFlags.isSceneContainerEnabled()) return
+ if (!SceneContainerFlag.isEnabled) return
isNextButtonAvailable = isAvailable
nextNotVisibleValue = notVisibleValue
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
index 21c3111..a65243d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
@@ -21,7 +21,6 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.flags.FeatureFlagsClassic
import com.android.systemui.flags.Flags
-import com.android.systemui.scene.shared.flag.SceneContainerFlag
import javax.inject.Inject
@SysUISingleton
@@ -49,7 +48,4 @@
/** Check whether we allow remote media to generate resume controls */
fun isRemoteResumeAllowed() = featureFlags.isEnabled(Flags.MEDIA_REMOTE_RESUME)
-
- /** Check whether to use scene framework */
- fun isSceneContainerEnabled() = SceneContainerFlag.isEnabled
}
diff --git a/packages/SystemUI/src/com/android/systemui/model/SceneContainerPlugin.kt b/packages/SystemUI/src/com/android/systemui/model/SceneContainerPlugin.kt
index 42f66cc..7d2a1e1 100644
--- a/packages/SystemUI/src/com/android/systemui/model/SceneContainerPlugin.kt
+++ b/packages/SystemUI/src/com/android/systemui/model/SceneContainerPlugin.kt
@@ -18,7 +18,6 @@
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.SceneKey
-import com.android.systemui.Flags.glanceableHubBackGesture
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.scene.domain.interactor.SceneContainerOcclusionInteractor
import com.android.systemui.scene.domain.interactor.SceneInteractor
@@ -107,10 +106,7 @@
{
it.scene == Scenes.Lockscreen && it.invisibleDueToOcclusion
},
- SYSUI_STATE_COMMUNAL_HUB_SHOWING to
- {
- glanceableHubBackGesture() && it.scene == Scenes.Communal
- }
+ SYSUI_STATE_COMMUNAL_HUB_SHOWING to { it.scene == Scenes.Communal }
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
index ac878c2..6f82d5d 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
@@ -19,19 +19,24 @@
import static android.app.StatusBarManager.WINDOW_NAVIGATION_BAR;
import static android.app.StatusBarManager.WindowVisibleState;
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
+import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR;
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_NAVIGATION_BARS;
import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
+import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.DEFAULT;
+import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.GESTURE;
+import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE;
import static com.android.systemui.accessibility.SystemActions.SYSTEM_ACTION_ID_ACCESSIBILITY_BUTTON;
import static com.android.systemui.accessibility.SystemActions.SYSTEM_ACTION_ID_ACCESSIBILITY_BUTTON_CHOOSER;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
import static com.android.systemui.shared.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
import static com.android.systemui.shared.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
import static com.android.systemui.shared.statusbar.phone.BarTransitions.MODE_OPAQUE;
import static com.android.systemui.shared.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
import static com.android.systemui.shared.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
import android.content.ContentResolver;
import android.content.Context;
@@ -60,10 +65,11 @@
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
-import com.android.internal.accessibility.common.ShortcutConstants;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dumpable;
import com.android.systemui.accessibility.AccessibilityButtonModeObserver;
import com.android.systemui.accessibility.AccessibilityButtonTargetsObserver;
+import com.android.systemui.accessibility.AccessibilityGestureTargetsObserver;
import com.android.systemui.accessibility.SystemActions;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.dagger.SysUISingleton;
@@ -107,6 +113,7 @@
AccessibilityManager.AccessibilityServicesStateChangeListener,
AccessibilityButtonModeObserver.ModeChangedListener,
AccessibilityButtonTargetsObserver.TargetsChangedListener,
+ AccessibilityGestureTargetsObserver.TargetsChangedListener,
OverviewProxyService.OverviewProxyListener, NavigationModeController.ModeChangedListener,
Dumpable, CommandQueue.Callbacks, ConfigurationController.ConfigurationListener {
private static final String TAG = NavBarHelper.class.getSimpleName();
@@ -122,6 +129,7 @@
private final SystemActions mSystemActions;
private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver;
private final AccessibilityButtonTargetsObserver mAccessibilityButtonTargetsObserver;
+ private final AccessibilityGestureTargetsObserver mAccessibilityGestureTargetsObserver;
private final List<NavbarTaskbarStateUpdater> mStateListeners = new ArrayList<>();
private final Context mContext;
private final NotificationShadeWindowController mNotificationShadeWindowController;
@@ -188,6 +196,7 @@
public NavBarHelper(Context context, AccessibilityManager accessibilityManager,
AccessibilityButtonModeObserver accessibilityButtonModeObserver,
AccessibilityButtonTargetsObserver accessibilityButtonTargetsObserver,
+ AccessibilityGestureTargetsObserver accessibilityGestureTargetsObserver,
SystemActions systemActions,
OverviewProxyService overviewProxyService,
Lazy<AssistManager> assistManagerLazy,
@@ -220,6 +229,7 @@
mSystemActions = systemActions;
mAccessibilityButtonModeObserver = accessibilityButtonModeObserver;
mAccessibilityButtonTargetsObserver = accessibilityButtonTargetsObserver;
+ mAccessibilityGestureTargetsObserver = accessibilityGestureTargetsObserver;
mWm = wm;
mDefaultDisplayId = displayTracker.getDefaultDisplayId();
mEdgeBackGestureHandler = edgeBackGestureHandlerFactory.create(context);
@@ -249,6 +259,7 @@
mAccessibilityManager.addAccessibilityServicesStateChangeListener(this);
mAccessibilityButtonModeObserver.addListener(this);
mAccessibilityButtonTargetsObserver.addListener(this);
+ mAccessibilityGestureTargetsObserver.addListener(this);
// Setup assistant listener
mContentResolver.registerContentObserver(
@@ -291,6 +302,7 @@
mAccessibilityManager.removeAccessibilityServicesStateChangeListener(this);
mAccessibilityButtonModeObserver.removeListener(this);
mAccessibilityButtonTargetsObserver.removeListener(this);
+ mAccessibilityGestureTargetsObserver.removeListener(this);
// Clean up assistant listeners
mContentResolver.unregisterContentObserver(mAssistContentObserver);
@@ -380,43 +392,50 @@
}
@Override
+ public void onAccessibilityGestureTargetsChanged(String targets) {
+ updateA11yState();
+ }
+
+ @Override
public void onConfigChanged(Configuration newConfig) {
mEdgeBackGestureHandler.onConfigurationChanged(newConfig);
}
+ private int getNumOfA11yShortcutTargetsForNavSystem() {
+ final int buttonMode = mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode();
+ final int shortcutType;
+ if (!android.provider.Flags.a11yStandaloneGestureEnabled()) {
+ shortcutType = buttonMode
+ != ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU ? SOFTWARE : DEFAULT;
+ // If accessibility button is floating menu mode, there are no clickable targets.
+ } else {
+ if (mNavBarMode == NAV_BAR_MODE_GESTURAL) {
+ shortcutType = GESTURE;
+ } else {
+ shortcutType = buttonMode == ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR
+ ? SOFTWARE : DEFAULT;
+ }
+ }
+ return mAccessibilityManager.getAccessibilityShortcutTargets(shortcutType).size();
+ }
+
/**
* Updates the current accessibility button state. The accessibility button state is only
* used for {@link Secure#ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR} and
* {@link Secure#ACCESSIBILITY_BUTTON_MODE_GESTURE}, otherwise it is reset to 0.
*/
- private void updateA11yState() {
+ @VisibleForTesting
+ void updateA11yState() {
final long prevState = mA11yButtonState;
final boolean clickable;
final boolean longClickable;
- if (mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode()
- == ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU) {
- // If accessibility button is floating menu mode, click and long click state should be
- // disabled.
- clickable = false;
- longClickable = false;
- mA11yButtonState = 0;
- } else {
- // AccessibilityManagerService resolves services for the current user since the local
- // AccessibilityManager is created from a Context with the INTERACT_ACROSS_USERS
- // permission
- final List<String> a11yButtonTargets =
- mAccessibilityManager.getAccessibilityShortcutTargets(
- ShortcutConstants.UserShortcutType.SOFTWARE);
- final int requestingServices = a11yButtonTargets.size();
-
- clickable = requestingServices >= 1;
-
- // `longClickable` is used to determine whether to pop up the accessibility chooser
- // dialog or not, and it’s also only for multiple services.
- longClickable = requestingServices >= 2;
- mA11yButtonState = (clickable ? SYSUI_STATE_A11Y_BUTTON_CLICKABLE : 0)
- | (longClickable ? SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE : 0);
- }
+ int clickableServices = getNumOfA11yShortcutTargetsForNavSystem();
+ clickable = clickableServices >= 1;
+ // `longClickable` is used to determine whether to pop up the accessibility chooser
+ // dialog or not, and it’s also only for multiple services.
+ longClickable = clickableServices >= 2;
+ mA11yButtonState = (clickable ? SYSUI_STATE_A11Y_BUTTON_CLICKABLE : 0)
+ | (longClickable ? SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE : 0);
// Update the system actions if the state has changed
if (prevState != mA11yButtonState) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
index 8887f58..9abc494 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java
@@ -71,6 +71,7 @@
import com.android.systemui.qs.logging.QSLogger;
import java.io.PrintWriter;
+import java.util.Objects;
/**
* Base quick-settings tile, extend this to create a new tile.
@@ -350,6 +351,7 @@
public void userSwitch(int newUserId) {
mHandler.obtainMessage(H.USER_SWITCH, newUserId, 0).sendToTarget();
+ postStale();
}
public void destroy() {
@@ -667,6 +669,18 @@
public String toString() {
return "DrawableIcon";
}
+
+ @Override
+ public boolean equals(@Nullable Object other) {
+ // No need to compare equality of the mInvisibleDrawable as that's generated from
+ // mDrawable's constant state.
+ return other instanceof DrawableIcon && ((DrawableIcon) other).mDrawable == mDrawable;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mDrawable);
+ }
}
public static class DrawableIconWithRes extends DrawableIcon {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index ecf816b..fe5cbb1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -26,7 +26,6 @@
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
import static com.android.internal.accessibility.common.ShortcutConstants.CHOOSER_PACKAGE_NAME;
-import static com.android.systemui.Flags.glanceableHubBackGesture;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNFOLD_ANIMATION_FORWARDER;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER;
@@ -86,10 +85,10 @@
import com.android.internal.util.ScreenshotRequest;
import com.android.systemui.Dumpable;
import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.contextualeducation.GestureType;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.contextualeducation.GestureType;
import com.android.systemui.education.domain.interactor.KeyboardTouchpadEduStatsInteractor;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
import com.android.systemui.keyguard.KeyguardWmStateRefactor;
@@ -231,7 +230,7 @@
// If scene framework is enabled, set the scene container window to
// visible and let the touch "slip" into that window.
if (SceneContainerFlag.isEnabled()) {
- mSceneInteractor.get().onRemoteUserInteractionStarted("launcher swipe");
+ mSceneInteractor.get().onRemoteUserInputStarted("launcher swipe");
} else {
mShadeViewControllerLazy.get().startInputFocusTransfer();
}
@@ -267,7 +266,7 @@
if (SceneContainerFlag.isEnabled()) {
int action = event.getActionMasked();
if (action == ACTION_DOWN) {
- mSceneInteractor.get().onRemoteUserInteractionStarted(
+ mSceneInteractor.get().onRemoteUserInputStarted(
"trackpad swipe");
} else if (action == ACTION_UP) {
mSceneInteractor.get().changeScene(
@@ -837,8 +836,7 @@
.setFlag(SYSUI_STATE_BOUNCER_SHOWING, bouncerShowing)
.setFlag(SYSUI_STATE_DEVICE_DOZING, isDozing)
.setFlag(SYSUI_STATE_DEVICE_DREAMING, isDreaming)
- .setFlag(SYSUI_STATE_COMMUNAL_HUB_SHOWING,
- glanceableHubBackGesture() && communalShowing)
+ .setFlag(SYSUI_STATE_COMMUNAL_HUB_SHOWING, communalShowing)
.commitUpdate(mContext.getDisplayId());
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt b/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
index 3e2c630..beb6816 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
@@ -56,7 +56,10 @@
*
* For more information see the logic in `SceneInteractor` that mutates this.
*/
- val isRemoteUserInteractionOngoing = MutableStateFlow(false)
+ val isRemoteUserInputOngoing = MutableStateFlow(false)
+
+ /** Whether there's ongoing user input on the scene container Composable hierarchy */
+ val isSceneContainerUserInputOngoing = MutableStateFlow(false)
private val defaultTransitionState = ObservableTransitionState.Idle(config.initialSceneKey)
private val _transitionState = MutableStateFlow<Flow<ObservableTransitionState>?>(null)
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
index 1b9c346..4c404e2 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
@@ -148,11 +148,11 @@
val isVisible: StateFlow<Boolean> =
combine(
repository.isVisible,
- repository.isRemoteUserInteractionOngoing,
+ repository.isRemoteUserInputOngoing,
) { isVisible, isRemoteUserInteractionOngoing ->
isVisibleInternal(
raw = isVisible,
- isRemoteUserInteractionOngoing = isRemoteUserInteractionOngoing,
+ isRemoteUserInputOngoing = isRemoteUserInteractionOngoing,
)
}
.stateIn(
@@ -162,8 +162,13 @@
)
/** Whether there's an ongoing remotely-initiated user interaction. */
- val isRemoteUserInteractionOngoing: StateFlow<Boolean> =
- repository.isRemoteUserInteractionOngoing
+ val isRemoteUserInteractionOngoing: StateFlow<Boolean> = repository.isRemoteUserInputOngoing
+
+ /**
+ * Whether there's an ongoing user interaction started in the scene container Compose hierarchy.
+ */
+ val isSceneContainerUserInputOngoing: StateFlow<Boolean> =
+ repository.isSceneContainerUserInputOngoing
/**
* The amount of transition into or out of the given [scene].
@@ -284,7 +289,7 @@
* Please do not call this from outside of the scene framework. If you are trying to force the
* visibility to visible or invisible, prefer making changes to the existing caller of this
* method or to upstream state used to calculate [isVisible]; for an example of the latter,
- * please see [onRemoteUserInteractionStarted] and [onUserInteractionFinished].
+ * please see [onRemoteUserInputStarted] and [onUserInputFinished].
*/
fun setVisible(isVisible: Boolean, loggingReason: String) {
val wasVisible = repository.isVisible.value
@@ -301,6 +306,16 @@
}
/**
+ * Notifies that a scene container user interaction has begun.
+ *
+ * This is a user interaction that originates within the Composable hierarchy of the scene
+ * container.
+ */
+ fun onSceneContainerUserInputStarted() {
+ repository.isSceneContainerUserInputOngoing.value = true
+ }
+
+ /**
* Notifies that a remote user interaction has begun.
*
* This is a user interaction that originates outside of the UI of the scene container and
@@ -311,18 +326,19 @@
* then rerouted by window manager to System UI. While the user interaction definitely continues
* within the System UI process and code, it also originates remotely.
*/
- fun onRemoteUserInteractionStarted(loggingReason: String) {
- logger.logRemoteUserInteractionStarted(loggingReason)
- repository.isRemoteUserInteractionOngoing.value = true
+ fun onRemoteUserInputStarted(loggingReason: String) {
+ logger.logRemoteUserInputStarted(loggingReason)
+ repository.isRemoteUserInputOngoing.value = true
}
/**
* Notifies that the current user interaction (internally or remotely started, see
- * [onRemoteUserInteractionStarted]) has finished.
+ * [onSceneContainerUserInputStarted] and [onRemoteUserInputStarted]) has finished.
*/
- fun onUserInteractionFinished() {
- logger.logUserInteractionFinished()
- repository.isRemoteUserInteractionOngoing.value = false
+ fun onUserInputFinished() {
+ logger.logUserInputFinished()
+ repository.isSceneContainerUserInputOngoing.value = false
+ repository.isRemoteUserInputOngoing.value = false
}
/**
@@ -351,9 +367,9 @@
private fun isVisibleInternal(
raw: Boolean = repository.isVisible.value,
- isRemoteUserInteractionOngoing: Boolean = repository.isRemoteUserInteractionOngoing.value,
+ isRemoteUserInputOngoing: Boolean = repository.isRemoteUserInputOngoing.value,
): Boolean {
- return raw || isRemoteUserInteractionOngoing
+ return raw || isRemoteUserInputOngoing
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/StatusBarStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/StatusBarStartable.kt
index 893f030..d741368 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/StatusBarStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/StatusBarStartable.kt
@@ -166,7 +166,7 @@
StatusBarManager.DISABLE_NONE,
disableToken,
applicationContext.packageName,
- selectedUserInteractor.getSelectedUserId(true),
+ selectedUserInteractor.getSelectedUserId(),
)
} catch (e: RemoteException) {
Log.d(TAG, "Failed to clear flags", e)
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
index 94c94e2..045a887 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
@@ -115,7 +115,7 @@
)
}
- fun logRemoteUserInteractionStarted(
+ fun logRemoteUserInputStarted(
reason: String,
) {
logBuffer.log(
@@ -126,7 +126,7 @@
)
}
- fun logUserInteractionFinished() {
+ fun logUserInputFinished() {
logBuffer.log(
tag = TAG,
level = LogLevel.INFO,
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
index 9dfb745..8b4b77f 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
@@ -31,6 +31,7 @@
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.logger.SceneLogger
import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.statusbar.notification.stack.ui.view.SharedNotificationContainer
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@@ -97,7 +98,9 @@
}
/**
- * Notifies that a [MotionEvent] is first seen at the top of the scene container UI.
+ * Notifies that a [MotionEvent] is first seen at the top of the scene container UI. This
+ * includes gestures on [SharedNotificationContainer] as well as the Composable scene container
+ * hierarchy.
*
* Call this before the [MotionEvent] starts to propagate through the UI hierarchy.
*/
@@ -108,11 +111,21 @@
event.actionMasked == MotionEvent.ACTION_UP ||
event.actionMasked == MotionEvent.ACTION_CANCEL
) {
- sceneInteractor.onUserInteractionFinished()
+ sceneInteractor.onUserInputFinished()
}
}
/**
+ * Notifies that a scene container user interaction has begun.
+ *
+ * This is a user interaction that has reached the Composable hierarchy of the scene container,
+ * rather than being handled by [SharedNotificationContainer].
+ */
+ fun onSceneContainerUserInputStarted() {
+ sceneInteractor.onSceneContainerUserInputStarted()
+ }
+
+ /**
* Notifies that a [MotionEvent] that was previously sent to [onMotionEvent] has passed through
* the scene container UI.
*
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
index 0a1f649..ed590c3 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
@@ -36,6 +36,13 @@
import com.android.systemui.flags.FeatureFlagsClassic
import com.android.systemui.flags.Flags
import com.android.systemui.util.Assert
+import java.io.PrintWriter
+import java.lang.ref.WeakReference
+import java.util.concurrent.CountDownLatch
+import java.util.concurrent.Executor
+import javax.inject.Provider
+import kotlin.properties.ReadWriteProperty
+import kotlin.reflect.KProperty
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
@@ -44,30 +51,23 @@
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
-import java.io.PrintWriter
-import java.lang.ref.WeakReference
-import java.util.concurrent.CountDownLatch
-import java.util.concurrent.Executor
-import javax.inject.Provider
-import kotlin.properties.ReadWriteProperty
-import kotlin.reflect.KProperty
/**
* SystemUI cache for keeping track of the current user and associated values.
*
- * The values provided asynchronously are NOT copies, but shared among all requesters. Do not
- * modify them.
+ * The values provided asynchronously are NOT copies, but shared among all requesters. Do not modify
+ * them.
*
* This class purposefully doesn't use [BroadcastDispatcher] in order to receive the broadcast as
- * soon as possible (and reduce its dependency graph).
- * Other classes that want to listen to the broadcasts listened here SHOULD
- * subscribe to this class instead.
+ * soon as possible (and reduce its dependency graph). Other classes that want to listen to the
+ * broadcasts listened here SHOULD subscribe to this class instead.
*
* @see UserTracker
*
* Class constructed and initialized in [SettingsModule].
*/
-open class UserTrackerImpl internal constructor(
+open class UserTrackerImpl
+internal constructor(
private val context: Context,
private val featureFlagsProvider: Provider<FeatureFlagsClassic>,
private val userManager: UserManager,
@@ -87,8 +87,8 @@
private set
private val mutex = Any()
- private val isBackgroundUserSwitchEnabled: Boolean get() =
- featureFlagsProvider.get().isEnabled(Flags.USER_TRACKER_BACKGROUND_CALLBACKS)
+ private val isBackgroundUserSwitchEnabled: Boolean
+ get() = featureFlagsProvider.get().isEnabled(Flags.USER_TRACKER_BACKGROUND_CALLBACKS)
@Deprecated("Use UserInteractor.getSelectedUserId()")
override var userId: Int by SynchronizedDelegate(context.userId)
@@ -118,8 +118,7 @@
override var userProfiles: List<UserInfo> by SynchronizedDelegate(emptyList())
protected set
- @GuardedBy("callbacks")
- private val callbacks: MutableList<DataItem> = ArrayList()
+ @GuardedBy("callbacks") private val callbacks: MutableList<DataItem> = ArrayList()
private var userSwitchingJob: Job? = null
private var afterUserSwitchingJob: Job? = null
@@ -128,23 +127,25 @@
if (initialized) {
return
}
+ Log.i(TAG, "Starting user: $startingUser")
initialized = true
setUserIdInternal(startingUser)
- val filter = IntentFilter().apply {
- addAction(Intent.ACTION_LOCALE_CHANGED)
- addAction(Intent.ACTION_USER_INFO_CHANGED)
- addAction(Intent.ACTION_PROFILE_ADDED)
- addAction(Intent.ACTION_PROFILE_REMOVED)
- addAction(Intent.ACTION_PROFILE_AVAILABLE)
- addAction(Intent.ACTION_PROFILE_UNAVAILABLE)
- // These get called when a managed profile goes in or out of quiet mode.
- addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE)
- addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)
- addAction(Intent.ACTION_MANAGED_PROFILE_ADDED)
- addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED)
- addAction(Intent.ACTION_MANAGED_PROFILE_UNLOCKED)
- }
+ val filter =
+ IntentFilter().apply {
+ addAction(Intent.ACTION_LOCALE_CHANGED)
+ addAction(Intent.ACTION_USER_INFO_CHANGED)
+ addAction(Intent.ACTION_PROFILE_ADDED)
+ addAction(Intent.ACTION_PROFILE_REMOVED)
+ addAction(Intent.ACTION_PROFILE_AVAILABLE)
+ addAction(Intent.ACTION_PROFILE_UNAVAILABLE)
+ // These get called when a managed profile goes in or out of quiet mode.
+ addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE)
+ addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)
+ addAction(Intent.ACTION_MANAGED_PROFILE_ADDED)
+ addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED)
+ addAction(Intent.ACTION_MANAGED_PROFILE_UNLOCKED)
+ }
context.registerReceiverForAllUsers(this, filter, null, backgroundHandler)
registerUserSwitchObserver()
@@ -191,36 +192,39 @@
}
private fun registerUserSwitchObserver() {
- iActivityManager.registerUserSwitchObserver(object : UserSwitchObserver() {
- override fun onBeforeUserSwitching(newUserId: Int) {
- handleBeforeUserSwitching(newUserId)
- }
-
- override fun onUserSwitching(newUserId: Int, reply: IRemoteCallback?) {
- if (isBackgroundUserSwitchEnabled) {
- userSwitchingJob?.cancel()
- userSwitchingJob = appScope.launch(backgroundContext) {
- handleUserSwitchingCoroutines(newUserId) {
- reply?.sendResult(null)
- }
- }
- } else {
- handleUserSwitching(newUserId)
- reply?.sendResult(null)
+ iActivityManager.registerUserSwitchObserver(
+ object : UserSwitchObserver() {
+ override fun onBeforeUserSwitching(newUserId: Int) {
+ handleBeforeUserSwitching(newUserId)
}
- }
- override fun onUserSwitchComplete(newUserId: Int) {
- if (isBackgroundUserSwitchEnabled) {
- afterUserSwitchingJob?.cancel()
- afterUserSwitchingJob = appScope.launch(backgroundContext) {
+ override fun onUserSwitching(newUserId: Int, reply: IRemoteCallback?) {
+ if (isBackgroundUserSwitchEnabled) {
+ userSwitchingJob?.cancel()
+ userSwitchingJob =
+ appScope.launch(backgroundContext) {
+ handleUserSwitchingCoroutines(newUserId) { reply?.sendResult(null) }
+ }
+ } else {
+ handleUserSwitching(newUserId)
+ reply?.sendResult(null)
+ }
+ }
+
+ override fun onUserSwitchComplete(newUserId: Int) {
+ if (isBackgroundUserSwitchEnabled) {
+ afterUserSwitchingJob?.cancel()
+ afterUserSwitchingJob =
+ appScope.launch(backgroundContext) {
+ handleUserSwitchComplete(newUserId)
+ }
+ } else {
handleUserSwitchComplete(newUserId)
}
- } else {
- handleUserSwitchComplete(newUserId)
}
- }
- }, TAG)
+ },
+ TAG
+ )
}
@WorkerThread
@@ -228,9 +232,10 @@
setUserIdInternal(newUserId)
notifySubscribers { callback, resultCallback ->
- callback.onBeforeUserSwitching(newUserId)
- resultCallback.run()
- }.await()
+ callback.onBeforeUserSwitching(newUserId)
+ resultCallback.run()
+ }
+ .await()
}
@WorkerThread
@@ -239,31 +244,34 @@
Log.i(TAG, "Switching to user $newUserId")
notifySubscribers { callback, resultCallback ->
- callback.onUserChanging(newUserId, userContext, resultCallback)
- }.await()
+ callback.onUserChanging(newUserId, userContext, resultCallback)
+ }
+ .await()
}
@WorkerThread
protected open suspend fun handleUserSwitchingCoroutines(newUserId: Int, onDone: () -> Unit) =
- coroutineScope {
- Assert.isNotMainThread()
- Log.i(TAG, "Switching to user $newUserId")
+ coroutineScope {
+ Assert.isNotMainThread()
+ Log.i(TAG, "Switching to user $newUserId")
- for (callbackDataItem in synchronized(callbacks) { callbacks.toList() }) {
- val callback: UserTracker.Callback = callbackDataItem.callback.get() ?: continue
- launch(callbackDataItem.executor.asCoroutineDispatcher()) {
+ for (callbackDataItem in synchronized(callbacks) { callbacks.toList() }) {
+ val callback: UserTracker.Callback = callbackDataItem.callback.get() ?: continue
+ launch(callbackDataItem.executor.asCoroutineDispatcher()) {
val mutex = Mutex(true)
- val thresholdLogJob = launch(backgroundContext) {
- delay(USER_CHANGE_THRESHOLD)
- Log.e(TAG, "Failed to finish $callback in time")
- }
+ val thresholdLogJob =
+ launch(backgroundContext) {
+ delay(USER_CHANGE_THRESHOLD)
+ Log.e(TAG, "Failed to finish $callback in time")
+ }
callback.onUserChanging(userId, userContext) { mutex.unlock() }
mutex.lock()
thresholdLogJob.cancel()
- }.join()
- }
- onDone()
+ }
+ .join()
}
+ onDone()
+ }
@WorkerThread
protected open fun handleUserSwitchComplete(newUserId: Int) {
@@ -284,36 +292,26 @@
synchronized(mutex) {
userProfiles = profiles.map { UserInfo(it) } // save a "deep" copy
}
- notifySubscribers { callback, _ ->
- callback.onProfilesChanged(profiles)
- }
+ notifySubscribers { callback, _ -> callback.onProfilesChanged(profiles) }
}
override fun addCallback(callback: UserTracker.Callback, executor: Executor) {
- synchronized(callbacks) {
- callbacks.add(DataItem(WeakReference(callback), executor))
- }
+ synchronized(callbacks) { callbacks.add(DataItem(WeakReference(callback), executor)) }
}
override fun removeCallback(callback: UserTracker.Callback) {
- synchronized(callbacks) {
- callbacks.removeIf { it.sameOrEmpty(callback) }
- }
+ synchronized(callbacks) { callbacks.removeIf { it.sameOrEmpty(callback) } }
}
private inline fun notifySubscribers(
- crossinline action: (UserTracker.Callback, resultCallback: Runnable) -> Unit
+ crossinline action: (UserTracker.Callback, resultCallback: Runnable) -> Unit
): CountDownLatch {
- val list = synchronized(callbacks) {
- callbacks.toList()
- }
+ val list = synchronized(callbacks) { callbacks.toList() }
val latch = CountDownLatch(list.size)
list.forEach {
val callback = it.callback.get()
if (callback != null) {
- it.executor.execute {
- action(callback) { latch.countDown() }
- }
+ it.executor.execute { action(callback) { latch.countDown() } }
} else {
latch.countDown()
}
@@ -328,20 +326,13 @@
val ids = userProfiles.map { it.toFullString() }
pw.println("userProfiles: $ids")
}
- val list = synchronized(callbacks) {
- callbacks.toList()
- }
+ val list = synchronized(callbacks) { callbacks.toList() }
pw.println("Callbacks:")
- list.forEach {
- it.callback.get()?.let {
- pw.println(" $it")
- }
- }
+ list.forEach { it.callback.get()?.let { pw.println(" $it") } }
}
- private class SynchronizedDelegate<T : Any>(
- private var value: T
- ) : ReadWriteProperty<UserTrackerImpl, T> {
+ private class SynchronizedDelegate<T : Any>(private var value: T) :
+ ReadWriteProperty<UserTrackerImpl, T> {
@GuardedBy("mutex")
override fun getValue(thisRef: UserTrackerImpl, property: KProperty<*>): T {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
index 6223ca7..4639e22 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
@@ -17,7 +17,6 @@
package com.android.systemui.shade
import android.content.Context
-import android.graphics.Insets
import android.graphics.Rect
import android.os.PowerManager
import android.os.SystemClock
@@ -26,7 +25,6 @@
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
-import android.view.WindowInsets
import android.widget.FrameLayout
import androidx.activity.OnBackPressedDispatcher
import androidx.activity.OnBackPressedDispatcherOwner
@@ -42,7 +40,6 @@
import com.android.compose.theme.PlatformTheme
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.Flags
-import com.android.systemui.Flags.glanceableHubBackGesture
import com.android.systemui.ambient.touch.TouchMonitor
import com.android.systemui.ambient.touch.dagger.AmbientTouchComponent
import com.android.systemui.communal.dagger.Communal
@@ -322,21 +319,13 @@
// Run when the touch handling lifecycle is RESUMED, meaning the hub is visible and not
// occluded.
lifecycleRegistry.repeatOnLifecycle(Lifecycle.State.RESUMED) {
- // Avoid adding exclusion to end/start edges to allow back gestures.
- val insets =
- if (glanceableHubBackGesture()) {
- containerView.rootWindowInsets.getInsets(WindowInsets.Type.systemGestures())
- } else {
- Insets.NONE
- }
-
val ltr = containerView.layoutDirection == View.LAYOUT_DIRECTION_LTR
val backGestureInset =
Rect(
- if (ltr) 0 else insets.left,
0,
- if (ltr) insets.right else containerView.right,
+ 0,
+ if (ltr) 0 else containerView.right,
containerView.bottom,
)
@@ -352,9 +341,9 @@
// Only allow swipe up to bouncer and swipe down to shade in the very
// top/bottom to avoid conflicting with widgets in the hub grid.
Rect(
- insets.left,
+ 0,
topEdgeSwipeRegionWidth,
- containerView.right - insets.right,
+ containerView.right,
containerView.bottom - bottomEdgeSwipeRegionWidth
),
// Disable back gestures on the left side of the screen, to avoid
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModel.kt
index 2f98488..f270e82 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/NotificationShadeWindowModel.kt
@@ -17,14 +17,15 @@
package com.android.systemui.shade.ui.viewmodel
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
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
+import com.android.systemui.keyguard.shared.model.KeyguardState.GLANCEABLE_HUB
import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED
-import com.android.systemui.util.kotlin.BooleanFlowOperators.anyOf
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.util.kotlin.BooleanFlowOperators.any
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.map
/** Models UI state for the shade window. */
@SysUISingleton
@@ -32,11 +33,38 @@
@Inject
constructor(
keyguardTransitionInteractor: KeyguardTransitionInteractor,
- keyguardInteractor: KeyguardInteractor,
) {
+ /**
+ * Considered to be occluded if in OCCLUDED, DREAMING, GLANCEABLE_HUB/Communal, or transitioning
+ * between those states. Every permutation is listed so we can use optimal flows and support
+ * Scenes.
+ */
val isKeyguardOccluded: Flow<Boolean> =
- anyOf(
- keyguardTransitionInteractor.transitionValue(OCCLUDED).map { it == 1f },
- keyguardTransitionInteractor.transitionValue(DREAMING).map { it == 1f },
- )
+ listOf(
+ // Finished in state...
+ keyguardTransitionInteractor.isFinishedIn(OCCLUDED),
+ keyguardTransitionInteractor.isFinishedIn(DREAMING),
+ keyguardTransitionInteractor.isFinishedIn(Scenes.Communal, GLANCEABLE_HUB),
+
+ // ... or transitions between those states
+ keyguardTransitionInteractor.isInTransition(Edge.create(OCCLUDED, DREAMING)),
+ keyguardTransitionInteractor.isInTransition(Edge.create(DREAMING, OCCLUDED)),
+ keyguardTransitionInteractor.isInTransition(
+ edge = Edge.create(from = OCCLUDED, to = Scenes.Communal),
+ edgeWithoutSceneContainer = Edge.create(from = OCCLUDED, to = GLANCEABLE_HUB),
+ ),
+ keyguardTransitionInteractor.isInTransition(
+ edge = Edge.create(from = Scenes.Communal, to = OCCLUDED),
+ edgeWithoutSceneContainer = Edge.create(from = GLANCEABLE_HUB, to = OCCLUDED),
+ ),
+ keyguardTransitionInteractor.isInTransition(
+ edge = Edge.create(from = DREAMING, to = Scenes.Communal),
+ edgeWithoutSceneContainer = Edge.create(from = DREAMING, to = GLANCEABLE_HUB),
+ ),
+ keyguardTransitionInteractor.isInTransition(
+ edge = Edge.create(from = Scenes.Communal, to = DREAMING),
+ edgeWithoutSceneContainer = Edge.create(from = GLANCEABLE_HUB, to = DREAMING),
+ ),
+ )
+ .any()
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index d0c51bc2..bf00a39 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -1255,6 +1255,11 @@
}
@Override
+ public void closeGutsOnSceneTouch() {
+ mController.closeControlsDueToOutsideTouch();
+ }
+
+ @Override
public void setSyntheticScrollConsumer(@Nullable Consumer<Float> consumer) {
mScrollViewFields.setSyntheticScrollConsumer(consumer);
}
@@ -1265,6 +1270,11 @@
}
@Override
+ public void setCurrentGestureInGutsConsumer(@Nullable Consumer<Boolean> consumer) {
+ mScrollViewFields.setCurrentGestureInGutsConsumer(consumer);
+ }
+
+ @Override
public void setHeadsUpHeightConsumer(@Nullable Consumer<Float> consumer) {
mScrollViewFields.setHeadsUpHeightConsumer(consumer);
}
@@ -3548,33 +3558,41 @@
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
- if (SceneContainerFlag.isEnabled() && mIsBeingDragged) {
+ if (SceneContainerFlag.isEnabled()) {
int action = ev.getActionMasked();
- boolean isUpOrCancel = action == ACTION_UP || action == ACTION_CANCEL;
- if (mSendingTouchesToSceneFramework) {
- MotionEvent adjustedEvent = MotionEvent.obtain(ev);
- adjustedEvent.setLocation(ev.getRawX(), ev.getRawY());
- mController.sendTouchToSceneFramework(adjustedEvent);
- mScrollViewFields.sendCurrentGestureOverscroll(
- getExpandedInThisMotion() && !isUpOrCancel);
- adjustedEvent.recycle();
- } else if (!isUpOrCancel) {
- // if this is the first touch being sent to the scene framework,
- // convert it into a synthetic DOWN event.
- mSendingTouchesToSceneFramework = true;
- MotionEvent downEvent = MotionEvent.obtain(ev);
- downEvent.setAction(MotionEvent.ACTION_DOWN);
- downEvent.setLocation(ev.getRawX(), ev.getRawY());
- mController.sendTouchToSceneFramework(downEvent);
- mScrollViewFields.sendCurrentGestureOverscroll(getExpandedInThisMotion());
- downEvent.recycle();
+ boolean isTouchInGuts = mController.isTouchInGutsView(ev);
+ if (action == MotionEvent.ACTION_DOWN && !isTouchInGuts) {
+ mController.closeControlsDueToOutsideTouch();
}
+ if (mIsBeingDragged) {
+ boolean isUpOrCancel = action == ACTION_UP || action == ACTION_CANCEL;
+ if (mSendingTouchesToSceneFramework) {
+ MotionEvent adjustedEvent = MotionEvent.obtain(ev);
+ adjustedEvent.setLocation(ev.getRawX(), ev.getRawY());
+ mScrollViewFields.sendCurrentGestureOverscroll(
+ getExpandedInThisMotion() && !isUpOrCancel);
+ mController.sendTouchToSceneFramework(adjustedEvent);
+ adjustedEvent.recycle();
+ } else if (!isUpOrCancel) {
+ // if this is the first touch being sent to the scene framework,
+ // convert it into a synthetic DOWN event.
+ mSendingTouchesToSceneFramework = true;
+ MotionEvent downEvent = MotionEvent.obtain(ev);
+ downEvent.setAction(MotionEvent.ACTION_DOWN);
+ downEvent.setLocation(ev.getRawX(), ev.getRawY());
+ mScrollViewFields.sendCurrentGestureInGuts(isTouchInGuts);
+ mScrollViewFields.sendCurrentGestureOverscroll(getExpandedInThisMotion());
+ mController.sendTouchToSceneFramework(downEvent);
+ downEvent.recycle();
+ }
- if (isUpOrCancel) {
- mScrollViewFields.sendCurrentGestureOverscroll(false);
- setIsBeingDragged(false);
+ if (isUpOrCancel) {
+ mScrollViewFields.sendCurrentGestureInGuts(false);
+ mScrollViewFields.sendCurrentGestureOverscroll(false);
+ setIsBeingDragged(false);
+ }
+ return false;
}
- return false;
}
return TouchLogger.logDispatchTouch(TAG, ev, super.dispatchTouchEvent(ev));
}
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 c25b30d..4e73529 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
@@ -1690,7 +1690,7 @@
mVisibilityProvider.obtain(entry, true));
}
- public void closeControlsIfOutsideTouch(MotionEvent ev) {
+ private View getGutsView() {
NotificationGuts guts = mNotificationGutsManager.getExposedGuts();
NotificationMenuRowPlugin menuRow = mSwipeHelper.getCurrentMenuRow();
View translatingParentView = mSwipeHelper.getTranslatingParentView();
@@ -1703,15 +1703,35 @@
// Checking menu
view = translatingParentView;
}
+ return view;
+ }
+
+ public void closeControlsIfOutsideTouch(MotionEvent ev) {
+ SceneContainerFlag.assertInLegacyMode();
+ View view = getGutsView();
if (view != null && !NotificationSwipeHelper.isTouchInView(ev, view)) {
// Touch was outside visible guts / menu notification, close what's visible
- mNotificationGutsManager.closeAndSaveGuts(false /* removeLeavebehind */,
- false /* force */, true /* removeControls */, -1 /* x */, -1 /* y */,
- false /* resetMenu */);
- mSwipeHelper.resetExposedMenuView(true /* animate */, true /* force */);
+ closeAndSaveGuts();
}
}
+ void closeControlsDueToOutsideTouch() {
+ if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return;
+ closeAndSaveGuts();
+ }
+
+ private void closeAndSaveGuts() {
+ mNotificationGutsManager.closeAndSaveGuts(false /* removeLeavebehind */,
+ false /* force */, true /* removeControls */, -1 /* x */, -1 /* y */,
+ false /* resetMenu */);
+ mSwipeHelper.resetExposedMenuView(true /* animate */, true /* force */);
+ }
+
+ boolean isTouchInGutsView(MotionEvent event) {
+ View view = getGutsView();
+ return NotificationSwipeHelper.isTouchInView(event, view);
+ }
+
public void clearSilentNotifications() {
FooterViewRefactor.assertInLegacyMode();
// Leave the shade open if there will be other notifs left over to clear
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ScrollViewFields.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ScrollViewFields.kt
index 383d8b3..aa39539 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ScrollViewFields.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ScrollViewFields.kt
@@ -53,6 +53,11 @@
*/
var currentGestureOverscrollConsumer: Consumer<Boolean>? = null
/**
+ * When a gesture is on open notification guts, which means scene container should not close the
+ * guts off of this gesture, we can notify the placeholder through here.
+ */
+ var currentGestureInGutsConsumer: Consumer<Boolean>? = null
+ /**
* Any time the heads up height is recalculated, it should be updated here to be used by the
* placeholder
*/
@@ -66,6 +71,10 @@
fun sendCurrentGestureOverscroll(isCurrentGestureOverscroll: Boolean) =
currentGestureOverscrollConsumer?.accept(isCurrentGestureOverscroll)
+ /** send [isCurrentGestureInGuts] to the [currentGestureInGutsConsumer], if present. */
+ fun sendCurrentGestureInGuts(isCurrentGestureInGuts: Boolean) =
+ currentGestureInGutsConsumer?.accept(isCurrentGestureInGuts)
+
/** send the [headsUpHeight] to the [headsUpHeightConsumer], if present. */
fun sendHeadsUpHeight(headsUpHeight: Float) = headsUpHeightConsumer?.accept(headsUpHeight)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationViewHeightRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationViewHeightRepository.kt
index f6d9351..4907d44 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationViewHeightRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/data/repository/NotificationViewHeightRepository.kt
@@ -39,4 +39,7 @@
* consumed part of the gesture.
*/
val isCurrentGestureOverscroll = MutableStateFlow(false)
+
+ /** Whether the current touch gesture is on any open notification guts. */
+ val isCurrentGestureInGuts = MutableStateFlow(false)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt
index 8557afc..756cd87 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractor.kt
@@ -18,6 +18,7 @@
package com.android.systemui.statusbar.notification.stack.domain.interactor
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.notification.stack.data.repository.NotificationPlaceholderRepository
@@ -39,6 +40,7 @@
constructor(
private val viewHeightRepository: NotificationViewHeightRepository,
private val placeholderRepository: NotificationPlaceholderRepository,
+ sceneInteractor: SceneInteractor,
shadeInteractor: ShadeInteractor,
) {
/** The bounds of the notification stack in the current scene. */
@@ -93,6 +95,15 @@
val isCurrentGestureOverscroll: Flow<Boolean> =
viewHeightRepository.isCurrentGestureOverscroll.asStateFlow()
+ /** Whether we should close any notification guts that are currently open. */
+ val shouldCloseGuts: Flow<Boolean> =
+ combine(
+ sceneInteractor.isSceneContainerUserInputOngoing,
+ viewHeightRepository.isCurrentGestureInGuts
+ ) { isUserInputOngoing, isCurrentGestureInGuts ->
+ isUserInputOngoing && !isCurrentGestureInGuts
+ }
+
/** Sets the alpha to apply to the NSSL for the brightness mirror */
fun setAlphaForBrightnessMirror(alpha: Float) {
placeholderRepository.alphaForBrightnessMirror.value = alpha
@@ -119,6 +130,10 @@
viewHeightRepository.isCurrentGestureOverscroll.value = isOverscroll
}
+ fun setCurrentGestureInGuts(isInGuts: Boolean) {
+ viewHeightRepository.isCurrentGestureInGuts.value = isInGuts
+ }
+
fun setConstrainedAvailableSpace(height: Int) {
placeholderRepository.constrainedAvailableSpace.value = height
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt
index 1289cec..235b4da 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt
@@ -71,6 +71,9 @@
/** Set a consumer for current gesture overscroll events */
fun setCurrentGestureOverscrollConsumer(consumer: Consumer<Boolean>?)
+ /** Set a consumer for current gesture in guts events */
+ fun setCurrentGestureInGutsConsumer(consumer: Consumer<Boolean>?)
+
/** Set a consumer for heads up height changed events */
fun setHeadsUpHeightConsumer(consumer: Consumer<Float>?)
@@ -92,6 +95,12 @@
/** Gets the inset for HUNs when they are not visible */
fun getHeadsUpInset(): Int
+ /**
+ * Signals that any open Notification guts should be closed, as scene container is handling
+ * touch events.
+ */
+ fun closeGutsOnSceneTouch()
+
/** Adds a listener to be notified, when the stack height might have changed. */
fun addStackHeightChangedListener(runnable: Runnable)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt
index c044f6f..3cc6e81 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt
@@ -36,6 +36,7 @@
import kotlinx.coroutines.DisposableHandle
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
/** Binds the [NotificationScrollView]. */
@@ -98,13 +99,18 @@
.filter { it }
.collect { view.setStackTop(-(view.getHeadsUpInset().toFloat())) }
}
+ launch {
+ viewModel.shouldCloseGuts.filter { it }.collect { view.closeGutsOnSceneTouch() }
+ }
launchAndDispose {
view.setSyntheticScrollConsumer(viewModel.syntheticScrollConsumer)
view.setCurrentGestureOverscrollConsumer(viewModel.currentGestureOverscrollConsumer)
+ view.setCurrentGestureInGutsConsumer(viewModel.currentGestureInGutsConsumer)
DisposableHandle {
view.setSyntheticScrollConsumer(null)
view.setCurrentGestureOverscrollConsumer(null)
+ view.setCurrentGestureInGutsConsumer(null)
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt
index b2045fe..3999578 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt
@@ -136,6 +136,9 @@
val qsExpandFraction: Flow<Float> =
shadeInteractor.qsExpansion.dumpWhileCollecting("qsExpandFraction")
+ /** Whether we should close any open notification guts. */
+ val shouldCloseGuts: Flow<Boolean> = stackAppearanceInteractor.shouldCloseGuts
+
val shouldResetStackTop: Flow<Boolean> =
sceneInteractor.transitionState
.mapNotNull { state -> state is Idle && state.currentScene == Scenes.Gone }
@@ -202,6 +205,10 @@
val currentGestureOverscrollConsumer: (Boolean) -> Unit =
stackAppearanceInteractor::setCurrentGestureOverscroll
+ /** Receives whether the current touch gesture is inside any open guts. */
+ val currentGestureInGutsConsumer: (Boolean) -> Unit =
+ stackAppearanceInteractor::setCurrentGestureInGuts
+
/** Whether the notification stack is scrollable or not. */
val isScrollable: Flow<Boolean> =
sceneInteractor.currentScene
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 0f93ff2..f11fd7b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -68,7 +68,6 @@
import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor;
import com.android.systemui.dock.DockManager;
import com.android.systemui.dreams.DreamOverlayStateController;
-import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.KeyguardWmStateRefactor;
import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardSurfaceBehindInteractor;
@@ -104,6 +103,7 @@
import com.android.systemui.unfold.FoldAodAnimationController;
import com.android.systemui.unfold.SysUIUnfoldComponent;
import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
+import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.kotlin.JavaAdapter;
import dagger.Lazy;
@@ -179,6 +179,8 @@
private float mFraction = -1f;
private boolean mTracking = false;
private boolean mBouncerShowingOverDream;
+ private int mAttemptsToShowBouncer = 0;
+ private DelayableExecutor mExecutor;
private final PrimaryBouncerExpansionCallback mExpansionCallback =
new PrimaryBouncerExpansionCallback() {
@@ -315,8 +317,6 @@
private boolean mLastScreenOffAnimationPlaying;
private float mQsExpansion;
- private FeatureFlags mFlags;
-
final Set<KeyguardViewManagerCallback> mCallbacks = new HashSet<>();
private boolean mIsBackAnimationEnabled;
private final UdfpsOverlayInteractor mUdfpsOverlayInteractor;
@@ -399,9 +399,11 @@
JavaAdapter javaAdapter,
Lazy<SceneInteractor> sceneInteractorLazy,
StatusBarKeyguardViewManagerInteractor statusBarKeyguardViewManagerInteractor,
+ @Main DelayableExecutor executor,
Lazy<DeviceEntryInteractor> deviceEntryInteractorLazy
) {
mContext = context;
+ mExecutor = executor;
mViewMediatorCallback = callback;
mLockPatternUtils = lockPatternUtils;
mConfigurationController = configurationController;
@@ -711,13 +713,7 @@
* {@link #needsFullscreenBouncer()}.
*/
protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing, boolean isFalsingReset) {
- boolean isDozing = mDozing;
- if (Flags.simPinRaceConditionOnRestart()) {
- KeyguardState toState = mKeyguardTransitionInteractor.getTransitionState().getValue()
- .getTo();
- isDozing = mDozing || toState == KeyguardState.DOZING || toState == KeyguardState.AOD;
- }
- if (needsFullscreenBouncer() && !isDozing) {
+ if (needsFullscreenBouncer() && !mDozing) {
// The keyguard might be showing (already). So we need to hide it.
if (!primaryBouncerIsShowing()) {
if (SceneContainerFlag.isEnabled()) {
@@ -727,9 +723,22 @@
} else {
if (Flags.simPinRaceConditionOnRestart()) {
if (mPrimaryBouncerInteractor.show(/* isScrimmed= */ true)) {
+ mAttemptsToShowBouncer = 0;
mCentralSurfaces.hideKeyguard();
} else {
- mCentralSurfaces.showKeyguard();
+ if (mAttemptsToShowBouncer > 6) {
+ mAttemptsToShowBouncer = 0;
+ Log.e(TAG, "Too many failed attempts to show bouncer, showing "
+ + "keyguard instead");
+ mCentralSurfaces.showKeyguard();
+ } else {
+ Log.v(TAG, "Failed to show bouncer, attempt #: "
+ + mAttemptsToShowBouncer++);
+ mExecutor.executeDelayed(() ->
+ showBouncerOrKeyguard(hideBouncerWhenShowing,
+ isFalsingReset),
+ 500);
+ }
}
} else {
mCentralSurfaces.hideKeyguard();
@@ -1874,6 +1883,11 @@
|| mode == KeyguardSecurityModel.SecurityMode.SimPuk;
}
+ @VisibleForTesting
+ void setAttemptsToShowBouncer(int attempts) {
+ mAttemptsToShowBouncer = attempts;
+ }
+
/**
* Delegate used to send show and hide events to an alternate authentication method instead of
* the regular pin/pattern/password bouncer.
diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/SelectedUserInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/SelectedUserInteractor.kt
index 59c819d..cd32718 100644
--- a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/SelectedUserInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/SelectedUserInteractor.kt
@@ -3,8 +3,6 @@
import android.annotation.UserIdInt
import android.content.pm.UserInfo
import android.os.UserManager
-import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.Flags.refactorGetCurrentUser
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.user.data.repository.UserRepository
import javax.inject.Inject
@@ -21,23 +19,11 @@
/** Flow providing the [UserInfo] of the currently selected user. */
val selectedUserInfo = repository.selectedUserInfo
- /**
- * Returns the ID of the currently-selected user.
- *
- * @param bypassFlag this will ignore the feature flag and get the data from the repository
- * instead. This is used for refactored methods that were previously pointing to `userTracker`
- * and therefore should not be routed back to KeyguardUpdateMonitor when flag is disabled.
- * KeyguardUpdateMonitor.getCurrentUser() is deprecated and will be removed soon (together
- * with this flag).
- */
+ /** Returns the ID of the currently-selected user. */
@UserIdInt
@JvmOverloads
- fun getSelectedUserId(bypassFlag: Boolean = false): Int {
- return if (bypassFlag || refactorGetCurrentUser()) {
- repository.getSelectedUserInfo().id
- } else {
- KeyguardUpdateMonitor.getCurrentUser()
- }
+ fun getSelectedUserId(): Int {
+ return repository.getSelectedUserInfo().id
}
/**
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 7aa415b..52fde7e 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -354,7 +354,6 @@
ExtendedMockito.doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
.when(SubscriptionManager::getDefaultSubscriptionId);
when(mSelectedUserInteractor.getSelectedUserId()).thenReturn(mCurrentUserId);
- when(mSelectedUserInteractor.getSelectedUserId(anyBoolean())).thenReturn(mCurrentUserId);
mContext.getOrCreateTestableResources().addOverride(
com.android.systemui.res.R.integer.config_face_auth_supported_posture,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityGestureTargetsObserverTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityGestureTargetsObserverTest.java
new file mode 100644
index 0000000..ba990ef
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/AccessibilityGestureTargetsObserverTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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.accessibility;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManager;
+import android.provider.Settings;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.settings.UserTracker;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+/** Test for {@link AccessibilityGestureTargetsObserver}. */
+@RunWith(AndroidTestingRunner.class)
+@SmallTest
+public class AccessibilityGestureTargetsObserverTest extends SysuiTestCase {
+ private static final int MY_USER_ID = ActivityManager.getCurrentUser();
+
+ @Rule
+ public MockitoRule mockito = MockitoJUnit.rule();
+
+ @Mock
+ private UserTracker mUserTracker;
+ @Mock
+ private AccessibilityGestureTargetsObserver.TargetsChangedListener mListener;
+
+ private AccessibilityGestureTargetsObserver mAccessibilityGestureTargetsObserver;
+
+ private static final String TEST_A11Y_BTN_TARGETS = "Magnification";
+
+ @Before
+ public void setUp() {
+ when(mUserTracker.getUserId()).thenReturn(MY_USER_ID);
+ mAccessibilityGestureTargetsObserver = new AccessibilityGestureTargetsObserver(mContext,
+ mUserTracker);
+ }
+
+ @Test
+ public void onChange_haveListener_invokeCallback() {
+ mAccessibilityGestureTargetsObserver.addListener(mListener);
+ Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_GESTURE_TARGETS, TEST_A11Y_BTN_TARGETS,
+ MY_USER_ID);
+
+ mAccessibilityGestureTargetsObserver.mContentObserver.onChange(false);
+
+ verify(mListener).onAccessibilityGestureTargetsChanged(TEST_A11Y_BTN_TARGETS);
+ }
+
+ @Test
+ public void onChange_listenerRemoved_noInvokeCallback() {
+ mAccessibilityGestureTargetsObserver.addListener(mListener);
+ mAccessibilityGestureTargetsObserver.removeListener(mListener);
+ Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_GESTURE_TARGETS, TEST_A11Y_BTN_TARGETS,
+ MY_USER_ID);
+
+ mAccessibilityGestureTargetsObserver.mContentObserver.onChange(false);
+
+ verify(mListener, never()).onAccessibilityGestureTargetsChanged(anyString());
+ }
+
+ @Test
+ public void getCurrentAccessibilityGestureTargets_expectedValue() {
+ Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ Settings.Secure.ACCESSIBILITY_GESTURE_TARGETS, TEST_A11Y_BTN_TARGETS,
+ MY_USER_ID);
+
+ final String actualValue =
+ mAccessibilityGestureTargetsObserver.getCurrentAccessibilityGestureTargets();
+
+ assertThat(actualValue).isEqualTo(TEST_A11Y_BTN_TARGETS);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 37f1a3d..597ffef 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -26,7 +26,6 @@
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
import static com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR;
-import static com.android.systemui.Flags.FLAG_REFACTOR_GET_CURRENT_USER;
import static com.android.systemui.keyguard.KeyguardViewMediator.DELAYED_KEYGUARD_ACTION;
import static com.android.systemui.keyguard.KeyguardViewMediator.KEYGUARD_LOCK_AFTER_DELAY_DEFAULT;
import static com.android.systemui.keyguard.KeyguardViewMediator.REBOOT_MAINLINE_UPDATE;
@@ -250,7 +249,6 @@
when(mCommunalTransitionViewModel.getTransitionFromOccludedEnded())
.thenReturn(mock(Flow.class));
when(mSelectedUserInteractor.getSelectedUserId()).thenReturn(mDefaultUserId);
- when(mSelectedUserInteractor.getSelectedUserId(anyBoolean())).thenReturn(mDefaultUserId);
when(mProcessWrapper.isSystemUser()).thenReturn(true);
mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(
mContext,
@@ -275,7 +273,6 @@
mKosmos.getNotificationShadeWindowModel(),
mKosmos::getCommunalInteractor);
mFeatureFlags = new FakeFeatureFlags();
- mSetFlagsRule.enableFlags(FLAG_REFACTOR_GET_CURRENT_USER);
mSetFlagsRule.disableFlags(FLAG_KEYGUARD_WM_STATE_REFACTOR);
DejankUtils.setImmediate(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt
index a0fe538b..3cbbb64 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt
@@ -23,6 +23,7 @@
import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.bouncer.domain.interactor.alternateBouncerInteractor
+import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
import com.android.systemui.flags.EnableSceneContainer
@@ -62,26 +63,19 @@
private val keyguardRepository = kosmos.fakeKeyguardRepository
private val testScope = kosmos.testScope
- private lateinit var dismissInteractorWithDependencies:
- KeyguardDismissInteractorFactory.WithDependencies
+ private lateinit var dismissInteractor: KeyguardDismissInteractor
private lateinit var underTest: KeyguardDismissActionInteractor
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- dismissInteractorWithDependencies =
- KeyguardDismissInteractorFactory.create(
- context = context,
- testScope = testScope,
- keyguardRepository = keyguardRepository,
- )
-
+ dismissInteractor = kosmos.keyguardDismissInteractor
underTest =
KeyguardDismissActionInteractor(
repository = keyguardRepository,
transitionInteractor = kosmos.keyguardTransitionInteractor,
- dismissInteractor = dismissInteractorWithDependencies.interactor,
+ dismissInteractor = dismissInteractor,
applicationScope = testScope.backgroundScope,
sceneInteractor = kosmos.sceneInteractor,
deviceEntryInteractor = kosmos.deviceEntryInteractor,
@@ -166,9 +160,7 @@
willAnimateOnLockscreen = true,
)
)
- dismissInteractorWithDependencies.bouncerRepository.setKeyguardAuthenticatedBiometrics(
- true
- )
+ kosmos.fakeKeyguardBouncerRepository.setKeyguardAuthenticatedBiometrics(true)
assertThat(executeDismissAction).isEqualTo(onDismissAction)
}
@@ -307,8 +299,7 @@
@Test
fun setKeyguardDone() =
testScope.runTest {
- val keyguardDoneTiming by
- collectLastValue(dismissInteractorWithDependencies.interactor.keyguardDone)
+ val keyguardDoneTiming by collectLastValue(dismissInteractor.keyguardDone)
runCurrent()
underTest.setKeyguardDone(KeyguardDone.LATER)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorTest.kt
index ecb46bd..fabed03 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorTest.kt
@@ -23,11 +23,18 @@
import androidx.test.filters.SmallTest
import com.android.keyguard.TrustGrantFlags
import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.fakeTrustRepository
import com.android.systemui.keyguard.shared.model.DismissAction
import com.android.systemui.keyguard.shared.model.KeyguardDone
import com.android.systemui.keyguard.shared.model.TrustModel
+import com.android.systemui.power.data.repository.fakePowerRepository
+import com.android.systemui.testKosmos
+import com.android.systemui.user.data.repository.fakeUserRepository
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestDispatcher
import kotlinx.coroutines.test.TestScope
@@ -38,14 +45,16 @@
import org.junit.runner.RunWith
import org.mockito.MockitoAnnotations
+@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
class KeyguardDismissInteractorTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
+
private lateinit var dispatcher: TestDispatcher
private lateinit var testScope: TestScope
- private lateinit var underTestDependencies: KeyguardDismissInteractorFactory.WithDependencies
- private lateinit var underTest: KeyguardDismissInteractor
+ private val underTest = kosmos.keyguardDismissInteractor
private val userInfo = UserInfo(0, "", 0)
@Before
@@ -54,13 +63,7 @@
dispatcher = StandardTestDispatcher()
testScope = TestScope(dispatcher)
- underTestDependencies =
- KeyguardDismissInteractorFactory.create(
- context = context,
- testScope = testScope,
- )
- underTest = underTestDependencies.interactor
- underTestDependencies.userRepository.setUserInfos(listOf(userInfo))
+ kosmos.fakeUserRepository.setUserInfos(listOf(userInfo))
}
@Test
@@ -69,10 +72,10 @@
val dismissKeyguardRequestWithoutImmediateDismissAction by
collectLastValue(underTest.dismissKeyguardRequestWithoutImmediateDismissAction)
- underTestDependencies.bouncerRepository.setKeyguardAuthenticatedBiometrics(null)
+ kosmos.fakeKeyguardBouncerRepository.setKeyguardAuthenticatedBiometrics(null)
assertThat(dismissKeyguardRequestWithoutImmediateDismissAction).isNull()
- underTestDependencies.bouncerRepository.setKeyguardAuthenticatedBiometrics(true)
+ kosmos.fakeKeyguardBouncerRepository.setKeyguardAuthenticatedBiometrics(true)
assertThat(dismissKeyguardRequestWithoutImmediateDismissAction).isEqualTo(Unit)
}
@@ -81,7 +84,7 @@
testScope.runTest {
val dismissKeyguardRequestWithoutImmediateDismissAction by
collectLastValue(underTest.dismissKeyguardRequestWithoutImmediateDismissAction)
- underTestDependencies.trustRepository.setRequestDismissKeyguard(
+ kosmos.fakeTrustRepository.setRequestDismissKeyguard(
TrustModel(
true,
0,
@@ -90,8 +93,8 @@
)
assertThat(dismissKeyguardRequestWithoutImmediateDismissAction).isNull()
- underTestDependencies.powerRepository.setInteractive(true)
- underTestDependencies.trustRepository.setRequestDismissKeyguard(
+ kosmos.fakePowerRepository.setInteractive(true)
+ kosmos.fakeTrustRepository.setRequestDismissKeyguard(
TrustModel(
true,
0,
@@ -106,15 +109,15 @@
testScope.runTest {
val dismissKeyguardRequestWithoutImmediateDismissAction by
collectLastValue(underTest.dismissKeyguardRequestWithoutImmediateDismissAction)
- underTestDependencies.userRepository.setSelectedUserInfo(userInfo)
+ kosmos.fakeUserRepository.setSelectedUserInfo(userInfo)
runCurrent()
// authenticated different user
- underTestDependencies.bouncerRepository.setKeyguardAuthenticatedPrimaryAuth(22)
+ kosmos.fakeKeyguardBouncerRepository.setKeyguardAuthenticatedPrimaryAuth(22)
assertThat(dismissKeyguardRequestWithoutImmediateDismissAction).isNull()
// authenticated correct user
- underTestDependencies.bouncerRepository.setKeyguardAuthenticatedPrimaryAuth(userInfo.id)
+ kosmos.fakeKeyguardBouncerRepository.setKeyguardAuthenticatedPrimaryAuth(userInfo.id)
assertThat(dismissKeyguardRequestWithoutImmediateDismissAction).isEqualTo(Unit)
}
@@ -123,17 +126,15 @@
testScope.runTest {
val dismissKeyguardRequestWithoutImmediateDismissAction by
collectLastValue(underTest.dismissKeyguardRequestWithoutImmediateDismissAction)
- underTestDependencies.userRepository.setSelectedUserInfo(userInfo)
+ kosmos.fakeUserRepository.setSelectedUserInfo(userInfo)
runCurrent()
// requested from different user
- underTestDependencies.bouncerRepository.setUserRequestedBouncerWhenAlreadyAuthenticated(
- 22
- )
+ kosmos.fakeKeyguardBouncerRepository.setUserRequestedBouncerWhenAlreadyAuthenticated(22)
assertThat(dismissKeyguardRequestWithoutImmediateDismissAction).isNull()
// requested from correct user
- underTestDependencies.bouncerRepository.setUserRequestedBouncerWhenAlreadyAuthenticated(
+ kosmos.fakeKeyguardBouncerRepository.setUserRequestedBouncerWhenAlreadyAuthenticated(
userInfo.id
)
assertThat(dismissKeyguardRequestWithoutImmediateDismissAction).isEqualTo(Unit)
@@ -159,10 +160,10 @@
collectLastValue(underTest.dismissKeyguardRequestWithoutImmediateDismissAction)
val dismissKeyguardRequestWithImmediateDismissAction by
collectLastValue(underTest.dismissKeyguardRequestWithImmediateDismissAction)
- underTestDependencies.userRepository.setSelectedUserInfo(userInfo)
+ kosmos.fakeUserRepository.setSelectedUserInfo(userInfo)
runCurrent()
- underTestDependencies.keyguardRepository.setDismissAction(
+ kosmos.fakeKeyguardRepository.setDismissAction(
DismissAction.RunImmediately(
onDismissAction = { KeyguardDone.IMMEDIATE },
onCancelAction = {},
@@ -170,7 +171,7 @@
willAnimateOnLockscreen = true,
)
)
- underTestDependencies.bouncerRepository.setUserRequestedBouncerWhenAlreadyAuthenticated(
+ kosmos.fakeKeyguardBouncerRepository.setUserRequestedBouncerWhenAlreadyAuthenticated(
userInfo.id
)
assertThat(dismissKeyguardRequestWithoutImmediateDismissAction).isNull()
@@ -184,10 +185,10 @@
collectLastValue(underTest.dismissKeyguardRequestWithoutImmediateDismissAction)
val dismissKeyguardRequestWithImmediateDismissAction by
collectLastValue(underTest.dismissKeyguardRequestWithImmediateDismissAction)
- underTestDependencies.userRepository.setSelectedUserInfo(userInfo)
+ kosmos.fakeUserRepository.setSelectedUserInfo(userInfo)
runCurrent()
- underTestDependencies.keyguardRepository.setDismissAction(
+ kosmos.fakeKeyguardRepository.setDismissAction(
DismissAction.RunAfterKeyguardGone(
dismissAction = {},
onCancelAction = {},
@@ -195,7 +196,7 @@
willAnimateOnLockscreen = true,
)
)
- underTestDependencies.bouncerRepository.setUserRequestedBouncerWhenAlreadyAuthenticated(
+ kosmos.fakeKeyguardBouncerRepository.setUserRequestedBouncerWhenAlreadyAuthenticated(
userInfo.id
)
assertThat(dismissKeyguardRequestWithImmediateDismissAction).isNull()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
index 2cc8cc7..99c5b7c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
@@ -57,6 +57,7 @@
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.kosmos.testScope
import com.android.systemui.media.controls.data.repository.MediaDataRepository
import com.android.systemui.media.controls.data.repository.MediaFilterRepository
@@ -134,6 +135,7 @@
@SmallTest
@RunWithLooper(setAsMainLooper = true)
@RunWith(AndroidJUnit4::class)
+@EnableSceneContainer
class MediaDataProcessorTest : SysuiTestCase() {
val kosmos = testKosmos()
@@ -200,8 +202,6 @@
@Before
fun setup() {
- whenever(mediaFlags.isSceneContainerEnabled()).thenReturn(true)
-
staticMockSession =
ExtendedMockito.mockitoSession()
.mockStatic<UriGrantsManager>(UriGrantsManager::class.java)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt
index f8358c5..850916b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt
@@ -186,7 +186,6 @@
sceneInteractor = kosmos.sceneInteractor,
)
verify(configurationController).addCallback(capture(configListener))
- verify(mediaDataManager).addListener(capture(listener))
verify(visualStabilityProvider)
.addPersistentReorderingAllowedListener(capture(visualStabilityCallback))
verify(keyguardUpdateMonitor).registerCallback(capture(keyguardCallback))
@@ -405,8 +404,11 @@
assertTrue(MediaPlayerData.playerKeys().elementAt(2).isSsMediaRec)
}
+ @DisableSceneContainer
@Test
fun testOrderWithSmartspace_prioritized_updatingVisibleMediaPlayers() {
+ verify(mediaDataManager).addListener(capture(listener))
+
testPlayerOrdering()
// If smartspace is prioritized
@@ -439,8 +441,11 @@
assertTrue(MediaPlayerData.playerKeys().elementAt(idx).isSsMediaRec)
}
+ @DisableSceneContainer
@Test
fun testPlayingExistingMediaPlayerFromCarousel_visibleMediaPlayersNotUpdated() {
+ verify(mediaDataManager).addListener(capture(listener))
+
testPlayerOrdering()
// playing paused player
listener.value.onMediaDataLoaded(
@@ -547,8 +552,11 @@
verify(logger).logRecommendationRemoved(eq(packageName), eq(instanceId!!))
}
+ @DisableSceneContainer
@Test
fun testMediaLoaded_ScrollToActivePlayer() {
+ verify(mediaDataManager).addListener(capture(listener))
+
listener.value.onMediaDataLoaded(
PLAYING_LOCAL,
null,
@@ -604,8 +612,11 @@
)
}
+ @DisableSceneContainer
@Test
fun testMediaLoadedFromRecommendationCard_ScrollToActivePlayer() {
+ verify(mediaDataManager).addListener(capture(listener))
+
listener.value.onSmartspaceMediaDataLoaded(
SMARTSPACE_KEY,
EMPTY_SMARTSPACE_MEDIA_DATA.copy(packageName = "PACKAGE_NAME", isActive = true),
@@ -647,8 +658,11 @@
assertEquals(playerIndex, 0)
}
+ @DisableSceneContainer
@Test
fun testRecommendationRemovedWhileNotVisible_updateHostVisibility() {
+ verify(mediaDataManager).addListener(capture(listener))
+
var result = false
mediaCarouselController.updateHostVisibility = { result = true }
@@ -658,8 +672,11 @@
assertEquals(true, result)
}
+ @DisableSceneContainer
@Test
fun testRecommendationRemovedWhileVisible_thenReorders_updateHostVisibility() {
+ verify(mediaDataManager).addListener(capture(listener))
+
var result = false
mediaCarouselController.updateHostVisibility = { result = true }
@@ -788,8 +805,11 @@
verify(pageIndicator, times(4)).setNumPages(any())
}
+ @DisableSceneContainer
@Test
fun testRecommendation_persistentEnabled_newSmartspaceLoaded_updatesSort() {
+ verify(mediaDataManager).addListener(capture(listener))
+
testRecommendation_persistentEnabled_inactiveSmartspaceDataLoaded_isAdded()
// When an update to existing smartspace data is loaded
@@ -804,8 +824,11 @@
assertTrue(MediaPlayerData.visiblePlayerKeys().elementAt(0).data.active)
}
+ @DisableSceneContainer
@Test
fun testRecommendation_persistentEnabled_inactiveSmartspaceDataLoaded_isAdded() {
+ verify(mediaDataManager).addListener(capture(listener))
+
whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(true)
// When inactive smartspace data is loaded
@@ -1023,11 +1046,13 @@
verify(panel).updateAnimatorDurationScale()
}
+ @DisableSceneContainer
@Test
fun swipeToDismiss_pausedAndResumeOff_userInitiated() {
+ verify(mediaDataManager).addListener(capture(listener))
+
// When resumption is disabled, paused media should be dismissed after being swiped away
Settings.Secure.putInt(context.contentResolver, Settings.Secure.MEDIA_CONTROLS_RESUME, 0)
-
val pausedMedia = DATA.copy(isPlaying = false)
listener.value.onMediaDataLoaded(PAUSED_LOCAL, PAUSED_LOCAL, pausedMedia)
mediaCarouselController.onSwipeToDismiss()
@@ -1042,8 +1067,11 @@
verify(mediaDataManager).dismissMediaData(eq(PAUSED_LOCAL), anyLong(), eq(true))
}
+ @DisableSceneContainer
@Test
fun swipeToDismiss_pausedAndResumeOff_delayed_userInitiated() {
+ verify(mediaDataManager).addListener(capture(listener))
+
// When resumption is disabled, paused media should be dismissed after being swiped away
Settings.Secure.putInt(context.contentResolver, Settings.Secure.MEDIA_CONTROLS_RESUME, 0)
mediaCarouselController.updateHostVisibility = {}
@@ -1068,6 +1096,7 @@
* @param function called when a certain configuration change occurs.
*/
private fun testConfigurationChange(function: () -> Unit) {
+ verify(mediaDataManager).addListener(capture(listener))
mediaCarouselController.pageIndicator = pageIndicator
listener.value.onMediaDataLoaded(
PLAYING_LOCAL,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt
index 521aa5a..1260a65 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaControlPanelTest.kt
@@ -70,6 +70,7 @@
import com.android.systemui.bluetooth.BroadcastDialogController
import com.android.systemui.broadcast.BroadcastSender
import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor
+import com.android.systemui.flags.DisableSceneContainer
import com.android.systemui.media.controls.MediaTestUtils
import com.android.systemui.media.controls.domain.pipeline.EMPTY_SMARTSPACE_MEDIA_DATA
import com.android.systemui.media.controls.domain.pipeline.MediaDataManager
@@ -84,7 +85,6 @@
import com.android.systemui.media.controls.ui.view.MediaViewHolder
import com.android.systemui.media.controls.ui.view.RecommendationViewHolder
import com.android.systemui.media.controls.ui.viewmodel.SeekBarViewModel
-import com.android.systemui.media.controls.util.MediaFlags
import com.android.systemui.media.controls.util.MediaUiEventLogger
import com.android.systemui.media.dialog.MediaOutputDialogManager
import com.android.systemui.monet.ColorScheme
@@ -141,6 +141,7 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
+@DisableSceneContainer
public class MediaControlPanelTest : SysuiTestCase() {
@get:Rule val checkFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
@@ -233,9 +234,7 @@
@Mock private lateinit var recProgressBar1: SeekBar
@Mock private lateinit var recProgressBar2: SeekBar
@Mock private lateinit var recProgressBar3: SeekBar
- private var shouldShowBroadcastButton: Boolean = false
@Mock private lateinit var globalSettings: GlobalSettings
- @Mock private lateinit var mediaFlags: MediaFlags
@JvmField @Rule val mockito = MockitoJUnit.rule()
@@ -254,7 +253,6 @@
.thenReturn(applicationInfo)
whenever(packageManager.getApplicationLabel(any())).thenReturn(PACKAGE)
context.setMockPackageManager(packageManager)
- whenever(mediaFlags.isSceneContainerEnabled()).thenReturn(false)
player =
object :
@@ -278,7 +276,6 @@
lockscreenUserManager,
broadcastDialogController,
globalSettings,
- mediaFlags,
) {
override fun loadAnimator(
animId: Int,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManagerTest.kt
index 6c350cb..2370bca 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManagerTest.kt
@@ -30,6 +30,7 @@
import com.android.systemui.communal.ui.viewmodel.communalTransitionViewModel
import com.android.systemui.controls.controller.ControlsControllerImplTest.Companion.eq
import com.android.systemui.dreams.DreamOverlayStateController
+import com.android.systemui.flags.DisableSceneContainer
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
@@ -40,7 +41,6 @@
import com.android.systemui.media.controls.ui.view.MediaCarouselScrollHandler
import com.android.systemui.media.controls.ui.view.MediaHost
import com.android.systemui.media.controls.ui.view.MediaHostState
-import com.android.systemui.media.controls.util.MediaFlags
import com.android.systemui.media.dream.MediaDreamComplication
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.res.R
@@ -85,6 +85,7 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
+@DisableSceneContainer
class MediaHierarchyManagerTest : SysuiTestCase() {
private val kosmos = testKosmos()
@@ -105,7 +106,6 @@
@Mock private lateinit var dreamOverlayStateController: DreamOverlayStateController
@Mock private lateinit var shadeInteractor: ShadeInteractor
@Mock lateinit var logger: MediaViewLogger
- @Mock private lateinit var mediaFlags: MediaFlags
@Captor
private lateinit var wakefullnessObserver: ArgumentCaptor<(WakefulnessLifecycle.Observer)>
@Captor
@@ -139,7 +139,6 @@
shadeExpansion = MutableStateFlow(0f)
whenever(shadeInteractor.isQsBypassingShade).thenReturn(isQsBypassingShade)
whenever(shadeInteractor.shadeExpansion).thenReturn(shadeExpansion)
- whenever(mediaFlags.isSceneContainerEnabled()).thenReturn(false)
mediaHierarchyManager =
MediaHierarchyManager(
context,
@@ -160,7 +159,6 @@
testScope.backgroundScope,
ResourcesSplitShadeStateController(),
logger,
- mediaFlags,
)
verify(wakefulnessLifecycle).addObserver(wakefullnessObserver.capture())
verify(statusBarStateController).addCallback(statusBarCallback.capture())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaViewControllerTest.kt
index 00b9a46..e765b6f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaViewControllerTest.kt
@@ -38,12 +38,12 @@
import androidx.test.filters.SmallTest
import com.android.internal.widget.CachingIconView
import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.media.controls.ui.view.GutsViewHolder
import com.android.systemui.media.controls.ui.view.MediaHost
import com.android.systemui.media.controls.ui.view.MediaViewHolder
import com.android.systemui.media.controls.ui.view.RecommendationViewHolder
import com.android.systemui.media.controls.ui.viewmodel.SeekBarViewModel
-import com.android.systemui.media.controls.util.MediaFlags
import com.android.systemui.res.R
import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffectView
import com.android.systemui.surfaceeffects.ripple.MultiRippleView
@@ -113,7 +113,6 @@
@Mock private lateinit var mediaTitleWidgetState: WidgetState
@Mock private lateinit var mediaSubTitleWidgetState: WidgetState
@Mock private lateinit var mediaContainerWidgetState: WidgetState
- @Mock private lateinit var mediaFlags: MediaFlags
@Mock private lateinit var seekBarViewModel: SeekBarViewModel
@Mock private lateinit var seekBarData: LiveData<SeekBarViewModel.Progress>
@Mock private lateinit var globalSettings: GlobalSettings
@@ -140,7 +139,6 @@
logger,
seekBarViewModel,
mainExecutor,
- mediaFlags,
globalSettings,
) {
override fun loadAnimator(
@@ -374,10 +372,9 @@
verify(mediaSubTitleWidgetState).alpha = floatThat { kotlin.math.abs(it - 1.0F) < delta }
}
+ @EnableSceneContainer
@Test
fun attachPlayer_seekBarDisabled_seekBarVisibilityIsSetToInvisible() {
- whenever(mediaFlags.isSceneContainerEnabled()).thenReturn(true)
-
mediaViewController.attachPlayer(viewHolder)
getEnabledChangeListener().onEnabledChanged(enabled = true)
getEnabledChangeListener().onEnabledChanged(enabled = false)
@@ -386,10 +383,9 @@
.isEqualTo(ConstraintSet.INVISIBLE)
}
+ @EnableSceneContainer
@Test
fun attachPlayer_seekBarEnabled_seekBarVisible() {
- whenever(mediaFlags.isSceneContainerEnabled()).thenReturn(true)
-
mediaViewController.attachPlayer(viewHolder)
getEnabledChangeListener().onEnabledChanged(enabled = true)
@@ -397,10 +393,9 @@
.isEqualTo(ConstraintSet.VISIBLE)
}
+ @EnableSceneContainer
@Test
fun attachPlayer_seekBarStatusUpdate_seekBarVisibilityChanges() {
- whenever(mediaFlags.isSceneContainerEnabled()).thenReturn(true)
-
mediaViewController.attachPlayer(viewHolder)
getEnabledChangeListener().onEnabledChanged(enabled = true)
@@ -413,10 +408,9 @@
.isEqualTo(ConstraintSet.INVISIBLE)
}
+ @EnableSceneContainer
@Test
fun attachPlayer_notScrubbing_scrubbingViewsGone() {
- whenever(mediaFlags.isSceneContainerEnabled()).thenReturn(true)
-
mediaViewController.attachPlayer(viewHolder)
mediaViewController.canShowScrubbingTime = true
getScrubbingChangeListener().onScrubbingChanged(true)
@@ -433,10 +427,9 @@
.isEqualTo(ConstraintSet.GONE)
}
+ @EnableSceneContainer
@Test
fun setIsScrubbing_noSemanticActions_scrubbingViewsGone() {
- whenever(mediaFlags.isSceneContainerEnabled()).thenReturn(true)
-
mediaViewController.attachPlayer(viewHolder)
mediaViewController.canShowScrubbingTime = false
getScrubbingChangeListener().onScrubbingChanged(true)
@@ -452,10 +445,9 @@
.isEqualTo(ConstraintSet.GONE)
}
+ @EnableSceneContainer
@Test
fun setIsScrubbing_noPrevButton_scrubbingTimesNotShown() {
- whenever(mediaFlags.isSceneContainerEnabled()).thenReturn(true)
-
mediaViewController.attachPlayer(viewHolder)
mediaViewController.setUpNextButtonInfo(true)
mediaViewController.setUpPrevButtonInfo(false)
@@ -474,10 +466,9 @@
.isEqualTo(ConstraintSet.GONE)
}
+ @EnableSceneContainer
@Test
fun setIsScrubbing_noNextButton_scrubbingTimesNotShown() {
- whenever(mediaFlags.isSceneContainerEnabled()).thenReturn(true)
-
mediaViewController.attachPlayer(viewHolder)
mediaViewController.setUpNextButtonInfo(false)
mediaViewController.setUpPrevButtonInfo(true)
@@ -496,10 +487,9 @@
.isEqualTo(ConstraintSet.GONE)
}
+ @EnableSceneContainer
@Test
fun setIsScrubbing_scrubbingViewsShownAndPrevNextHiddenOnlyInExpanded() {
- whenever(mediaFlags.isSceneContainerEnabled()).thenReturn(true)
-
mediaViewController.attachPlayer(viewHolder)
mediaViewController.setUpNextButtonInfo(true)
mediaViewController.setUpPrevButtonInfo(true)
@@ -522,10 +512,9 @@
.isEqualTo(ConstraintSet.VISIBLE)
}
+ @EnableSceneContainer
@Test
fun setIsScrubbing_trueThenFalse_reservePrevAndNextButtons() {
- whenever(mediaFlags.isSceneContainerEnabled()).thenReturn(true)
-
mediaViewController.attachPlayer(viewHolder)
mediaViewController.setUpNextButtonInfo(true, ConstraintSet.INVISIBLE)
mediaViewController.setUpPrevButtonInfo(true, ConstraintSet.INVISIBLE)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java
index bfbb7ce..a770ee1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java
@@ -18,7 +18,9 @@
import static android.app.StatusBarManager.WINDOW_NAVIGATION_BAR;
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
+import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_GESTURE;
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
@@ -37,6 +39,9 @@
import android.content.ComponentName;
import android.content.res.Configuration;
import android.os.Handler;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.provider.Flags;
import android.view.IWindowManager;
import android.view.accessibility.AccessibilityManager;
@@ -47,6 +52,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.accessibility.AccessibilityButtonModeObserver;
import com.android.systemui.accessibility.AccessibilityButtonTargetsObserver;
+import com.android.systemui.accessibility.AccessibilityGestureTargetsObserver;
import com.android.systemui.accessibility.SystemActions;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.dump.DumpManager;
@@ -94,6 +100,8 @@
@Mock
AccessibilityButtonTargetsObserver mAccessibilityButtonTargetObserver;
@Mock
+ AccessibilityGestureTargetsObserver mAccessibilityGestureTargetObserver;
+ @Mock
SystemActions mSystemActions;
@Mock
OverviewProxyService mOverviewProxyService;
@@ -152,6 +160,7 @@
mAccessibilityManager).addAccessibilityServicesStateChangeListener(any());
mNavBarHelper = new NavBarHelper(mContext, mAccessibilityManager,
mAccessibilityButtonModeObserver, mAccessibilityButtonTargetObserver,
+ mAccessibilityGestureTargetObserver,
mSystemActions, mOverviewProxyService, mAssistManagerLazy,
() -> Optional.of(mock(CentralSurfaces.class)), mock(KeyguardStateController.class),
mNavigationModeController, mEdgeBackGestureHandlerFactory, mWm, mUserTracker,
@@ -171,6 +180,7 @@
mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
verify(mAccessibilityButtonModeObserver, times(1)).addListener(mNavBarHelper);
verify(mAccessibilityButtonTargetObserver, times(1)).addListener(mNavBarHelper);
+ verify(mAccessibilityGestureTargetObserver, times(1)).addListener(mNavBarHelper);
verify(mAccessibilityManager, times(1)).addAccessibilityServicesStateChangeListener(
mNavBarHelper);
verify(mAssistManager, times(1)).getAssistInfoForUser(anyInt());
@@ -185,6 +195,7 @@
mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
verify(mAccessibilityButtonModeObserver, times(1)).removeListener(mNavBarHelper);
verify(mAccessibilityButtonTargetObserver, times(1)).removeListener(mNavBarHelper);
+ verify(mAccessibilityGestureTargetObserver, times(1)).removeListener(mNavBarHelper);
verify(mAccessibilityManager, times(1)).removeAccessibilityServicesStateChangeListener(
mNavBarHelper);
verify(mWm, times(1)).removeRotationWatcher(any());
@@ -353,6 +364,83 @@
verify(mEdgeBackGestureHandler, times(1)).onConfigurationChanged(any());
}
+ @Test
+ public void updateA11yState_navBarMode_softwareTargets_isClickable() {
+ when(mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode()).thenReturn(
+ ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR);
+ when(mAccessibilityManager.getAccessibilityShortcutTargets(UserShortcutType.SOFTWARE))
+ .thenReturn(createFakeShortcutTargets());
+
+ mNavBarHelper.updateA11yState();
+ long state = mNavBarHelper.getA11yButtonState();
+ assertThat(state & SYSUI_STATE_A11Y_BUTTON_CLICKABLE).isEqualTo(
+ SYSUI_STATE_A11Y_BUTTON_CLICKABLE);
+ assertThat(state & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE).isEqualTo(
+ SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE);
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
+ public void updateA11yState_gestureMode_softwareTargets_isClickable() {
+ when(mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode()).thenReturn(
+ ACCESSIBILITY_BUTTON_MODE_GESTURE);
+ when(mAccessibilityManager.getAccessibilityShortcutTargets(UserShortcutType.SOFTWARE))
+ .thenReturn(createFakeShortcutTargets());
+
+ mNavBarHelper.updateA11yState();
+ long state = mNavBarHelper.getA11yButtonState();
+ assertThat(state & SYSUI_STATE_A11Y_BUTTON_CLICKABLE).isEqualTo(
+ SYSUI_STATE_A11Y_BUTTON_CLICKABLE);
+ assertThat(state & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE).isEqualTo(
+ SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
+ public void updateA11yState_gestureNavMode_floatingButtonMode_gestureTargets_isClickable() {
+ mNavBarHelper.onNavigationModeChanged(NAV_BAR_MODE_GESTURAL);
+ when(mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode()).thenReturn(
+ ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU);
+ when(mAccessibilityManager.getAccessibilityShortcutTargets(UserShortcutType.GESTURE))
+ .thenReturn(createFakeShortcutTargets());
+
+ mNavBarHelper.updateA11yState();
+ long state = mNavBarHelper.getA11yButtonState();
+ assertThat(state & SYSUI_STATE_A11Y_BUTTON_CLICKABLE).isEqualTo(
+ SYSUI_STATE_A11Y_BUTTON_CLICKABLE);
+ assertThat(state & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE).isEqualTo(
+ SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
+ public void updateA11yState_navBarMode_gestureTargets_isNotClickable() {
+ when(mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode()).thenReturn(
+ ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR);
+ when(mAccessibilityManager.getAccessibilityShortcutTargets(UserShortcutType.GESTURE))
+ .thenReturn(createFakeShortcutTargets());
+
+ mNavBarHelper.updateA11yState();
+ long state = mNavBarHelper.getA11yButtonState();
+ assertThat(state & SYSUI_STATE_A11Y_BUTTON_CLICKABLE).isEqualTo(0);
+ assertThat(state & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE).isEqualTo(0);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_A11Y_STANDALONE_GESTURE_ENABLED)
+ public void updateA11yState_singleTarget_clickableButNotLongClickable() {
+ when(mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode()).thenReturn(
+ ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR);
+ when(mAccessibilityManager.getAccessibilityShortcutTargets(UserShortcutType.SOFTWARE))
+ .thenReturn(new ArrayList<>(List.of("a")));
+
+ mNavBarHelper.updateA11yState();
+ long state = mNavBarHelper.getA11yButtonState();
+ assertThat(state & SYSUI_STATE_A11Y_BUTTON_CLICKABLE).isEqualTo(
+ SYSUI_STATE_A11Y_BUTTON_CLICKABLE);
+ assertThat(state & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE).isEqualTo(0);
+ }
+
private List<String> createFakeShortcutTargets() {
return new ArrayList<>(List.of("a", "b", "c", "d"));
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/views/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/views/NavigationBarTest.java
index 04d140c..2905a73 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/views/NavigationBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/views/NavigationBarTest.java
@@ -85,6 +85,7 @@
import com.android.systemui.SysuiTestableContext;
import com.android.systemui.accessibility.AccessibilityButtonModeObserver;
import com.android.systemui.accessibility.AccessibilityButtonTargetsObserver;
+import com.android.systemui.accessibility.AccessibilityGestureTargetsObserver;
import com.android.systemui.accessibility.SystemActions;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.dump.DumpManager;
@@ -287,6 +288,7 @@
mNavBarHelper = spy(new NavBarHelper(mContext, mock(AccessibilityManager.class),
mock(AccessibilityButtonModeObserver.class),
mock(AccessibilityButtonTargetsObserver.class),
+ mock(AccessibilityGestureTargetsObserver.class),
mSystemActions, mOverviewProxyService,
() -> mock(AssistManager.class), () -> Optional.of(mCentralSurfaces),
mKeyguardStateController, mock(NavigationModeController.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
index ebab049..748c7d9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
@@ -497,6 +497,17 @@
assertThat(mTile.mRefreshes).isEqualTo(1);
}
+ @Test
+ public void testStaleTriggeredOnUserSwitch() {
+ mTile.clearRefreshes();
+
+ mTile.userSwitch(10);
+ mTestableLooper.processAllMessages();
+
+ assertFalse(mTile.isListening());
+ assertThat(mTile.mRefreshes).isEqualTo(1);
+ }
+
private void assertEvent(UiEventLogger.UiEventEnum eventType,
UiEventLoggerFake.FakeUiEvent fakeEvent) {
assertEquals(eventType.getId(), fakeEvent.eventId);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
index 90c70f2..5a5cdcd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
@@ -33,7 +33,6 @@
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.SceneKey
import com.android.systemui.Flags
-import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_BACK_GESTURE
import com.android.systemui.Flags.FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX
import com.android.systemui.SysuiTestCase
import com.android.systemui.ambient.touch.TouchHandler
@@ -442,7 +441,7 @@
}
@Test
- @DisableFlags(FLAG_GLANCEABLE_HUB_BACK_GESTURE, FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX)
+ @DisableFlags(FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX)
fun gestureExclusionZone_setAfterInit() =
with(kosmos) {
testScope.runTest {
@@ -468,7 +467,6 @@
}
@Test
- @DisableFlags(FLAG_GLANCEABLE_HUB_BACK_GESTURE)
@EnableFlags(FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX)
fun gestureExclusionZone_setAfterInit_fullSwipe() =
with(kosmos) {
@@ -489,7 +487,7 @@
}
@Test
- @DisableFlags(FLAG_GLANCEABLE_HUB_BACK_GESTURE, FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX)
+ @DisableFlags(FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX)
fun gestureExclusionZone_setAfterInit_rtl() =
with(kosmos) {
testScope.runTest {
@@ -514,7 +512,6 @@
}
}
- @DisableFlags(FLAG_GLANCEABLE_HUB_BACK_GESTURE)
@EnableFlags(FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX)
fun gestureExclusionZone_setAfterInit_rtl_fullSwipe() =
with(kosmos) {
@@ -535,102 +532,6 @@
}
@Test
- @EnableFlags(FLAG_GLANCEABLE_HUB_BACK_GESTURE)
- @DisableFlags(FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX)
- fun gestureExclusionZone_setAfterInit_backGestureEnabled() =
- with(kosmos) {
- testScope.runTest {
- whenever(containerView.layoutDirection).thenReturn(View.LAYOUT_DIRECTION_LTR)
- goToScene(CommunalScenes.Communal)
-
- assertThat(containerView.systemGestureExclusionRects)
- .containsExactly(
- Rect(
- /* left= */ FAKE_INSETS.left,
- /* top= */ TOP_SWIPE_REGION_WIDTH,
- /* right= */ CONTAINER_WIDTH - FAKE_INSETS.right,
- /* bottom= */ CONTAINER_HEIGHT - BOTTOM_SWIPE_REGION_WIDTH
- ),
- Rect(
- /* left= */ 0,
- /* top= */ 0,
- /* right= */ FAKE_INSETS.right,
- /* bottom= */ CONTAINER_HEIGHT
- )
- )
- }
- }
-
- @Test
- @EnableFlags(FLAG_GLANCEABLE_HUB_BACK_GESTURE, FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX)
- fun gestureExclusionZone_setAfterInit_backGestureEnabled_fullSwipe() =
- with(kosmos) {
- testScope.runTest {
- whenever(containerView.layoutDirection).thenReturn(View.LAYOUT_DIRECTION_LTR)
- goToScene(CommunalScenes.Communal)
-
- assertThat(containerView.systemGestureExclusionRects)
- .containsExactly(
- Rect(
- /* left= */ 0,
- /* top= */ 0,
- /* right= */ FAKE_INSETS.right,
- /* bottom= */ CONTAINER_HEIGHT
- )
- )
- }
- }
-
- @Test
- @EnableFlags(FLAG_GLANCEABLE_HUB_BACK_GESTURE)
- @DisableFlags(FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX)
- fun gestureExclusionZone_setAfterInit_backGestureEnabled_rtl() =
- with(kosmos) {
- testScope.runTest {
- whenever(containerView.layoutDirection).thenReturn(View.LAYOUT_DIRECTION_RTL)
- goToScene(CommunalScenes.Communal)
-
- assertThat(containerView.systemGestureExclusionRects)
- .containsExactly(
- Rect(
- /* left= */ FAKE_INSETS.left,
- /* top= */ TOP_SWIPE_REGION_WIDTH,
- /* right= */ CONTAINER_WIDTH - FAKE_INSETS.right,
- /* bottom= */ CONTAINER_HEIGHT - BOTTOM_SWIPE_REGION_WIDTH
- ),
- Rect(
- /* left= */ FAKE_INSETS.left,
- /* top= */ 0,
- /* right= */ CONTAINER_WIDTH,
- /* bottom= */ CONTAINER_HEIGHT
- )
- )
- }
- }
-
- @Test
- @EnableFlags(FLAG_GLANCEABLE_HUB_BACK_GESTURE, FLAG_HUBMODE_FULLSCREEN_VERTICAL_SWIPE_FIX)
- fun gestureExclusionZone_setAfterInit_backGestureEnabled_rtl_fullSwipe() =
- with(kosmos) {
- testScope.runTest {
- whenever(containerView.layoutDirection).thenReturn(View.LAYOUT_DIRECTION_RTL)
- goToScene(CommunalScenes.Communal)
-
- assertThat(containerView.systemGestureExclusionRects)
- .containsExactly(
- Rect(
- Rect(
- /* left= */ FAKE_INSETS.left,
- /* top= */ 0,
- /* right= */ CONTAINER_WIDTH,
- /* bottom= */ CONTAINER_HEIGHT
- )
- )
- )
- }
- }
-
- @Test
fun gestureExclusionZone_unsetWhenShadeOpen() =
with(kosmos) {
testScope.runTest {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 9b61105..b75ac2b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -108,7 +108,9 @@
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.unfold.SysUIUnfoldComponent;
import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
+import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.kotlin.JavaAdapter;
+import com.android.systemui.util.time.FakeSystemClock;
import com.google.common.truth.Truth;
@@ -175,6 +177,7 @@
mBouncerExpansionCallback;
private FakeKeyguardStateController mKeyguardStateController =
spy(new FakeKeyguardStateController());
+ private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
@Mock
private ViewRootImpl mViewRootImpl;
@@ -238,6 +241,7 @@
mock(JavaAdapter.class),
() -> mSceneInteractor,
mock(StatusBarKeyguardViewManagerInteractor.class),
+ mExecutor,
() -> mDeviceEntryInteractor) {
@Override
public ViewRootImpl getViewRootImpl() {
@@ -760,6 +764,7 @@
mock(JavaAdapter.class),
() -> mSceneInteractor,
mock(StatusBarKeyguardViewManagerInteractor.class),
+ mExecutor,
() -> mDeviceEntryInteractor) {
@Override
public ViewRootImpl getViewRootImpl() {
@@ -1084,6 +1089,9 @@
.thenReturn(KeyguardState.LOCKSCREEN);
reset(mCentralSurfaces);
+ // Advance past reattempts
+ mStatusBarKeyguardViewManager.setAttemptsToShowBouncer(10);
+
mStatusBarKeyguardViewManager.showBouncerOrKeyguard(false, false);
verify(mPrimaryBouncerInteractor).show(true);
verify(mCentralSurfaces).showKeyguard();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManagerTest.kt
index 230ddf9..48c2cc7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManagerTest.kt
@@ -56,11 +56,11 @@
runCurrent()
assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse()
- sceneRepository.isRemoteUserInteractionOngoing.value = true
+ sceneRepository.isRemoteUserInputOngoing.value = true
runCurrent()
assertThat(underTest.shouldMakeEntireScreenTouchable()).isTrue()
- sceneRepository.isRemoteUserInteractionOngoing.value = false
+ sceneRepository.isRemoteUserInputOngoing.value = false
runCurrent()
assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse()
}
@@ -71,7 +71,7 @@
testScope.runTest {
assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse()
- sceneRepository.isRemoteUserInteractionOngoing.value = true
+ sceneRepository.isRemoteUserInputOngoing.value = true
runCurrent()
assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorTest.kt
index 78028f8..26f6f31 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/SelectedUserInteractorTest.kt
@@ -3,7 +3,6 @@
import android.content.pm.UserInfo
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.Flags.FLAG_REFACTOR_GET_CURRENT_USER
import com.android.systemui.SysuiTestCase
import com.android.systemui.user.data.repository.FakeUserRepository
import com.google.common.truth.Truth.assertThat
@@ -28,7 +27,6 @@
@Test
fun getSelectedUserIdReturnsId() {
- mSetFlagsRule.enableFlags(FLAG_REFACTOR_GET_CURRENT_USER)
runBlocking { userRepository.setSelectedUserInfo(USER_INFOS[0]) }
val actualId = underTest.getSelectedUserId()
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt
deleted file mode 100644
index 9b7bca6..0000000
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorFactory.kt
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2023 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.keyguard.domain.interactor
-
-import android.content.Context
-import android.os.Handler
-import com.android.keyguard.KeyguardSecurityModel
-import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
-import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
-import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
-import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor
-import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
-import com.android.systemui.bouncer.ui.BouncerView
-import com.android.systemui.classifier.FalsingCollector
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryBiometricsAllowedInteractor
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
-import com.android.systemui.keyguard.DismissCallbackRegistry
-import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.keyguard.data.repository.FakeTrustRepository
-import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.power.data.repository.FakePowerRepository
-import com.android.systemui.power.domain.interactor.PowerInteractorFactory
-import com.android.systemui.scene.domain.interactor.SceneInteractor
-import com.android.systemui.statusbar.policy.KeyguardStateController
-import com.android.systemui.user.data.repository.FakeUserRepository
-import com.android.systemui.user.domain.interactor.SelectedUserInteractor
-import com.android.systemui.util.time.FakeSystemClock
-import kotlinx.coroutines.test.TestScope
-import org.mockito.Mockito.mock
-
-/**
- * Helper to create a new KeyguardDismissInteractor in a way that doesn't require modifying many
- * tests whenever we add a constructor param.
- */
-object KeyguardDismissInteractorFactory {
- @JvmOverloads
- @JvmStatic
- fun create(
- context: Context,
- testScope: TestScope,
- trustRepository: FakeTrustRepository = FakeTrustRepository(),
- keyguardRepository: FakeKeyguardRepository = FakeKeyguardRepository(),
- bouncerRepository: FakeKeyguardBouncerRepository = FakeKeyguardBouncerRepository(),
- keyguardUpdateMonitor: KeyguardUpdateMonitor = mock(KeyguardUpdateMonitor::class.java),
- powerRepository: FakePowerRepository = FakePowerRepository(),
- userRepository: FakeUserRepository = FakeUserRepository(),
- ): WithDependencies {
- val primaryBouncerInteractor =
- PrimaryBouncerInteractor(
- bouncerRepository,
- mock(BouncerView::class.java),
- mock(Handler::class.java),
- mock(KeyguardStateController::class.java),
- mock(KeyguardSecurityModel::class.java),
- mock(PrimaryBouncerCallbackInteractor::class.java),
- mock(FalsingCollector::class.java),
- mock(DismissCallbackRegistry::class.java),
- context,
- keyguardUpdateMonitor,
- trustRepository,
- testScope.backgroundScope,
- mock(SelectedUserInteractor::class.java),
- mock(DeviceEntryFaceAuthInteractor::class.java),
- )
- val alternateBouncerInteractor =
- AlternateBouncerInteractor(
- mock(StatusBarStateController::class.java),
- mock(KeyguardStateController::class.java),
- bouncerRepository,
- FakeFingerprintPropertyRepository(),
- FakeBiometricSettingsRepository(),
- FakeSystemClock(),
- keyguardUpdateMonitor,
- { mock(DeviceEntryBiometricsAllowedInteractor::class.java) },
- { mock(KeyguardInteractor::class.java) },
- { mock(KeyguardTransitionInteractor::class.java) },
- { mock(SceneInteractor::class.java) },
- testScope.backgroundScope,
- )
- val powerInteractorWithDeps =
- PowerInteractorFactory.create(
- repository = powerRepository,
- )
- val selectedUserInteractor = SelectedUserInteractor(repository = userRepository)
- return WithDependencies(
- trustRepository = trustRepository,
- keyguardRepository = keyguardRepository,
- bouncerRepository = bouncerRepository,
- keyguardUpdateMonitor = keyguardUpdateMonitor,
- powerRepository = powerRepository,
- userRepository = userRepository,
- interactor =
- KeyguardDismissInteractor(
- trustRepository,
- keyguardRepository,
- primaryBouncerInteractor,
- alternateBouncerInteractor,
- powerInteractorWithDeps.powerInteractor,
- selectedUserInteractor,
- ),
- )
- }
-
- data class WithDependencies(
- val trustRepository: FakeTrustRepository,
- val keyguardRepository: FakeKeyguardRepository,
- val bouncerRepository: FakeKeyguardBouncerRepository,
- val keyguardUpdateMonitor: KeyguardUpdateMonitor,
- val powerRepository: FakePowerRepository,
- val userRepository: FakeUserRepository,
- val interactor: KeyguardDismissInteractor,
- )
-}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorKosmos.kt
index f33ca95..ace1157 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorKosmos.kt
@@ -20,7 +20,10 @@
import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor
import com.android.systemui.keyguard.data.repository.keyguardRepository
import com.android.systemui.keyguard.data.repository.trustRepository
+import com.android.systemui.keyguard.dismissCallbackRegistry
import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.user.domain.interactor.selectedUserInteractor
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -29,11 +32,14 @@
val Kosmos.keyguardDismissInteractor by
Kosmos.Fixture {
KeyguardDismissInteractor(
- trustRepository = trustRepository,
+ mainDispatcher = testDispatcher,
+ scope = applicationCoroutineScope,
keyguardRepository = keyguardRepository,
primaryBouncerInteractor = primaryBouncerInteractor,
+ selectedUserInteractor = selectedUserInteractor,
+ dismissCallbackRegistry = dismissCallbackRegistry,
+ trustRepository = trustRepository,
alternateBouncerInteractor = alternateBouncerInteractor,
powerInteractor = powerInteractor,
- selectedUserInteractor = selectedUserInteractor,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeWindowModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeWindowModelKosmos.kt
index 6252d44..4b42e07 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeWindowModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeWindowModelKosmos.kt
@@ -16,7 +16,6 @@
package com.android.systemui.shade.ui.viewmodel
-import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.kosmos.Kosmos
@@ -24,6 +23,5 @@
Kosmos.Fixture {
NotificationShadeWindowModel(
keyguardTransitionInteractor,
- keyguardInteractor,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorKosmos.kt
index dbfd9de..2772d36 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorKosmos.kt
@@ -18,6 +18,7 @@
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.statusbar.notification.stack.data.repository.notificationPlaceholderRepository
import com.android.systemui.statusbar.notification.stack.data.repository.notificationViewHeightRepository
@@ -26,6 +27,7 @@
NotificationStackAppearanceInteractor(
viewHeightRepository = notificationViewHeightRepository,
placeholderRepository = notificationPlaceholderRepository,
+ sceneInteractor = sceneInteractor,
shadeInteractor = shadeInteractor,
)
}
diff --git a/services/Android.bp b/services/Android.bp
index 0006455..653cd3c3 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -136,6 +136,7 @@
":services.searchui-sources",
":services.smartspace-sources",
":services.soundtrigger-sources",
+ ":services.supervision-sources",
":services.systemcaptions-sources",
":services.translation-sources",
":services.texttospeech-sources",
@@ -237,6 +238,7 @@
"services.searchui",
"services.smartspace",
"services.soundtrigger",
+ "services.supervision",
"services.systemcaptions",
"services.translation",
"services.texttospeech",
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 19279a8..07e5f2e 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -3527,7 +3527,8 @@
// of the calling App
final long token = Binder.clearCallingIdentity();
try {
- Context targetAppContext = mContext.createPackageContext(packageName, 0);
+ Context targetAppContext = mContext.createPackageContextAsUser(packageName,
+ /* flags= */ 0, UserHandle.of(UserHandle.getUserId(originalUid)));
Intent intent = new Intent(Intent.ACTION_DEFAULT);
intent.setClassName(packageName,
appInfo.manageSpaceActivityName);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b599a2f..d80b38e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -12168,6 +12168,7 @@
pw.println(" -p: dump also private dirty memory usage.");
pw.println(" --oom: only show processes organized by oom adj.");
pw.println(" --local: only collect details locally, don't call process.");
+ pw.println(" --logstats: dump native allocator stats to log");
pw.println(" --package: interpret process arg as package, dumping all");
pw.println(" processes that have loaded that package.");
pw.println(" --checkin: dump data for a checkin");
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/AidlResponseHandler.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/AidlResponseHandler.java
index cf677d5..7b1186c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/AidlResponseHandler.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/AidlResponseHandler.java
@@ -80,13 +80,16 @@
private final AuthSessionCoordinator mAuthSessionCoordinator;
@NonNull
private final AidlResponseHandlerCallback mAidlResponseHandlerCallback;
+ @NonNull
+ private final FaceUtils mBiometricUtils;
public AidlResponseHandler(@NonNull Context context,
@NonNull BiometricScheduler scheduler, int sensorId, int userId,
@NonNull LockoutTracker lockoutTracker,
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
@NonNull AuthSessionCoordinator authSessionCoordinator,
- @NonNull AidlResponseHandlerCallback aidlResponseHandlerCallback) {
+ @NonNull AidlResponseHandlerCallback aidlResponseHandlerCallback,
+ @NonNull FaceUtils biometricUtils) {
mContext = context;
mScheduler = scheduler;
mSensorId = sensorId;
@@ -95,6 +98,7 @@
mLockoutResetDispatcher = lockoutResetDispatcher;
mAuthSessionCoordinator = authSessionCoordinator;
mAidlResponseHandlerCallback = aidlResponseHandlerCallback;
+ mBiometricUtils = biometricUtils;
}
@Override
@@ -167,8 +171,7 @@
} else {
currentUserId = client.getTargetUserId();
}
- final CharSequence name = FaceUtils.getInstance(mSensorId)
- .getUniqueName(mContext, currentUserId);
+ final CharSequence name = mBiometricUtils.getUniqueName(mContext, currentUserId);
final Face face = new Face(name, enrollmentId, mSensorId);
handleResponse(FaceEnrollClient.class, (c) -> {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
index 3eecc6d..d4ec573 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
@@ -60,7 +60,6 @@
import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback;
import com.android.server.biometrics.sensors.EnrollClient;
import com.android.server.biometrics.sensors.face.FaceService;
-import com.android.server.biometrics.sensors.face.FaceUtils;
import java.io.IOException;
import java.util.ArrayList;
@@ -85,6 +84,7 @@
private final int mMaxTemplatesPerUser;
private final boolean mDebugConsent;
private final @android.hardware.face.FaceEnrollOptions.EnrollReason int mEnrollReason;
+ private final BiometricUtils<Face> mBiometricUtils;
private final ClientMonitorCallback mPreviewHandleDeleterCallback =
new ClientMonitorCallback() {
@@ -107,7 +107,8 @@
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
int maxTemplatesPerUser, boolean debugConsent,
android.hardware.face.FaceEnrollOptions options,
- @NonNull AuthenticationStateListeners authenticationStateListeners) {
+ @NonNull AuthenticationStateListeners authenticationStateListeners,
+ @NonNull BiometricUtils<Face> biometricUtils) {
super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, opPackageName, utils,
timeoutSec, sensorId, false /* shouldVibrate */, logger, biometricContext,
BiometricFaceConstants.reasonToMetric(options.getEnrollReason()));
@@ -122,6 +123,7 @@
mDebugConsent = debugConsent;
mDisabledFeatures = disabledFeatures;
mPreviewSurface = previewSurface;
+ mBiometricUtils = biometricUtils;
Slog.w(TAG, "EnrollOptions "
+ android.hardware.face.FaceEnrollOptions.enrollReasonToString(
options.getEnrollReason()));
@@ -144,7 +146,7 @@
@Override
protected boolean hasReachedEnrollmentLimit() {
- return FaceUtils.getInstance(getSensorId()).getBiometricsForUser(getContext(),
+ return mBiometricUtils.getBiometricsForUser(getContext(),
getTargetUserId()).size() >= mMaxTemplatesPerUser;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java
index 964bf6c..c27b7c4 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java
@@ -30,7 +30,6 @@
import com.android.server.biometrics.sensors.InternalCleanupClient;
import com.android.server.biometrics.sensors.InternalEnumerateClient;
import com.android.server.biometrics.sensors.RemovalClient;
-import com.android.server.biometrics.sensors.face.FaceUtils;
import java.util.List;
import java.util.Map;
@@ -75,7 +74,7 @@
@Override
protected void onAddUnknownTemplate(int userId,
@NonNull BiometricAuthenticator.Identifier identifier) {
- FaceUtils.getInstance(getSensorId()).addBiometricForUser(
+ mBiometricUtils.addBiometricForUser(
getContext(), getTargetUserId(), (Face) identifier);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
index f0a4189..bb213bf 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
@@ -72,7 +72,6 @@
import com.android.server.biometrics.sensors.LockoutTracker;
import com.android.server.biometrics.sensors.PerformanceTracker;
import com.android.server.biometrics.sensors.SensorList;
-import com.android.server.biometrics.sensors.face.FaceUtils;
import com.android.server.biometrics.sensors.face.ServiceProvider;
import com.android.server.biometrics.sensors.face.UsageStats;
import com.android.server.biometrics.sensors.face.hidl.HidlToAidlSensorAdapter;
@@ -326,8 +325,8 @@
}
if (Build.isDebuggable()) {
- BiometricUtils<Face> utils = FaceUtils.getInstance(
- mFaceSensors.keyAt(0));
+ BiometricUtils<Face> utils = mFaceSensors.get(
+ mFaceSensors.keyAt(0)).getFaceUtilsInstance();
for (UserInfo user : UserManager.get(mContext).getAliveUsers()) {
List<Face> enrollments = utils.getBiometricsForUser(mContext, user.id);
Slog.d(getTag(), "Expecting enrollments for user " + user.id + ": "
@@ -386,7 +385,7 @@
new InvalidationRequesterClient<>(mContext, userId, sensorId,
BiometricLogger.ofUnknown(mContext),
mBiometricContext,
- FaceUtils.getInstance(sensorId));
+ mFaceSensors.get(sensorId).getFaceUtilsInstance());
scheduleForSensor(sensorId, client);
});
}
@@ -415,7 +414,8 @@
@NonNull
@Override
public List<Face> getEnrolledFaces(int sensorId, int userId) {
- return FaceUtils.getInstance(sensorId).getBiometricsForUser(mContext, userId);
+ return mFaceSensors.get(sensorId).getFaceUtilsInstance()
+ .getBiometricsForUser(mContext, userId);
}
@Override
@@ -497,13 +497,14 @@
final FaceEnrollClient client = new FaceEnrollClient(mContext,
mFaceSensors.get(sensorId).getLazySession(), token,
new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
- opPackageName, id, FaceUtils.getInstance(sensorId), disabledFeatures,
- ENROLL_TIMEOUT_SEC, previewSurface, sensorId,
+ opPackageName, id, mFaceSensors.get(sensorId).getFaceUtilsInstance(),
+ disabledFeatures, ENROLL_TIMEOUT_SEC, previewSurface, sensorId,
createLogger(BiometricsProtoEnums.ACTION_ENROLL,
BiometricsProtoEnums.CLIENT_UNKNOWN,
mAuthenticationStatsCollector),
mBiometricContext, maxTemplatesPerUser, debugConsent, options,
- mAuthenticationStateListeners);
+ mAuthenticationStateListeners,
+ mFaceSensors.get(sensorId).getFaceUtilsInstance());
scheduleForSensor(sensorId, client, mBiometricStateCallback);
});
return id;
@@ -615,7 +616,7 @@
@Override
public void scheduleRemoveAll(int sensorId, @NonNull IBinder token, int userId,
@NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName) {
- final List<Face> faces = FaceUtils.getInstance(sensorId)
+ final List<Face> faces = mFaceSensors.get(sensorId).getFaceUtilsInstance()
.getBiometricsForUser(mContext, userId);
final int[] faceIds = new int[faces.size()];
for (int i = 0; i < faces.size(); i++) {
@@ -632,7 +633,7 @@
final FaceRemovalClient client = new FaceRemovalClient(mContext,
mFaceSensors.get(sensorId).getLazySession(), token,
new ClientMonitorCallbackConverter(receiver), faceIds, userId,
- opPackageName, FaceUtils.getInstance(sensorId), sensorId,
+ opPackageName, mFaceSensors.get(sensorId).getFaceUtilsInstance(), sensorId,
createLogger(BiometricsProtoEnums.ACTION_REMOVE,
BiometricsProtoEnums.CLIENT_UNKNOWN,
mAuthenticationStatsCollector),
@@ -666,7 +667,7 @@
@NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName) {
mHandler.post(() -> {
mFaceSensors.get(sensorId).scheduleFaceUpdateActiveUserClient(userId);
- final List<Face> faces = FaceUtils.getInstance(sensorId)
+ final List<Face> faces = mFaceSensors.get(sensorId).getFaceUtilsInstance()
.getBiometricsForUser(mContext, userId);
if (faces.isEmpty()) {
Slog.w(getTag(), "Ignoring setFeature, no templates enrolled for user: " + userId);
@@ -687,7 +688,7 @@
@NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName) {
mHandler.post(() -> {
mFaceSensors.get(sensorId).scheduleFaceUpdateActiveUserClient(userId);
- final List<Face> faces = FaceUtils.getInstance(sensorId)
+ final List<Face> faces = mFaceSensors.get(sensorId).getFaceUtilsInstance()
.getBiometricsForUser(mContext, userId);
if (faces.isEmpty()) {
Slog.w(getTag(), "Ignoring getFeature, no templates enrolled for user: " + userId);
@@ -727,7 +728,7 @@
BiometricsProtoEnums.CLIENT_UNKNOWN,
mAuthenticationStatsCollector),
mBiometricContext,
- FaceUtils.getInstance(sensorId),
+ mFaceSensors.get(sensorId).getFaceUtilsInstance(),
mFaceSensors.get(sensorId).getAuthenticatorIds());
if (favorHalEnrollments) {
client.setFavorHalEnrollments();
@@ -768,7 +769,7 @@
JSONArray sets = new JSONArray();
for (UserInfo user : UserManager.get(mContext).getUsers()) {
final int userId = user.getUserHandle().getIdentifier();
- final int c = FaceUtils.getInstance(sensorId)
+ final int c = mFaceSensors.get(sensorId).getFaceUtilsInstance()
.getBiometricsForUser(mContext, userId).size();
JSONObject set = new JSONObject();
set.put("id", userId);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
index b0e7575..6f95349 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
@@ -158,7 +158,7 @@
Slog.e(TAG, "Face sensor hardware unavailable.");
mCurrentSession = null;
}
- });
+ }, getFaceUtilsInstance());
return Sensor.this.getStartUserClient(resultController, sensorId,
newUserId, provider);
@@ -280,8 +280,7 @@
final long userToken = proto.start(SensorStateProto.USER_STATES);
proto.write(UserStateProto.USER_ID, userId);
proto.write(UserStateProto.NUM_ENROLLED,
- FaceUtils.getInstance(mSensorProperties.sensorId)
- .getBiometricsForUser(mContext, userId).size());
+ getFaceUtilsInstance().getBiometricsForUser(mContext, userId).size());
proto.end(userToken);
}
@@ -358,4 +357,8 @@
Supplier<AidlSession> lazySession) {
mLazySession = lazySession;
}
+
+ public FaceUtils getFaceUtilsInstance() {
+ return FaceUtils.getInstance(mSensorProperties.sensorId);
+ }
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSensorAdapter.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSensorAdapter.java
index 9a4c29d..444a6d1 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSensorAdapter.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSensorAdapter.java
@@ -159,6 +159,11 @@
}
@Override
+ public FaceUtils getFaceUtilsInstance() {
+ return FaceUtils.getLegacyInstance(getSensorProperties().sensorId);
+ }
+
+ @Override
protected LockoutTracker getLockoutTracker(boolean forAuth) {
return mLockoutTracker;
}
@@ -180,7 +185,8 @@
mLockoutTracker,
mLockoutResetDispatcher,
mAuthSessionCoordinator,
- mAidlResponseHandlerCallback);
+ mAidlResponseHandlerCallback,
+ getFaceUtilsInstance());
}
private IBiometricsFace getIBiometricsFace() {
@@ -247,8 +253,7 @@
return new FaceUpdateActiveUserClient(getContext(), this::getIBiometricsFace,
mUserStartedCallback, userId, TAG, getSensorProperties().sensorId,
BiometricLogger.ofUnknown(getContext()), getBiometricContext(),
- !FaceUtils.getInstance(getSensorProperties().sensorId).getBiometricsForUser(
- getContext(), userId).isEmpty(),
+ !getFaceUtilsInstance().getBiometricsForUser(getContext(), userId).isEmpty(),
getAuthenticatorIds());
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlResponseHandler.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlResponseHandler.java
index 6d1715f..80b7cde 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlResponseHandler.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlResponseHandler.java
@@ -80,13 +80,16 @@
private final AuthSessionCoordinator mAuthSessionCoordinator;
@NonNull
private final AidlResponseHandlerCallback mAidlResponseHandlerCallback;
+ @NonNull
+ private final FingerprintUtils mBiometricUtils;
public AidlResponseHandler(@NonNull Context context,
@NonNull BiometricScheduler scheduler, int sensorId, int userId,
@NonNull LockoutTracker lockoutTracker,
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
@NonNull AuthSessionCoordinator authSessionCoordinator,
- @NonNull AidlResponseHandlerCallback aidlResponseHandlerCallback) {
+ @NonNull AidlResponseHandlerCallback aidlResponseHandlerCallback,
+ @NonNull FingerprintUtils biometricUtils) {
mContext = context;
mScheduler = scheduler;
mSensorId = sensorId;
@@ -95,6 +98,7 @@
mLockoutResetDispatcher = lockoutResetDispatcher;
mAuthSessionCoordinator = authSessionCoordinator;
mAidlResponseHandlerCallback = aidlResponseHandlerCallback;
+ mBiometricUtils = biometricUtils;
}
@Override
@@ -158,8 +162,7 @@
} else {
currentUserId = client.getTargetUserId();
}
- final CharSequence name = FingerprintUtils.getInstance(mSensorId)
- .getUniqueName(mContext, currentUserId);
+ final CharSequence name = mBiometricUtils.getUniqueName(mContext, currentUserId);
final Fingerprint fingerprint = new Fingerprint(name, currentUserId,
enrollmentId, mSensorId);
handleResponse(FingerprintEnrollClient.class, (c) -> {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java
index 1fc5179..40b8a45 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java
@@ -81,7 +81,7 @@
@Override
protected void onAddUnknownTemplate(int userId,
@NonNull BiometricAuthenticator.Identifier identifier) {
- FingerprintUtils.getInstance(getSensorId()).addBiometricForUser(
+ mBiometricUtils.addBiometricForUser(
getContext(), getTargetUserId(), (Fingerprint) identifier);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
index 12baf00..9edaa4e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -79,7 +79,6 @@
import com.android.server.biometrics.sensors.LockoutTracker;
import com.android.server.biometrics.sensors.PerformanceTracker;
import com.android.server.biometrics.sensors.SensorList;
-import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
import com.android.server.biometrics.sensors.fingerprint.PowerPressHandler;
import com.android.server.biometrics.sensors.fingerprint.ServiceProvider;
@@ -354,8 +353,9 @@
}
if (Build.isDebuggable()) {
- BiometricUtils<Fingerprint> utils = FingerprintUtils.getInstance(
- mFingerprintSensors.keyAt(0));
+ final int sensorId = mFingerprintSensors.keyAt(0);
+ final BiometricUtils<Fingerprint> utils = mFingerprintSensors.get(sensorId)
+ .getFingerprintUtilsInstance();
for (UserInfo user : UserManager.get(mContext).getAliveUsers()) {
List<Fingerprint> enrollments = utils.getBiometricsForUser(mContext, user.id);
Slog.d(getTag(), "Expecting enrollments for user " + user.id + ": "
@@ -442,7 +442,7 @@
new InvalidationRequesterClient<>(mContext, userId, sensorId,
BiometricLogger.ofUnknown(mContext),
mBiometricContext,
- FingerprintUtils.getInstance(sensorId));
+ mFingerprintSensors.get(sensorId).getFingerprintUtilsInstance());
scheduleForSensor(sensorId, client);
});
}
@@ -507,7 +507,7 @@
final FingerprintEnrollClient client = new FingerprintEnrollClient(mContext,
mFingerprintSensors.get(sensorId).getLazySession(), token, id,
new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
- opPackageName, FingerprintUtils.getInstance(sensorId),
+ opPackageName, mFingerprintSensors.get(sensorId).getFingerprintUtilsInstance(),
sensorId, createLogger(BiometricsProtoEnums.ACTION_ENROLL,
BiometricsProtoEnums.CLIENT_UNKNOWN, mAuthenticationStatsCollector),
mBiometricContext,
@@ -638,8 +638,8 @@
public void scheduleRemoveAll(int sensorId, @NonNull IBinder token,
@NonNull IFingerprintServiceReceiver receiver, int userId,
@NonNull String opPackageName) {
- final List<Fingerprint> fingers = FingerprintUtils.getInstance(sensorId)
- .getBiometricsForUser(mContext, userId);
+ final List<Fingerprint> fingers = mFingerprintSensors.get(sensorId)
+ .getFingerprintUtilsInstance().getBiometricsForUser(mContext, userId);
final int[] fingerIds = new int[fingers.size()];
for (int i = 0; i < fingers.size(); i++) {
fingerIds[i] = fingers.get(i).getBiometricId();
@@ -655,11 +655,10 @@
final FingerprintRemovalClient client = new FingerprintRemovalClient(mContext,
mFingerprintSensors.get(sensorId).getLazySession(), token,
new ClientMonitorCallbackConverter(receiver), fingerprintIds, userId,
- opPackageName, FingerprintUtils.getInstance(sensorId), sensorId,
- createLogger(BiometricsProtoEnums.ACTION_REMOVE,
- BiometricsProtoEnums.CLIENT_UNKNOWN,
- mAuthenticationStatsCollector),
- mBiometricContext,
+ opPackageName, mFingerprintSensors.get(sensorId).getFingerprintUtilsInstance(),
+ sensorId, createLogger(BiometricsProtoEnums.ACTION_REMOVE,
+ BiometricsProtoEnums.CLIENT_UNKNOWN,
+ mAuthenticationStatsCollector), mBiometricContext,
mFingerprintSensors.get(sensorId).getAuthenticatorIds());
scheduleForSensor(sensorId, client, mBiometricStateCallback);
});
@@ -683,7 +682,7 @@
BiometricsProtoEnums.CLIENT_UNKNOWN,
mAuthenticationStatsCollector),
mBiometricContext,
- FingerprintUtils.getInstance(sensorId),
+ mFingerprintSensors.get(sensorId).getFingerprintUtilsInstance(),
mFingerprintSensors.get(sensorId).getAuthenticatorIds());
if (favorHalEnrollments) {
client.setFavorHalEnrollments();
@@ -706,14 +705,15 @@
@Override
public void rename(int sensorId, int fingerId, int userId, @NonNull String name) {
- FingerprintUtils.getInstance(sensorId)
+ mFingerprintSensors.get(sensorId).getFingerprintUtilsInstance()
.renameBiometricForUser(mContext, userId, fingerId, name);
}
@NonNull
@Override
public List<Fingerprint> getEnrolledFingerprints(int sensorId, int userId) {
- return FingerprintUtils.getInstance(sensorId).getBiometricsForUser(mContext, userId);
+ return mFingerprintSensors.get(sensorId).getFingerprintUtilsInstance()
+ .getBiometricsForUser(mContext, userId);
}
@Override
@@ -842,7 +842,7 @@
JSONArray sets = new JSONArray();
for (UserInfo user : UserManager.get(mContext).getUsers()) {
final int userId = user.getUserHandle().getIdentifier();
- final int c = FingerprintUtils.getInstance(sensorId)
+ final int c = mFingerprintSensors.get(sensorId).getFingerprintUtilsInstance()
.getBiometricsForUser(mContext, userId).size();
JSONObject set = new JSONObject();
set.put("id", userId);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
index 1c6dfe0..d12d7b2 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
@@ -170,7 +170,7 @@
"Fingerprint sensor hardware unavailable.");
mCurrentSession = null;
}
- });
+ }, getFingerprintUtilsInstance());
return Sensor.this.getStartUserClient(resultController, sensorId,
newUserId);
@@ -187,7 +187,7 @@
+ halInterfaceVersion);
mCurrentSession = new AidlSession(halInterfaceVersion,
newSession, userIdStarted, resultController);
- if (FingerprintUtils.getInstance(sensorId)
+ if (getFingerprintUtilsInstance()
.isInvalidationInProgress(mContext, userIdStarted)) {
Slog.w(TAG,
"Scheduling unfinished invalidation request for "
@@ -307,9 +307,8 @@
final long userToken = proto.start(SensorStateProto.USER_STATES);
proto.write(UserStateProto.USER_ID, userId);
- proto.write(UserStateProto.NUM_ENROLLED,
- FingerprintUtils.getInstance(mSensorProperties.sensorId)
- .getBiometricsForUser(mContext, userId).size());
+ proto.write(UserStateProto.NUM_ENROLLED, getFingerprintUtilsInstance()
+ .getBiometricsForUser(mContext, userId).size());
proto.end(userToken);
}
@@ -386,4 +385,8 @@
public FingerprintProvider getProvider() {
return mProvider;
}
+
+ public FingerprintUtils getFingerprintUtilsInstance() {
+ return FingerprintUtils.getInstance(mSensorProperties.sensorId);
+ }
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/HidlToAidlSensorAdapter.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/HidlToAidlSensorAdapter.java
index 3214b6d..8f52d00 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/HidlToAidlSensorAdapter.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/HidlToAidlSensorAdapter.java
@@ -148,6 +148,11 @@
}
@Override
+ public FingerprintUtils getFingerprintUtilsInstance() {
+ return FingerprintUtils.getLegacyInstance(getSensorProperties().sensorId);
+ }
+
+ @Override
@Nullable
@VisibleForTesting
protected AidlSession getSessionForUser(int userId) {
@@ -186,7 +191,8 @@
mLockoutTracker,
mLockoutResetDispatcher,
mAuthSessionCoordinator,
- mAidlResponseHandlerCallback);
+ mAidlResponseHandlerCallback,
+ getFingerprintUtilsInstance());
}
@VisibleForTesting IBiometricsFingerprint getIBiometricsFingerprint() {
@@ -266,8 +272,7 @@
() -> getSession().getSession(), newUserId, TAG,
getSensorProperties().sensorId, BiometricLogger.ofUnknown(getContext()),
getBiometricContext(), () -> mCurrentUserId,
- !FingerprintUtils.getInstance(getSensorProperties().sensorId)
- .getBiometricsForUser(getContext(),
+ !getFingerprintUtilsInstance().getBiometricsForUser(getContext(),
newUserId).isEmpty(), getAuthenticatorIds(), forceUpdateAuthenticatorIds,
mUserStartedCallback);
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 37e7cfc..da3ada8 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -256,6 +256,7 @@
import com.android.server.stats.pull.StatsPullAtomService;
import com.android.server.statusbar.StatusBarManagerService;
import com.android.server.storage.DeviceStorageMonitorService;
+import com.android.server.supervision.SupervisionService;
import com.android.server.systemcaptions.SystemCaptionsManagerService;
import com.android.server.telecom.TelecomLoaderService;
import com.android.server.testharness.TestHarnessModeService;
@@ -1598,6 +1599,12 @@
mSystemServiceManager.startService(ROLE_SERVICE_CLASS);
t.traceEnd();
+ if (android.app.supervision.flags.Flags.supervisionApi()) {
+ t.traceBegin("StartSupervisionService");
+ mSystemServiceManager.startService(SupervisionService.Lifecycle.class);
+ t.traceEnd();
+ }
+
if (!isTv) {
t.traceBegin("StartVibratorManagerService");
mSystemServiceManager.startService(VibratorManagerService.Lifecycle.class);
diff --git a/services/supervision/Android.bp b/services/supervision/Android.bp
new file mode 100644
index 0000000..93a0c4a
--- /dev/null
+++ b/services/supervision/Android.bp
@@ -0,0 +1,22 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+filegroup {
+ name: "services.supervision-sources",
+ srcs: ["java/**/*.java"],
+ path: "java",
+ visibility: ["//frameworks/base/services"],
+}
+
+java_library_static {
+ name: "services.supervision",
+ defaults: ["platform_service_defaults"],
+ srcs: [":services.supervision-sources"],
+ libs: ["services.core"],
+}
diff --git a/services/supervision/java/com/android/server/supervision/SupervisionService.java b/services/supervision/java/com/android/server/supervision/SupervisionService.java
new file mode 100644
index 0000000..a4ef629
--- /dev/null
+++ b/services/supervision/java/com/android/server/supervision/SupervisionService.java
@@ -0,0 +1,67 @@
+/*
+ * 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.server.supervision;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.supervision.ISupervisionManager;
+import android.content.Context;
+
+
+import com.android.internal.util.DumpUtils;
+import com.android.server.SystemService;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/** Service for handling system supervision. */
+public class SupervisionService extends ISupervisionManager.Stub {
+ private static final String LOG_TAG = "SupervisionService";
+
+ private final Context mContext;
+
+ public SupervisionService(Context context) {
+ mContext = context.createAttributionContext("SupervisionService");
+ }
+
+ @Override
+ public boolean isSupervisionEnabled() {
+ return false;
+ }
+
+ @Override
+ protected void dump(@NonNull FileDescriptor fd,
+ @NonNull PrintWriter fout, @Nullable String[] args) {
+ if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, fout)) return;
+
+ fout.println("Supervision enabled: " + isSupervisionEnabled());
+ }
+
+ public static class Lifecycle extends SystemService {
+ private final SupervisionService mSupervisionService;
+
+ public Lifecycle(@NonNull Context context) {
+ super(context);
+ mSupervisionService = new SupervisionService(context);
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(Context.SUPERVISION_SERVICE, mSupervisionService);
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClientTest.java
index f477682..6ac95c8 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClientTest.java
@@ -109,6 +109,8 @@
private AidlResponseHandler mAidlResponseHandler;
@Mock
private AuthenticationStateListeners mAuthenticationStateListeners;
+ @Mock
+ private BiometricUtils<Face> mBiometricUtils;
@Captor
private ArgumentCaptor<OperationContextExt> mOperationContextCaptor;
@Captor
@@ -213,7 +215,7 @@
mBiometricLogger, mBiometricContext, 5 /* maxTemplatesPerUser */,
true /* debugConsent */,
(new FaceEnrollOptions.Builder()).setEnrollReason(ENROLL_SOURCE).build(),
- mAuthenticationStateListeners);
+ mAuthenticationStateListeners, mBiometricUtils);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java
index 6780e60..bf97086 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java
@@ -50,6 +50,7 @@
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.LockoutTracker;
import com.android.server.biometrics.sensors.UserSwitchProvider;
+import com.android.server.biometrics.sensors.face.FaceUtils;
import org.junit.Before;
import org.junit.Test;
@@ -90,6 +91,8 @@
private AidlSession mCurrentSession;
@Mock
private AidlResponseHandler.AidlResponseHandlerCallback mAidlResponseHandlerCallback;
+ @Mock
+ private FaceUtils mBiometricUtils;
private final TestLooper mLooper = new TestLooper();
private final LockoutCache mLockoutCache = new LockoutCache();
@@ -114,7 +117,7 @@
mUserSwitchProvider);
mHalCallback = new AidlResponseHandler(mContext, mScheduler, SENSOR_ID, USER_ID,
mLockoutCache, mLockoutResetDispatcher, mAuthSessionCoordinator,
- mAidlResponseHandlerCallback);
+ mAidlResponseHandlerCallback, mBiometricUtils);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSensorAdapterTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSensorAdapterTest.java
index 4248e5e..24ce569 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSensorAdapterTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/HidlToAidlSensorAdapterTest.java
@@ -206,7 +206,7 @@
new int[]{} /* disabledFeatures */, ENROLL_TIMEOUT_SEC, null /* previewSurface */,
SENSOR_ID, mLogger, mBiometricContext, 1 /* maxTemplatesPerUser */,
false /* debugConsent */, (new FaceEnrollOptions.Builder()).build(),
- mAuthenticationStateListeners));
+ mAuthenticationStateListeners, mBiometricUtils));
mLooper.dispatchAll();
verify(mAidlResponseHandlerCallback).onEnrollSuccess();
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/SensorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/SensorTest.java
index 698db2e..4ef8782 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/SensorTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/SensorTest.java
@@ -51,6 +51,7 @@
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.LockoutTracker;
import com.android.server.biometrics.sensors.UserSwitchProvider;
+import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
import org.junit.Before;
@@ -96,6 +97,8 @@
private HandlerThread mThread;
@Mock
AidlResponseHandler.AidlResponseHandlerCallback mAidlResponseHandlerCallback;
+ @Mock
+ private FingerprintUtils mBiometricUtils;
private final TestLooper mLooper = new TestLooper();
private final LockoutCache mLockoutCache = new LockoutCache();
@@ -121,7 +124,7 @@
mUserSwitchProvider);
mHalCallback = new AidlResponseHandler(mContext, mScheduler, SENSOR_ID, USER_ID,
mLockoutCache, mLockoutResetDispatcher, mAuthSessionCoordinator,
- mAidlResponseHandlerCallback);
+ mAidlResponseHandlerCallback, mBiometricUtils);
}
@Test