summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/hardware/biometrics/BiometricStateListener.java (renamed from core/java/android/hardware/fingerprint/FingerprintStateListener.java)17
-rw-r--r--core/java/android/hardware/biometrics/IBiometricStateListener.aidl (renamed from core/java/android/hardware/fingerprint/IFingerprintStateListener.aidl)12
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintManager.java9
-rw-r--r--core/java/android/hardware/fingerprint/IFingerprintService.aidl6
-rw-r--r--core/java/android/net/vcn/VcnManager.java15
-rw-r--r--packages/SettingsLib/Utils/Android.bp1
-rw-r--r--packages/SettingsLib/Utils/src/com/android/settingslib/utils/BuildCompatUtils.java37
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java5
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java5
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/Utils.java4
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java7
-rw-r--r--packages/SystemUI/res/layout/media_smartspace_recommendations.xml153
-rw-r--r--packages/SystemUI/res/values/dimens.xml12
-rw-r--r--packages/SystemUI/res/values/strings.xml6
-rw-r--r--packages/SystemUI/res/values/styles.xml23
-rw-r--r--packages/SystemUI/res/xml/media_recommendation_collapsed.xml90
-rw-r--r--packages/SystemUI/res/xml/media_recommendation_expanded.xml111
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java2
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java55
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java11
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java185
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java217
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt221
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt5
-rw-r--r--services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java6
-rw-r--r--services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java9
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java3
-rw-r--r--services/companion/java/com/android/server/companion/presence/BleCompanionDeviceScanner.java2
-rw-r--r--services/core/java/com/android/server/BinaryTransparencyService.java1
-rw-r--r--services/core/java/com/android/server/VcnManagementService.java157
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java146
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java35
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java150
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java22
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java6
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java28
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java10
-rw-r--r--services/core/java/com/android/server/location/gnss/hal/GnssNative.java4
-rw-r--r--services/core/java/com/android/server/policy/SideFpsEventHandler.java37
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java (renamed from services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallbackTest.java)19
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/policy/SideFpsEventHandlerTest.java42
-rw-r--r--tests/vcn/java/com/android/server/VcnManagementServiceTest.java107
63 files changed, 1250 insertions, 966 deletions
diff --git a/core/java/android/hardware/fingerprint/FingerprintStateListener.java b/core/java/android/hardware/biometrics/BiometricStateListener.java
index 551f5120ce2a..2ac0c1edaef0 100644
--- a/core/java/android/hardware/fingerprint/FingerprintStateListener.java
+++ b/core/java/android/hardware/biometrics/BiometricStateListener.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.hardware.fingerprint;
+package android.hardware.biometrics;
import android.annotation.IntDef;
@@ -22,10 +22,10 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
- * Interface for handling state changes in fingerprint-related events.
+ * Interface for handling state changes in biometric sensors.
* @hide
*/
-public abstract class FingerprintStateListener extends IFingerprintStateListener.Stub {
+public abstract class BiometricStateListener extends IBiometricStateListener.Stub {
// Operation has not started yet.
public static final int STATE_IDLE = 0;
@@ -43,16 +43,19 @@ public abstract class FingerprintStateListener extends IFingerprintStateListener
@IntDef({STATE_IDLE, STATE_ENROLLING, STATE_KEYGUARD_AUTH, STATE_BP_AUTH, STATE_AUTH_OTHER})
@Retention(RetentionPolicy.SOURCE)
- public @interface State {}
+ public @interface State {
+ }
/**
* Defines behavior in response to state update
- * @param newState new state of fingerprint sensor
+ * @param newState new state of the biometric sensor
*/
- public void onStateChanged(@FingerprintStateListener.State int newState) {}
+ public void onStateChanged(@BiometricStateListener.State int newState) {
+ }
/**
* Invoked when enrollment state changes for the specified user
*/
- public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) {}
+ public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) {
+ }
}
diff --git a/core/java/android/hardware/fingerprint/IFingerprintStateListener.aidl b/core/java/android/hardware/biometrics/IBiometricStateListener.aidl
index 1aa6fa197066..5bdced034017 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintStateListener.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricStateListener.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,16 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.hardware.fingerprint;
-
-import android.hardware.fingerprint.Fingerprint;
+package android.hardware.biometrics;
/**
- * Communication channel for FingerprintManager to register the FingerprintStateListener
- * in FingerprintService.
+ * Communication channel between <Biometric>Manager and <Biometric>Service for passing the
+ * listener.
* @hide
*/
-oneway interface IFingerprintStateListener {
+oneway interface IBiometricStateListener {
void onStateChanged(int newState);
void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments);
}
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 60c4b523094e..28f1f02b7a93 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -45,6 +45,7 @@ import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricFingerprintConstants;
import android.hardware.biometrics.BiometricPrompt;
+import android.hardware.biometrics.BiometricStateListener;
import android.hardware.biometrics.BiometricTestSession;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
import android.hardware.biometrics.SensorProperties;
@@ -918,13 +919,13 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
/**
- * Forwards FingerprintStateListener to FingerprintService
- * @param listener new FingerprintStateListener being added
+ * Forwards BiometricStateListener to FingerprintService
+ * @param listener new BiometricStateListener being added
* @hide
*/
- public void registerFingerprintStateListener(@NonNull FingerprintStateListener listener) {
+ public void registerBiometricStateListener(@NonNull BiometricStateListener listener) {
try {
- mService.registerFingerprintStateListener(listener);
+ mService.registerBiometricStateListener(listener);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index d60bb6ef1543..0b6344617663 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -17,13 +17,13 @@ package android.hardware.fingerprint;
import android.hardware.biometrics.IBiometricSensorReceiver;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
+import android.hardware.biometrics.IBiometricStateListener;
import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.fingerprint.IFingerprintClientActiveCallback;
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
-import android.hardware.fingerprint.IFingerprintStateListener;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.hardware.fingerprint.ISidefpsController;
import android.hardware.fingerprint.Fingerprint;
@@ -169,6 +169,6 @@ interface IFingerprintService {
// Sets the controller for managing the SideFPS overlay.
void setSidefpsController(in ISidefpsController controller);
- // Registers FingerprintStateListener in list stored by FingerprintService.
- void registerFingerprintStateListener(IFingerprintStateListener listener);
+ // Registers BiometricStateListener.
+ void registerBiometricStateListener(IBiometricStateListener listener);
}
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
index 390c3b9453c2..f1b110ab29c8 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -172,11 +172,11 @@ public class VcnManager {
*
* <p>An app that has carrier privileges for any of the subscriptions in the given group may
* clear a VCN configuration. This API is ONLY permitted for callers running as the primary
- * user. Any active VCN will be torn down.
+ * user. Any active VCN associated with this configuration will be torn down.
*
* @param subscriptionGroup the subscription group that the configuration should be applied to
- * @throws SecurityException if the caller does not have carrier privileges, or is not running
- * as the primary user
+ * @throws SecurityException if the caller does not have carrier privileges, is not the owner of
+ * the associated configuration, or is not running as the primary user
* @throws IOException if the configuration failed to be cleared from disk. This may occur due
* to temporary disk errors, or more permanent conditions such as a full disk.
*/
@@ -196,8 +196,13 @@ public class VcnManager {
/**
* Retrieves the list of Subscription Groups for which a VCN Configuration has been set.
*
- * <p>The returned list will include only subscription groups for which the carrier app is
- * privileged, and which have an associated {@link VcnConfig}.
+ * <p>The returned list will include only subscription groups for which an associated {@link
+ * VcnConfig} exists, and the app is either:
+ *
+ * <ul>
+ * <li>Carrier privileged for that subscription group, or
+ * <li>Is the provisioning package of the config
+ * </ul>
*
* @throws SecurityException if the caller is not running as the primary user
*/
diff --git a/packages/SettingsLib/Utils/Android.bp b/packages/SettingsLib/Utils/Android.bp
index 7d5eb69190b6..d64fe7fb0009 100644
--- a/packages/SettingsLib/Utils/Android.bp
+++ b/packages/SettingsLib/Utils/Android.bp
@@ -15,6 +15,7 @@ android_library {
static_libs: [
"androidx.annotation_annotation",
+ "modules-utils-build",
],
sdk_version: "system_current",
diff --git a/packages/SettingsLib/Utils/src/com/android/settingslib/utils/BuildCompatUtils.java b/packages/SettingsLib/Utils/src/com/android/settingslib/utils/BuildCompatUtils.java
index 88e242340dee..fc945040fc83 100644
--- a/packages/SettingsLib/Utils/src/com/android/settingslib/utils/BuildCompatUtils.java
+++ b/packages/SettingsLib/Utils/src/com/android/settingslib/utils/BuildCompatUtils.java
@@ -17,10 +17,11 @@
package com.android.settingslib.utils;
import android.os.Build;
-import android.os.Build.VERSION;
import androidx.annotation.ChecksSdkIntAtLeast;
+import com.android.modules.utils.build.SdkLevel;
+
/**
* An util class to check whether the current OS version is higher or equal to sdk version of
* device.
@@ -34,7 +35,7 @@ public final class BuildCompatUtils {
*/
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.S)
public static boolean isAtLeastS() {
- return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S;
+ return SdkLevel.isAtLeastS();
}
/**
@@ -44,41 +45,17 @@ public final class BuildCompatUtils {
*/
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.S_V2)
public static boolean isAtLeastSV2() {
- return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S_V2;
+ return SdkLevel.isAtLeastSv2();
}
/**
- * Implementation of BuildCompat.isAtLeast*() suitable for use in Settings
- *
- * <p>This still should try using BuildCompat.isAtLeastR() as source of truth, but also checking
- * for VERSION_SDK_INT and VERSION.CODENAME in case when BuildCompat implementation returned
- * false. Note that both checks should be >= and not = to make sure that when Android version
- * increases (i.e., from R to S), this does not stop working.
- *
- * <p>Supported configurations:
- *
- * <ul>
- * <li>For current Android release: when new API is not finalized yet (CODENAME = "Tiramisu",
- * SDK_INT = 32)
- * <li>For current Android release: when new API is finalized (CODENAME = "REL", SDK_INT = 33)
- * <li>For next Android release (CODENAME = "U", SDK_INT = 34+)
- * </ul>
- *
- * <p>Note that Build.VERSION_CODES.S cannot be used here until final SDK is available, because
- * it is equal to Build.VERSION_CODES.CUR_DEVELOPMENT before API finalization.
+ * Implementation of BuildCompat.isAtLeastT() suitable for use in Settings
*
* @return Whether the current OS version is higher or equal to T.
*/
+ @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.TIRAMISU)
public static boolean isAtLeastT() {
- if (!isAtLeastS()) {
- return false;
- }
-
- return (VERSION.CODENAME.equals("REL") && VERSION.SDK_INT >= 33)
- || (VERSION.CODENAME.length() >= 1
- && VERSION.CODENAME.toUpperCase().charAt(0) >= 'T'
- && VERSION.CODENAME.toUpperCase().charAt(0) <= 'Z')
- || (Build.VERSION.CODENAME.equals("Tiramisu") && Build.VERSION.SDK_INT >= 32);
+ return SdkLevel.isAtLeastT();
}
private BuildCompatUtils() {}
diff --git a/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java b/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java
index 0f340239cd24..5c9ec4b3e6f1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/DeviceInfoUtils.java
@@ -36,7 +36,8 @@ import android.util.Log;
import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;
-import androidx.core.os.BuildCompat;
+
+import com.android.modules.utils.build.SdkLevel;
import java.io.BufferedReader;
import java.io.FileReader;
@@ -220,7 +221,7 @@ public class DeviceInfoUtils {
}
private static String getRawPhoneNumber(Context context, int subscriptionId) {
- if (BuildCompat.isAtLeastT()) {
+ if (SdkLevel.isAtLeastT()) {
return getRawPhoneNumberFromT(context, subscriptionId);
} else {
final TelephonyManager telephonyManager = context.getSystemService(
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
index 3a4a8d27b2f3..08aeeaec8bb0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedPreferenceHelper.java
@@ -31,10 +31,11 @@ import android.util.TypedValue;
import android.widget.TextView;
import androidx.annotation.RequiresApi;
-import androidx.core.os.BuildCompat;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
+import com.android.modules.utils.build.SdkLevel;
+
/**
* Helper class for managing settings preferences that can be disabled
* by device admins via user restrictions.
@@ -105,7 +106,7 @@ public class RestrictedPreferenceHelper {
if (mDisabledSummary) {
final TextView summaryView = (TextView) holder.findViewById(android.R.id.summary);
if (summaryView != null) {
- final CharSequence disabledText = BuildCompat.isAtLeastT()
+ final CharSequence disabledText = SdkLevel.isAtLeastT()
? getDisabledByAdminUpdatableString()
: mContext.getString(R.string.disabled_by_admin_summary_text);
if (mDisabledByAdmin) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index aaa011458258..a7f12022e172 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -45,12 +45,12 @@ import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.graphics.drawable.RoundedBitmapDrawable;
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
-import androidx.core.os.BuildCompat;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.UserIcons;
import com.android.launcher3.icons.BaseIconFactory.IconOptions;
import com.android.launcher3.icons.IconFactory;
+import com.android.modules.utils.build.SdkLevel;
import com.android.settingslib.drawable.UserIconDrawable;
import com.android.settingslib.fuelgauge.BatteryStatus;
@@ -130,7 +130,7 @@ public class Utils {
String name = info != null ? info.name : null;
if (info.isManagedProfile()) {
// We use predefined values for managed profiles
- return BuildCompat.isAtLeastT()
+ return SdkLevel.isAtLeastT()
? getUpdatableManagedUserTitle(context)
: context.getString(R.string.managed_user_title);
} else if (info.isGuest()) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
index 91d7388bc46d..17ac4307d6a6 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
@@ -47,7 +47,8 @@ import android.os.UserHandle;
import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;
-import androidx.core.os.BuildCompat;
+
+import com.android.modules.utils.build.SdkLevel;
/**
* Converts the user avatar icon to a circularly clipped one with an optional badge and frame
@@ -87,7 +88,7 @@ public class UserIconDrawable extends Drawable implements Drawable.Callback {
* @return drawable containing just the badge
*/
public static Drawable getManagedUserDrawable(Context context) {
- if (BuildCompat.isAtLeastT()) {
+ if (SdkLevel.isAtLeastT()) {
return getUpdatableManagedUserDrawable(context);
} else {
return getDrawableForDisplayDensity(
@@ -226,7 +227,7 @@ public class UserIconDrawable extends Drawable implements Drawable.Callback {
}
private static Drawable getManagementBadge(Context context) {
- if (BuildCompat.isAtLeastT()) {
+ if (SdkLevel.isAtLeastT()) {
return getUpdatableManagementBadge(context);
} else {
return getDrawableForDisplayDensity(
diff --git a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml
index c3fc66952395..3c3bc63906f0 100644
--- a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml
+++ b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml
@@ -22,160 +22,87 @@
android:id="@+id/media_recommendations"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingStart="@dimen/qs_media_padding"
- android:paddingEnd="@dimen/qs_media_padding"
android:clipChildren="false"
android:clipToPadding="false"
android:forceHasOverlappingRendering="false"
android:background="@drawable/qs_media_background"
android:theme="@style/MediaPlayer">
- <androidx.constraintlayout.widget.Guideline
- android:id="@+id/media_vertical_start_guideline"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- app:layout_constraintGuide_percent="0.25" />
-
- <androidx.constraintlayout.widget.Guideline
- android:id="@+id/media_horizontal_center_guideline"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- app:layout_constraintGuide_percent="0.5" />
+ <!-- This view just ensures the full media player is a certain height. -->
+ <View
+ android:id="@+id/sizing_view"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/qs_media_session_height_expanded" />
<com.android.internal.widget.CachingIconView
android:id="@+id/recommendation_card_icon"
- android:layout_width="@dimen/qs_media_icon_size"
- android:layout_height="@dimen/qs_media_icon_size"
- android:layout_marginTop="@dimen/qs_media_padding"
- android:src="@drawable/ic_headset"
- style="@style/MediaPlayer.AppIcon"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toStartOf="@id/media_vertical_start_guideline"
- app:layout_constraintHorizontal_bias="0"/>
-
- <TextView
- android:id="@+id/recommendation_card_text"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:maxLines="1"
- android:text="@string/controls_media_smartspace_rec_title"
- android:fontFamily="google-sans-medium"
- android:textDirection="locale"
- android:textSize="@dimen/qq_aa_media_rec_header_text_size"
- android:hyphenationFrequency="none"
- app:layout_constraintTop_toBottomOf="@id/recommendation_card_icon"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toStartOf="@id/media_vertical_start_guideline"
- app:layout_constraintHorizontal_bias="0"/>
-
- <View
- android:id="@+id/recommendation_gradient_view"
- android:layout_width="@dimen/qs_aa_media_gradient_bg_width"
- android:layout_height="0dp"
- android:clipToPadding="false"
- android:clipChildren="false"
- android:background="@drawable/qs_media_recommendation_bg_gradient"
- app:layout_constraintTop_toTopOf="@id/recommendation_card_text"
- app:layout_constraintBottom_toBottomOf="@id/recommendation_card_text"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toStartOf="@id/media_vertical_start_guideline"
- app:layout_constraintHorizontal_bias="1"/>
+ style="@style/MediaPlayer.Recommendation.AppIcon" />
<FrameLayout
android:id="@+id/media_cover1_container"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed"
- android:background="@drawable/qs_media_light_source">
+ style="@style/MediaPlayer.Recommendation.AlbumContainer"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@id/media_cover2_container"
+ android:layout_marginEnd="@dimen/qs_media_rec_album_margin"
+ app:layout_constraintHorizontal_chainStyle="packed"
+ app:layout_constraintHorizontal_bias="1.0"
+ app:layout_constraintVertical_bias="0.5"
+ >
<ImageView
android:id="@+id/media_cover1"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
android:adjustViewBounds="true"
android:background="@drawable/bg_smartspace_media_item"
- style="@style/MediaPlayer.Album"
+ style="@style/MediaPlayer.Recommendation.Album"
android:clipToOutline="true"
android:scaleType="centerCrop"/>
</FrameLayout>
+ <!-- TODO(b/223603970): Add title and subtitle below each album cover. -->
+
<FrameLayout
android:id="@+id/media_cover2_container"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed"
- android:background="@drawable/qs_media_light_source">
+ style="@style/MediaPlayer.Recommendation.AlbumContainer"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/media_cover1_container"
+ app:layout_constraintEnd_toStartOf="@id/media_cover3_container"
+ android:layout_marginEnd="@dimen/qs_media_rec_album_margin"
+ app:layout_constraintVertical_bias="0.5"
+ >
<ImageView
android:id="@+id/media_cover2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:background="@drawable/bg_smartspace_media_item"
- style="@style/MediaPlayer.Album"
+ style="@style/MediaPlayer.Recommendation.Album"
android:clipToOutline="true"
android:scaleType="centerCrop"/>
</FrameLayout>
<FrameLayout
android:id="@+id/media_cover3_container"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed"
- android:background="@drawable/qs_media_light_source">
+ style="@style/MediaPlayer.Recommendation.AlbumContainer"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/media_cover2_container"
+ app:layout_constraintEnd_toEndOf="parent"
+ android:layout_marginEnd="@dimen/qs_media_padding"
+ app:layout_constraintVertical_bias="0.5"
+ >
<ImageView
android:id="@+id/media_cover3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:background="@drawable/bg_smartspace_media_item"
- style="@style/MediaPlayer.Album"
- android:clipToOutline="true"
- android:scaleType="centerCrop"/>
- </FrameLayout>
-
- <FrameLayout
- android:id="@+id/media_cover4_container"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed"
- android:background="@drawable/qs_media_light_source">
- <ImageView
- android:id="@+id/media_cover4"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:adjustViewBounds="true"
- android:background="@drawable/bg_smartspace_media_item"
- style="@style/MediaPlayer.Album"
- android:clipToOutline="true"
- android:scaleType="centerCrop"/>
- </FrameLayout>
-
- <FrameLayout
- android:id="@+id/media_cover5_container"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed"
- android:background="@drawable/qs_media_light_source">
- <ImageView
- android:id="@+id/media_cover5"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:adjustViewBounds="true"
- android:background="@drawable/bg_smartspace_media_item"
- style="@style/MediaPlayer.Album"
- android:clipToOutline="true"
- android:scaleType="centerCrop"/>
- </FrameLayout>
-
- <FrameLayout
- android:id="@+id/media_cover6_container"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed"
- android:background="@drawable/qs_media_light_source">
- <ImageView
- android:id="@+id/media_cover6"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:adjustViewBounds="true"
- android:background="@drawable/bg_smartspace_media_item"
- style="@style/MediaPlayer.Album"
+ style="@style/MediaPlayer.Recommendation.Album"
android:clipToOutline="true"
android:scaleType="centerCrop"/>
</FrameLayout>
@@ -273,4 +200,4 @@
android:text="@string/controls_media_dismiss_button"
/>
</FrameLayout>
-</com.android.systemui.util.animation.TransitionLayout> \ No newline at end of file
+</com.android.systemui.util.animation.TransitionLayout>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 4725515d16fb..c7d41d3b28d3 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -959,7 +959,6 @@
<dimen name="qs_media_album_radius">14dp</dimen>
<dimen name="qs_media_info_margin">12dp</dimen>
<dimen name="qs_media_info_spacing">8dp</dimen>
- <dimen name="qs_media_icon_size">20dp</dimen>
<dimen name="qs_media_icon_offset">4dp</dimen>
<dimen name="qs_center_guideline_padding">10dp</dimen>
<dimen name="qs_media_action_spacing">4dp</dimen>
@@ -980,12 +979,9 @@
<dimen name="qs_media_session_collapsed_guideline">144dp</dimen>
<!-- Size of Smartspace media recommendations cards in the QSPanel carousel -->
- <dimen name="qs_aa_media_rec_album_size_collapsed">72dp</dimen>
- <dimen name="qs_aa_media_rec_album_size_expanded">76dp</dimen>
- <dimen name="qs_aa_media_gradient_bg_width">32dp</dimen>
- <dimen name="qs_aa_media_rec_album_margin">8dp</dimen>
- <dimen name="qs_aa_media_rec_album_margin_vert">4dp</dimen>
- <dimen name="qq_aa_media_rec_header_text_size">16sp</dimen>
+ <dimen name="qs_media_rec_album_size">88dp</dimen>
+ <dimen name="qs_media_rec_album_margin">16dp</dimen>
+ <dimen name="qs_media_rec_icon_size">24dp</dimen>
<!-- Media tap-to-transfer chip for sender device -->
<dimen name="media_ttt_chip_outer_padding">16dp</dimen>
@@ -1368,7 +1364,7 @@
<dimen name="keyguard_unfold_translation_x">16dp</dimen>
- <dimen name="fgs_manager_min_width_minor">100%</dimen>
+ <dimen name="fgs_manager_list_top_spacing">12dp</dimen>
<!-- Dream overlay related dimensions -->
<dimen name="dream_overlay_status_bar_height">60dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 0f5115b5c0f5..f7acda7ec379 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2440,14 +2440,16 @@
<!-- Label for the entry point to open the dialog which shows currently running applications [CHAR LIMIT=NONE]-->
<plurals name="fgs_manager_footer_label">
- <item quantity="one"><xliff:g id="count" example="1">%s</xliff:g> active app</item>
- <item quantity="other"><xliff:g id="count" example="2">%s</xliff:g> active apps</item>
+ <item quantity="one"><xliff:g id="count" example="1">%s</xliff:g> app is active</item>
+ <item quantity="other"><xliff:g id="count" example="2">%s</xliff:g> apps are active</item>
</plurals>
<!-- Content description for a dot indicator in the running application indicating that there
is new information [CHAR LIMIT=NONE] -->
<string name="fgs_dot_content_description">New information</string>
<!-- Title for dialog listing applications currently running [CHAR LIMIT=NONE]-->
<string name="fgs_manager_dialog_title">Active apps</string>
+ <!-- Detailed message for dialog listing applications currently running [CHAR LIMIT=NONE]-->
+ <string name="fgs_manager_dialog_message">Even if you\u2019re not using these apps, they\u2019re still active and might affect battery life</string>
<!-- Label of the button to stop an app from running [CHAR LIMIT=12]-->
<string name="fgs_manager_app_item_stop_button_label">Stop</string>
<!-- Label of the button to stop an app from running but the app is already stopped and the button is disabled [CHAR LIMIT=12]-->
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index d7799a7addd1..fc127cc08021 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -653,13 +653,29 @@
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
- <style name="MediaPlayer.AppIcon">
+ <style name="MediaPlayer.Recommendation"/>
+
+ <style name="MediaPlayer.Recommendation.AppIcon">
<item name="android:background">@drawable/qs_media_icon_background</item>
<item name="android:backgroundTint">@color/media_player_solid_button_bg</item>
- <item name="android:padding">4dp</item>
+ <item name="android:layout_width">@dimen/qs_media_rec_icon_size</item>
+ <item name="android:layout_height">@dimen/qs_media_rec_icon_size</item>
+ <item name="layout_constraintTop_toTopOf">parent</item>
+ <item name="layout_constraintStart_toStartOf">parent</item>
+ <item name="android:layout_marginTop">@dimen/qs_media_padding</item>
+ <item name="android:layout_marginStart">@dimen/qs_media_padding</item>
+ <item name="android:src">@drawable/ic_headset</item>
+ </style>
+
+ <style name="MediaPlayer.Recommendation.AlbumContainer">
+ <item name="android:layout_width">@dimen/qs_media_rec_album_size</item>
+ <item name="android:layout_height">@dimen/qs_media_rec_album_size</item>
+ <item name="android:background">@drawable/qs_media_light_source</item>
+ <item name="android:layout_marginTop">@dimen/qs_media_padding</item>
+ <item name="android:layout_marginBottom">@dimen/qs_media_padding</item>
</style>
- <style name="MediaPlayer.Album">
+ <style name="MediaPlayer.Recommendation.Album">
<item name="android:backgroundTint">@color/media_player_album_bg</item>
</style>
@@ -1085,6 +1101,7 @@
<style name="FgsManagerAppLabel" parent="TextAppearance.Dialog.Body">
<item name="android:textDirection">locale</item>
+ <item name="android:textStyle">bold</item>
</style>
<style name="FgsManagerAppDuration">
diff --git a/packages/SystemUI/res/xml/media_recommendation_collapsed.xml b/packages/SystemUI/res/xml/media_recommendation_collapsed.xml
index b6258d1c71eb..c9d76870ebbd 100644
--- a/packages/SystemUI/res/xml/media_recommendation_collapsed.xml
+++ b/packages/SystemUI/res/xml/media_recommendation_collapsed.xml
@@ -15,92 +15,12 @@
~ limitations under the License
-->
<ConstraintSet
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto">
+ xmlns:android="http://schemas.android.com/apk/res/android" >
<Constraint
- android:id="@+id/media_cover1_container"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed"
- app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_collapsed"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"
- android:layout_marginTop="@dimen/qs_media_padding"
- android:layout_marginBottom="@dimen/qs_media_padding"
- android:layout_marginEnd="@dimen/qs_aa_media_rec_album_margin"
- app:layout_constraintStart_toEndOf="@id/media_vertical_start_guideline"
- app:layout_constraintEnd_toStartOf="@id/media_cover2_container"
- app:layout_constraintHorizontal_chainStyle="packed"
- app:layout_constraintHorizontal_bias="1"
- android:visibility="gone" />
-
- <Constraint
- android:id="@+id/media_cover2_container"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed"
- app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_collapsed"
- android:layout_marginTop="@dimen/qs_media_padding"
- android:layout_marginBottom="@dimen/qs_media_padding"
- android:layout_marginEnd="@dimen/qs_aa_media_rec_album_margin"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toEndOf="@id/media_cover1_container"
- app:layout_constraintEnd_toStartOf="@id/media_cover3_container"
- app:layout_constraintHorizontal_chainStyle="packed"
- app:layout_constraintHorizontal_bias="1"
- android:visibility="gone" />
-
- <Constraint
- android:id="@+id/media_cover3_container"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_aa_media_rec_album_size_collapsed"
- app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_collapsed"
- android:layout_marginTop="@dimen/qs_media_padding"
- android:layout_marginBottom="@dimen/qs_media_padding"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toEndOf="@id/media_cover2_container"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintHorizontal_chainStyle="packed"
- app:layout_constraintHorizontal_bias="1"
- android:visibility="gone" />
-
- <Constraint
- android:id="@+id/media_cover4_container"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_marginEnd="@dimen/qs_aa_media_rec_album_margin"
- app:layout_constraintTop_toBottomOf="@+id/media_cover1_container"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toEndOf="@id/media_vertical_start_guideline"
- app:layout_constraintEnd_toStartOf="@id/media_cover5_container"
- app:layout_constraintHorizontal_chainStyle="packed"
- app:layout_constraintHorizontal_bias="1"
- android:visibility="gone" />
-
- <Constraint
- android:id="@+id/media_cover5_container"
- android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_marginEnd="@dimen/qs_aa_media_rec_album_margin"
- app:layout_constraintTop_toBottomOf="@+id/media_cover2_container"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toEndOf="@+id/media_cover4_container"
- app:layout_constraintEnd_toStartOf="@+id/media_cover6_container"
- app:layout_constraintHorizontal_chainStyle="packed"
- app:layout_constraintHorizontal_bias="1"
- android:visibility="gone" />
-
- <Constraint
- android:id="@+id/media_cover6_container"
- android:layout_width="0dp"
- android:layout_height="0dp"
- app:layout_constraintTop_toBottomOf="@id/media_cover3_container"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toEndOf="@id/media_cover5_container"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintHorizontal_chainStyle="packed"
- app:layout_constraintHorizontal_bias="1"
- android:visibility="gone" />
+ android:id="@+id/sizing_view"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/qs_media_session_height_collapsed"
+ />
</ConstraintSet>
diff --git a/packages/SystemUI/res/xml/media_recommendation_expanded.xml b/packages/SystemUI/res/xml/media_recommendation_expanded.xml
index 2fb33415e0df..09ffebb8b4a9 100644
--- a/packages/SystemUI/res/xml/media_recommendation_expanded.xml
+++ b/packages/SystemUI/res/xml/media_recommendation_expanded.xml
@@ -15,113 +15,12 @@
~ limitations under the License
-->
<ConstraintSet
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto">
+ xmlns:android="http://schemas.android.com/apk/res/android" >
<Constraint
- android:id="@+id/media_cover1_container"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_aa_media_rec_album_size_expanded"
- app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_expanded"
- android:layout_marginTop="@dimen/qs_media_padding"
- android:layout_marginBottom="@dimen/qs_aa_media_rec_album_margin_vert"
- android:layout_marginEnd="@dimen/qs_aa_media_rec_album_margin"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toTopOf="@+id/media_horizontal_center_guideline"
- app:layout_constraintStart_toEndOf="@id/media_vertical_start_guideline"
- app:layout_constraintEnd_toStartOf="@id/media_cover2_container"
- app:layout_constraintHorizontal_chainStyle="packed"
- app:layout_constraintHorizontal_bias="1"
- app:layout_constraintVertical_chainStyle="packed"
- app:layout_constraintVertical_bias="0"
- android:visibility="gone" />
-
- <Constraint
- android:id="@+id/media_cover2_container"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_aa_media_rec_album_size_expanded"
- app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_expanded"
- android:layout_marginTop="@dimen/qs_media_padding"
- android:layout_marginBottom="@dimen/qs_aa_media_rec_album_margin_vert"
- android:layout_marginEnd="@dimen/qs_aa_media_rec_album_margin"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toTopOf="@+id/media_horizontal_center_guideline"
- app:layout_constraintStart_toEndOf="@id/media_cover1_container"
- app:layout_constraintEnd_toStartOf="@id/media_cover3_container"
- app:layout_constraintHorizontal_chainStyle="packed"
- app:layout_constraintHorizontal_bias="1"
- app:layout_constraintVertical_chainStyle="packed"
- app:layout_constraintVertical_bias="0"
- android:visibility="gone" />
-
- <Constraint
- android:id="@+id/media_cover3_container"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_aa_media_rec_album_size_expanded"
- app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_expanded"
- android:layout_marginTop="@dimen/qs_media_padding"
- android:layout_marginBottom="@dimen/qs_aa_media_rec_album_margin_vert"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toTopOf="@+id/media_horizontal_center_guideline"
- app:layout_constraintStart_toEndOf="@id/media_cover2_container"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintHorizontal_chainStyle="packed"
- app:layout_constraintHorizontal_bias="1"
- app:layout_constraintVertical_chainStyle="packed"
- app:layout_constraintVertical_bias="0"
- android:visibility="gone" />
-
- <Constraint
- android:id="@+id/media_cover4_container"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_aa_media_rec_album_size_expanded"
- app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_expanded"
- android:layout_marginTop="@dimen/qs_aa_media_rec_album_margin_vert"
- android:layout_marginBottom="@dimen/qs_media_padding"
- android:layout_marginEnd="@dimen/qs_aa_media_rec_album_margin"
- app:layout_constraintTop_toBottomOf="@+id/media_horizontal_center_guideline"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toEndOf="@id/media_vertical_start_guideline"
- app:layout_constraintEnd_toStartOf="@id/media_cover5_container"
- app:layout_constraintHorizontal_chainStyle="packed"
- app:layout_constraintHorizontal_bias="1"
- app:layout_constraintVertical_chainStyle="packed"
- app:layout_constraintVertical_bias="1"
- android:visibility="gone" />
-
- <Constraint
- android:id="@+id/media_cover5_container"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_aa_media_rec_album_size_expanded"
- app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_expanded"
- android:layout_marginTop="@dimen/qs_aa_media_rec_album_margin_vert"
- android:layout_marginBottom="@dimen/qs_media_padding"
- android:layout_marginEnd="@dimen/qs_aa_media_rec_album_margin"
- app:layout_constraintTop_toBottomOf="@+id/media_horizontal_center_guideline"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toEndOf="@+id/media_cover4_container"
- app:layout_constraintEnd_toStartOf="@+id/media_cover6_container"
- app:layout_constraintHorizontal_chainStyle="packed"
- app:layout_constraintHorizontal_bias="1"
- app:layout_constraintVertical_chainStyle="packed"
- app:layout_constraintVertical_bias="1"
- android:visibility="gone" />
-
- <Constraint
- android:id="@+id/media_cover6_container"
- android:layout_width="0dp"
- android:layout_height="@dimen/qs_aa_media_rec_album_size_expanded"
- app:layout_constraintWidth_max="@dimen/qs_aa_media_rec_album_size_expanded"
- android:layout_marginTop="@dimen/qs_aa_media_rec_album_margin_vert"
- android:layout_marginBottom="@dimen/qs_media_padding"
- app:layout_constraintTop_toBottomOf="@id/media_horizontal_center_guideline"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintStart_toEndOf="@id/media_cover5_container"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintHorizontal_chainStyle="packed"
- app:layout_constraintHorizontal_bias="1"
- app:layout_constraintVertical_chainStyle="packed"
- app:layout_constraintVertical_bias="1"
- android:visibility="gone" />
+ android:id="@+id/sizing_view"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/qs_media_session_height_expanded"
+ />
</ConstraintSet>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
index bb7a0a719a74..01f417f147d7 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
@@ -568,7 +568,7 @@ public class RotationButtonController {
}
}
- private class TaskStackListenerImpl extends TaskStackChangeListener {
+ private class TaskStackListenerImpl implements TaskStackChangeListener {
// Invalidate any rotation suggestion on task change or activity orientation change
// Note: all callbacks happen on main thread
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
index c5d54391959a..f65d82a5d6d2 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
@@ -26,30 +26,30 @@ import com.android.systemui.shared.recents.model.ThumbnailData;
* An interface to track task stack changes. Classes should implement this instead of
* {@link android.app.ITaskStackListener} to reduce IPC calls from system services.
*/
-public abstract class TaskStackChangeListener {
+public interface TaskStackChangeListener {
// Binder thread callbacks
- public void onTaskStackChangedBackground() { }
+ default void onTaskStackChangedBackground() { }
// Main thread callbacks
- public void onTaskStackChanged() { }
- public void onTaskSnapshotChanged(int taskId, ThumbnailData snapshot) { }
- public void onActivityPinned(String packageName, int userId, int taskId, int stackId) { }
- public void onActivityUnpinned() { }
- public void onActivityRestartAttempt(RunningTaskInfo task, boolean homeTaskVisible,
+ default void onTaskStackChanged() { }
+ default void onTaskSnapshotChanged(int taskId, ThumbnailData snapshot) { }
+ default void onActivityPinned(String packageName, int userId, int taskId, int stackId) { }
+ default void onActivityUnpinned() { }
+ default void onActivityRestartAttempt(RunningTaskInfo task, boolean homeTaskVisible,
boolean clearedTask, boolean wasVisible) { }
- public void onActivityForcedResizable(String packageName, int taskId, int reason) { }
- public void onActivityDismissingDockedStack() { }
- public void onActivityLaunchOnSecondaryDisplayFailed() { }
+ default void onActivityForcedResizable(String packageName, int taskId, int reason) { }
+ default void onActivityDismissingDockedStack() { }
+ default void onActivityLaunchOnSecondaryDisplayFailed() { }
- public void onActivityLaunchOnSecondaryDisplayFailed(RunningTaskInfo taskInfo) {
+ default void onActivityLaunchOnSecondaryDisplayFailed(RunningTaskInfo taskInfo) {
onActivityLaunchOnSecondaryDisplayFailed();
}
/**
* @see #onActivityLaunchOnSecondaryDisplayRerouted(RunningTaskInfo taskInfo)
*/
- public void onActivityLaunchOnSecondaryDisplayRerouted() { }
+ default void onActivityLaunchOnSecondaryDisplayRerouted() { }
/**
* Called when an activity was requested to be launched on a secondary display but was rerouted
@@ -57,16 +57,16 @@ public abstract class TaskStackChangeListener {
*
* @param taskInfo info about the Activity's task
*/
- public void onActivityLaunchOnSecondaryDisplayRerouted(RunningTaskInfo taskInfo) {
+ default void onActivityLaunchOnSecondaryDisplayRerouted(RunningTaskInfo taskInfo) {
onActivityLaunchOnSecondaryDisplayRerouted();
}
- public void onTaskProfileLocked(int taskId, int userId) { }
- public void onTaskCreated(int taskId, ComponentName componentName) { }
- public void onTaskRemoved(int taskId) { }
- public void onTaskMovedToFront(int taskId) { }
+ default void onTaskProfileLocked(int taskId, int userId) { }
+ default void onTaskCreated(int taskId, ComponentName componentName) { }
+ default void onTaskRemoved(int taskId) { }
+ default void onTaskMovedToFront(int taskId) { }
- public void onTaskMovedToFront(RunningTaskInfo taskInfo) {
+ default void onTaskMovedToFront(RunningTaskInfo taskInfo) {
onTaskMovedToFront(taskInfo.taskId);
}
@@ -74,13 +74,14 @@ public abstract class TaskStackChangeListener {
* Called when a task’s description is changed due to an activity calling
* ActivityManagerService.setTaskDescription
*
- * @param taskInfo info about the task which changed, with {@link TaskInfo#taskDescription}
+ * @param taskInfo info about the task which changed, with
+ * {@link RunningTaskInfo#taskDescription}
*/
- public void onTaskDescriptionChanged(RunningTaskInfo taskInfo) { }
+ default void onTaskDescriptionChanged(RunningTaskInfo taskInfo) { }
- public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation) { }
+ default void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation) { }
- public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) { }
+ default void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) { }
/**
* Called when a task is reparented to a stack on a different display.
@@ -88,22 +89,22 @@ public abstract class TaskStackChangeListener {
* @param taskId id of the task which was moved to a different display.
* @param newDisplayId id of the new display.
*/
- public void onTaskDisplayChanged(int taskId, int newDisplayId) { }
+ default void onTaskDisplayChanged(int taskId, int newDisplayId) { }
/**
* Called when any additions or deletions to the recent tasks list have been made.
*/
- public void onRecentTaskListUpdated() { }
+ default void onRecentTaskListUpdated() { }
/** @see ITaskStackListener#onRecentTaskListFrozenChanged(boolean) */
- public void onRecentTaskListFrozenChanged(boolean frozen) { }
+ default void onRecentTaskListFrozenChanged(boolean frozen) { }
/** @see ITaskStackListener#onActivityRotation(int)*/
- public void onActivityRotation(int displayId) { }
+ default void onActivityRotation(int displayId) { }
/**
* Called when the lock task mode changes. See ActivityManager#LOCK_TASK_MODE_* and
* LockTaskController.
*/
- public void onLockTaskModeChanged(int mode) { }
+ default void onLockTaskModeChanged(int mode) { }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
index 5953611b454a..db2b4ac2c669 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
@@ -63,7 +63,8 @@ data class KeyguardFaceListenModel(
val primaryUser: Boolean,
val scanningAllowedByStrongAuth: Boolean,
val secureCameraLaunched: Boolean,
- val switchingUser: Boolean
+ val switchingUser: Boolean,
+ val udfpsBouncerShowing: Boolean
) : KeyguardListenModel()
/**
* Verbose debug information associated with [KeyguardUpdateMonitor.shouldTriggerActiveUnlock].
@@ -73,6 +74,7 @@ data class KeyguardActiveUnlockModel(
override val userId: Int,
override val listening: Boolean,
// keep sorted
+ val awakeKeyguard: Boolean,
val authInterruptActive: Boolean,
val encryptedOrTimedOut: Boolean,
val fpLockout: Boolean,
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 3103219d8978..53d7b8cee3be 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -700,6 +700,7 @@ public class KeyguardSecurityContainer extends FrameLayout {
}
public void reset() {
+ mViewMode.reset();
mDisappearAnimRunning = false;
}
@@ -798,9 +799,6 @@ public class KeyguardSecurityContainer extends FrameLayout {
mUserSwitcherViewGroup = mView.findViewById(R.id.keyguard_bouncer_user_switcher);
}
- Drawable userIcon = findUserIcon(KeyguardUpdateMonitor.getCurrentUser());
- ((ImageView) mView.findViewById(R.id.user_icon)).setImageDrawable(userIcon);
-
updateSecurityViewLocation();
mUserSwitcher = mView.findViewById(R.id.user_switcher_header);
@@ -813,6 +811,7 @@ public class KeyguardSecurityContainer extends FrameLayout {
mPopup.dismiss();
mPopup = null;
}
+ setupUserSwitcher();
}
private Drawable findUserIcon(int userId) {
@@ -858,6 +857,12 @@ public class KeyguardSecurityContainer extends FrameLayout {
private void setupUserSwitcher() {
final UserRecord currentUser = mUserSwitcherController.getCurrentUserRecord();
+ if (currentUser == null) {
+ Log.wtf(TAG, "Current user in user switcher is null.");
+ return;
+ }
+ Drawable userIcon = findUserIcon(currentUser.info.id);
+ ((ImageView) mView.findViewById(R.id.user_icon)).setImageDrawable(userIcon);
mUserSwitcher.setText(mUserSwitcherController.getCurrentUserName());
ViewGroup anchor = mView.findViewById(R.id.user_switcher_anchor);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 1a325d3586f4..ce4aad882df9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -219,6 +219,11 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
mKeyguardSecurityCallback.userActivity();
showMessage(null, null);
}
+ if (mUpdateMonitor.isFaceEnrolled()
+ && mUpdateMonitor.mRequestActiveUnlockOnUnlockIntent) {
+ mUpdateMonitor.requestActiveUnlock("unlock-intent, reason=swipeUpOnBouncer",
+ true);
+ }
}
};
private ConfigurationController.ConfigurationListener mConfigurationListener =
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index f1bec819560d..a6feedb50a12 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -56,6 +56,7 @@ import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.hardware.SensorPrivacyManager;
+import android.hardware.biometrics.BiometricFaceConstants;
import android.hardware.biometrics.BiometricFingerprintConstants;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricSourceType;
@@ -88,6 +89,7 @@ import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
+import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -246,6 +248,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
}
+ public final boolean mRequestActiveUnlockOnAssistant;
+ public final boolean mRequestActiveUnlockOnWakeup;
+ public final boolean mInitiateActiveUnlockOnWakeup;
+ public final boolean mRequestActiveUnlockOnUnlockIntent;
+ public final boolean mRequestActiveUnlockOnBioFail;
+
private final Context mContext;
private final boolean mIsPrimaryUser;
private final boolean mIsAutomotive;
@@ -281,6 +289,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private boolean mGoingToSleep;
private boolean mBouncerFullyShown;
private boolean mBouncerIsOrWillBeShowing;
+ private boolean mUdfpsBouncerShowing;
private boolean mAuthInterruptActive;
private boolean mNeedsSlowUnlockTransition;
private boolean mAssistantVisible;
@@ -451,10 +460,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
}
- if (KeyguardUpdateMonitor.getCurrentUser() == userId && getUserHasTrust(userId)) {
+ if (KeyguardUpdateMonitor.getCurrentUser() == userId) {
CharSequence message = null;
- if (trustGrantedMessages != null && trustGrantedMessages.size() > 0) {
- message = trustGrantedMessages.get(0); // for now only shows the first in the list
+ final boolean userHasTrust = getUserHasTrust(userId);
+ if (userHasTrust && trustGrantedMessages != null) {
+ for (String msg : trustGrantedMessages) {
+ if (!TextUtils.isEmpty(msg)) {
+ message = msg;
+ break;
+ }
+ }
}
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -463,6 +478,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
}
}
+
}
@Override
@@ -1354,8 +1370,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
void setAssistantVisible(boolean assistantVisible) {
mAssistantVisible = assistantVisible;
updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE);
- if (mAssistantVisible) {
- requestActiveUnlock();
+ if (mAssistantVisible && mRequestActiveUnlockOnAssistant) {
+ requestActiveUnlock("assistant", false);
}
}
@@ -1502,11 +1518,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
@Override
public void onAuthenticationFailed() {
+ if (mRequestActiveUnlockOnBioFail) {
+ requestActiveUnlock("biometric-failure, extra=fingerprintFailure",
+ true);
+ }
handleFingerprintAuthFailed();
-
- // TODO(b/225231929): Refactor as needed, add tests, etc.
- mTrustManager.reportUserRequestedUnlock(
- KeyguardUpdateMonitor.getCurrentUser(), true);
}
@Override
@@ -1564,6 +1580,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
@Override
public void onAuthenticationFailed() {
+ if (shouldRequestActiveUnlockOnFaceError()) {
+ String reason =
+ mKeyguardBypassController.canBypass() ? "bypass"
+ : mUdfpsBouncerShowing ? "udfpsBouncer" :
+ mBouncerFullyShown ? "bouncer" : "udfpsFpDown";
+ requestActiveUnlock("biometric-failure"
+ + ", extra=faceFailure-" + reason, true);
+ }
+
handleFaceAuthFailed();
if (mKeyguardBypassController != null) {
mKeyguardBypassController.setUserHasDeviceEntryIntent(false);
@@ -1592,12 +1617,23 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
if (mKeyguardBypassController != null) {
mKeyguardBypassController.setUserHasDeviceEntryIntent(false);
}
+ if (errMsgId == BiometricFaceConstants.FACE_ERROR_TIMEOUT
+ && shouldRequestActiveUnlockOnFaceError()) {
+ requestActiveUnlock("biometric-failure"
+ + ", extra=faceError-" + errMsgId, true);
+ }
}
@Override
public void onAuthenticationAcquired(int acquireInfo) {
handleFaceAcquired(acquireInfo);
}
+
+ private boolean shouldRequestActiveUnlockOnFaceError() {
+ return mRequestActiveUnlockOnBioFail
+ && (mKeyguardBypassController.canBypass() || mBouncerFullyShown
+ || mUdfpsBouncerShowing || mAuthController.isUdfpsFingerDown());
+ }
};
@VisibleForTesting
@@ -1713,7 +1749,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
Trace.beginSection("KeyguardUpdateMonitor#handleStartedWakingUp");
Assert.isMainThread();
updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE);
- requestActiveUnlock();
+ if (mRequestActiveUnlockOnWakeup) {
+ requestActiveUnlock("wake-unlock");
+ } else if (mInitiateActiveUnlockOnWakeup) {
+ initiateActiveUnlock("wake-initiate");
+ }
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -1860,6 +1900,18 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
dumpManager.registerDumpable(getClass().getName(), this);
mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);
+ // TODO, b/222459888: add official configurable names to Settings.java
+ mRequestActiveUnlockOnWakeup = Settings.Global.getInt(
+ mContext.getContentResolver(), "wake-unlock", 0) == 1;
+ mInitiateActiveUnlockOnWakeup = Settings.Global.getInt(
+ mContext.getContentResolver(), "wake-initiate", 1) == 1;
+ mRequestActiveUnlockOnUnlockIntent = Settings.Global.getInt(
+ mContext.getContentResolver(), "unlock-intent", 0) == 1;
+ mRequestActiveUnlockOnBioFail = Settings.Global.getInt(
+ mContext.getContentResolver(), "bio-fail", 0) == 1;
+ mRequestActiveUnlockOnAssistant = Settings.Global.getInt(
+ mContext.getContentResolver(), "assistant", 0) == 1;
+
mHandler = new Handler(mainLooper) {
@Override
public void handleMessage(Message msg) {
@@ -2194,7 +2246,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
// don't start running fingerprint until they're registered
- if (!mAuthController.areAllAuthenticatorsRegistered()) {
+ if (!mAuthController.areAllFingerprintAuthenticatorsRegistered()) {
return;
}
final boolean shouldListenForFingerprint = shouldListenForFingerprint(isUdfpsSupported());
@@ -2240,7 +2292,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
mAuthInterruptActive = active;
updateFaceListeningState(BIOMETRIC_ACTION_UPDATE);
- requestActiveUnlock();
+ if (mRequestActiveUnlockOnWakeup) {
+ requestActiveUnlock("wake-unlock, extra=onReach");
+ } else if (mInitiateActiveUnlockOnWakeup) {
+ initiateActiveUnlock("wake-initiate, extra=onReach");
+ }
}
/**
@@ -2290,25 +2346,69 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
/**
- * Attempts to trigger active unlock.
+ * Initiates active unlock to get the unlock token ready.
*/
- public void requestActiveUnlock() {
+ public void initiateActiveUnlock(String reason) {
// If this message exists, FP has already authenticated, so wait until that is handled
if (mHandler.hasMessages(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE)) {
return;
}
if (shouldTriggerActiveUnlock()) {
- // TODO(b/225231929): Refactor surrounding code to reflect calling of new method
+ if (DEBUG) {
+ Log.d("ActiveUnlock", "initiate active unlock triggerReason=" + reason);
+ }
mTrustManager.reportUserMayRequestUnlock(KeyguardUpdateMonitor.getCurrentUser());
}
}
+ /**
+ * Attempts to trigger active unlock from trust agent.
+ */
+ public void requestActiveUnlock(String reason, boolean dismissKeyguard) {
+ // If this message exists, FP has already authenticated, so wait until that is handled
+ if (mHandler.hasMessages(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE)) {
+ return;
+ }
+
+ if (shouldTriggerActiveUnlock()) {
+ if (DEBUG) {
+ Log.d("ActiveUnlock", "reportUserRequestedUnlock triggerReason=" + reason
+ + " dismissKeyguard=" + dismissKeyguard);
+ }
+ mTrustManager.reportUserRequestedUnlock(KeyguardUpdateMonitor.getCurrentUser(),
+ dismissKeyguard);
+ }
+ }
+
+ /**
+ * Attempts to trigger active unlock from trust agent.
+ * Only dismisses the keyguard if only face is enrolled (no FP) and bypass is enabled.
+ */
+ public void requestActiveUnlock(String reason) {
+ requestActiveUnlock(reason, isFaceEnrolled() && !isUdfpsEnrolled()
+ && mKeyguardBypassController.getBypassEnabled());
+ }
+
+ /**
+ * Whether the UDFPS bouncer is showing.
+ */
+ public void setUdfpsBouncerShowing(boolean showing) {
+ mUdfpsBouncerShowing = showing;
+ if (mUdfpsBouncerShowing) {
+ updateFaceListeningState(BIOMETRIC_ACTION_START);
+ if (mRequestActiveUnlockOnUnlockIntent) {
+ requestActiveUnlock("unlock-intent, extra=udfpsBouncer", true);
+ }
+ }
+ }
+
private boolean shouldTriggerActiveUnlock() {
// Triggers:
final boolean triggerActiveUnlockForAssistant = shouldTriggerActiveUnlockForAssistant();
- final boolean awakeKeyguard = mKeyguardIsVisible && mDeviceInteractive && !mGoingToSleep
- && mStatusBarState != StatusBarState.SHADE_LOCKED;
+ final boolean awakeKeyguard = mBouncerFullyShown || mUdfpsBouncerShowing
+ || (mKeyguardIsVisible && mDeviceInteractive && !mGoingToSleep
+ && mStatusBarState != StatusBarState.SHADE_LOCKED);
// Gates:
final int user = getCurrentUser();
@@ -2341,20 +2441,19 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
&& !mSecureCameraLaunched;
// Aggregate relevant fields for debug logging.
- if (DEBUG_ACTIVE_UNLOCK || DEBUG_SPEW) {
- maybeLogListenerModelData(
- new KeyguardActiveUnlockModel(
- System.currentTimeMillis(),
- user,
- shouldTriggerActiveUnlock,
- mAuthInterruptActive,
- isEncryptedOrTimedOut,
- fpLockedout,
- isLockDown,
- mSwitchingUser,
- triggerActiveUnlockForAssistant,
- userCanDismissLockScreen));
- }
+ maybeLogListenerModelData(
+ new KeyguardActiveUnlockModel(
+ System.currentTimeMillis(),
+ user,
+ shouldTriggerActiveUnlock,
+ awakeKeyguard,
+ mAuthInterruptActive,
+ isEncryptedOrTimedOut,
+ fpLockedout,
+ isLockDown,
+ mSwitchingUser,
+ triggerActiveUnlockForAssistant,
+ userCanDismissLockScreen));
return shouldTriggerActiveUnlock;
}
@@ -2507,7 +2606,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|| mOccludingAppRequestingFace
|| awakeKeyguard
|| shouldListenForFaceAssistant
- || mAuthController.isUdfpsFingerDown())
+ || mAuthController.isUdfpsFingerDown()
+ || mUdfpsBouncerShowing)
&& !mSwitchingUser && !faceDisabledForUser && becauseCannotSkipBouncer
&& !mKeyguardGoingAway && biometricEnabledForUser && !mLockIconPressed
&& strongAuthAllowsScanning && mIsPrimaryUser
@@ -2537,7 +2637,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mIsPrimaryUser,
strongAuthAllowsScanning,
mSecureCameraLaunched,
- mSwitchingUser));
+ mSwitchingUser,
+ mUdfpsBouncerShowing));
}
return shouldListen;
@@ -2550,8 +2651,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
if (DEBUG_ACTIVE_UNLOCK
- && model instanceof KeyguardActiveUnlockModel
- && model.getListening()) {
+ && model instanceof KeyguardActiveUnlockModel) {
mListenModels.add(model);
return;
}
@@ -3133,6 +3233,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
if (wasBouncerFullyShown != mBouncerFullyShown) {
+ if (mBouncerFullyShown && mRequestActiveUnlockOnUnlockIntent) {
+ requestActiveUnlock("unlock-intent, reason=bouncerFullyShown", true);
+ }
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -3619,8 +3722,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
final int strongAuthFlags = mStrongAuthTracker.getStrongAuthForUser(userId);
BiometricAuthenticated fingerprint = mUserFingerprintAuthenticated.get(userId);
pw.println(" Fingerprint state (user=" + userId + ")");
- pw.println(" areAllAuthenticatorsRegistered="
- + mAuthController.areAllAuthenticatorsRegistered());
+ pw.println(" areAllFpAuthenticatorsRegistered="
+ + mAuthController.areAllFingerprintAuthenticatorsRegistered());
pw.println(" allowed="
+ (fingerprint != null
&& isUnlockingWithBiometricAllowed(fingerprint.mIsStrongBiometric)));
@@ -3641,6 +3744,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
pw.println(" shouldListenForUdfps=" + shouldListenForFingerprint(true));
pw.println(" mBouncerIsOrWillBeShowing=" + mBouncerIsOrWillBeShowing);
pw.println(" mStatusBarState=" + StatusBarState.toString(mStatusBarState));
+ pw.println(" mUdfpsBouncerShowing=" + mUdfpsBouncerShowing);
}
}
if (mFaceManager != null && mFaceManager.isHardwareDetected()) {
@@ -3667,6 +3771,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
mListenModels.print(pw);
+ pw.println("Enabled active unlock triggers:");
+ pw.println(" mRequestActiveUnlockOnWakeup=" + mRequestActiveUnlockOnWakeup);
+ pw.println(" mInitiateActiveUnlockOnWakeup=" + mInitiateActiveUnlockOnWakeup);
+ pw.println(" mRequestActiveUnlockOnUnlockIntent=" + mRequestActiveUnlockOnUnlockIntent);
+ pw.println(" mRequestActiveUnlockOnBiometricFail=" + mRequestActiveUnlockOnBioFail);
+ pw.println(" mRequestActiveUnlockOnAssistant=" + mRequestActiveUnlockOnAssistant);
+
if (mIsAutomotive) {
pw.println(" Running on Automotive build");
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index b05bc245a79f..15d0648ae163 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -37,6 +37,7 @@ import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager.Authenticators;
import android.hardware.biometrics.BiometricManager.BiometricMultiSensorMode;
import android.hardware.biometrics.BiometricPrompt;
+import android.hardware.biometrics.BiometricStateListener;
import android.hardware.biometrics.IBiometricContextListener;
import android.hardware.biometrics.IBiometricSysuiReceiver;
import android.hardware.biometrics.PromptInfo;
@@ -45,7 +46,6 @@ import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.hardware.fingerprint.FingerprintStateListener;
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
import android.hardware.fingerprint.IUdfpsHbmListener;
import android.os.Bundle;
@@ -138,7 +138,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
@NonNull private final SparseBooleanArray mUdfpsEnrolledForUser;
@NonNull private final SensorPrivacyManager mSensorPrivacyManager;
private final WakefulnessLifecycle mWakefulnessLifecycle;
- private boolean mAllAuthenticatorsRegistered;
+ private boolean mAllFingerprintAuthenticatorsRegistered;
@NonNull private final UserManager mUserManager;
@NonNull private final LockPatternUtils mLockPatternUtils;
private final @Background DelayableExecutor mBackgroundExecutor;
@@ -157,12 +157,12 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
@Override
public void onAllAuthenticatorsRegistered(
List<FingerprintSensorPropertiesInternal> sensors) {
- mHandler.post(() -> handleAllAuthenticatorsRegistered(sensors));
+ mHandler.post(() -> handleAllFingerprintAuthenticatorsRegistered(sensors));
}
};
- private final FingerprintStateListener mFingerprintStateListener =
- new FingerprintStateListener() {
+ private final BiometricStateListener mBiometricStateListener =
+ new BiometricStateListener() {
@Override
public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) {
mHandler.post(
@@ -234,20 +234,20 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
}
/**
- * Whether all authentictors have been registered.
+ * Whether all fingerprint authentictors have been registered.
*/
- public boolean areAllAuthenticatorsRegistered() {
- return mAllAuthenticatorsRegistered;
+ public boolean areAllFingerprintAuthenticatorsRegistered() {
+ return mAllFingerprintAuthenticatorsRegistered;
}
- private void handleAllAuthenticatorsRegistered(
+ private void handleAllFingerprintAuthenticatorsRegistered(
List<FingerprintSensorPropertiesInternal> sensors) {
mExecution.assertIsMainThread();
if (DEBUG) {
Log.d(TAG, "handleAllAuthenticatorsRegistered | sensors: " + Arrays.toString(
sensors.toArray()));
}
- mAllAuthenticatorsRegistered = true;
+ mAllFingerprintAuthenticatorsRegistered = true;
mFpProps = sensors;
List<FingerprintSensorPropertiesInternal> udfpsProps = new ArrayList<>();
List<FingerprintSensorPropertiesInternal> sidefpsProps = new ArrayList<>();
@@ -281,7 +281,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
for (Callback cb : mCallbacks) {
cb.onAllAuthenticatorsRegistered();
}
- mFingerprintManager.registerFingerprintStateListener(mFingerprintStateListener);
+ mFingerprintManager.registerBiometricStateListener(mBiometricStateListener);
}
private void handleEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 2ac240885faa..eba87e49d35b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -799,6 +799,11 @@ public class UdfpsController implements DozeReceiver {
if (!mKeyguardUpdateMonitor.isFaceDetectionRunning()) {
mKeyguardUpdateMonitor.requestFaceAuth(/* userInitiatedRequest */ false);
}
+
+ if (mKeyguardUpdateMonitor.mRequestActiveUnlockOnUnlockIntent) {
+ mKeyguardUpdateMonitor.requestActiveUnlock("unlock-intent extra=udfpsFingerDown",
+ true);
+ }
}
mOnFingerDown = true;
mFingerprintManager.onPointerDown(requestId, mSensorProps.sensorId, x, y, minor, major);
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
index aaa4d9eefd29..c4531b573d22 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
@@ -42,10 +42,14 @@ import com.android.systemui.Dumpable;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.statusbar.commandline.Command;
+import com.android.systemui.statusbar.commandline.CommandRegistry;
import com.android.systemui.util.settings.SecureSettings;
import java.io.PrintWriter;
+import java.lang.reflect.Field;
import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
@@ -59,6 +63,10 @@ import javax.inject.Named;
*
* Flags can be set (or unset) via the following adb command:
*
+ * adb shell cmd statusbar flag <id> <on|off|toggle|erase>
+ *
+ * Alternatively, you can change flags via a broadcast intent:
+ *
* adb shell am broadcast -a com.android.systemui.action.SET_FLAG --ei id <id> [--ez value <0|1>]
*
* To restore a flag back to its default, leave the `--ez value <0|1>` off of the command.
@@ -67,6 +75,7 @@ import javax.inject.Named;
public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
private static final String TAG = "SysUIFlags";
static final String ALL_FLAGS = "all_flags";
+ private static final String FLAG_COMMAND = "flag";
private final FlagManager mFlagManager;
private final SecureSettings mSecureSettings;
@@ -86,12 +95,15 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
@Main Resources resources,
DumpManager dumpManager,
@Named(ALL_FLAGS) Map<Integer, Flag<?>> allFlags,
+ CommandRegistry commandRegistry,
IStatusBarService barService) {
mFlagManager = flagManager;
mSecureSettings = secureSettings;
mResources = resources;
mSystemProperties = systemProperties;
mAllFlags = allFlags;
+ mBarService = barService;
+
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_SET_FLAG);
filter.addAction(ACTION_GET_FLAGS);
@@ -100,7 +112,7 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
context.registerReceiver(mReceiver, filter, null, null,
Context.RECEIVER_EXPORTED_UNAUDITED);
dumpManager.registerDumpable(TAG, this);
- mBarService = barService;
+ commandRegistry.registerCommand(FLAG_COMMAND, FlagCommand::new);
}
@Override
@@ -276,6 +288,31 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
}
}
+ private void setBooleanFlagInternal(Flag<?> flag, boolean value) {
+ if (flag instanceof BooleanFlag) {
+ setFlagValue(flag.getId(), value, BooleanFlagSerializer.INSTANCE);
+ } else if (flag instanceof ResourceBooleanFlag) {
+ setFlagValue(flag.getId(), value, BooleanFlagSerializer.INSTANCE);
+ } else if (flag instanceof SysPropBooleanFlag) {
+ // Store SysProp flags in SystemProperties where they can read by outside parties.
+ mSystemProperties.setBoolean(((SysPropBooleanFlag) flag).getName(), value);
+ dispatchListenersAndMaybeRestart(flag.getId(),
+ FeatureFlagsDebug.this::restartAndroid);
+ } else {
+ throw new IllegalArgumentException("Unknown flag type");
+ }
+ }
+
+ private void setStringFlagInternal(Flag<?> flag, String value) {
+ if (flag instanceof StringFlag) {
+ setFlagValue(flag.getId(), value, StringFlagSerializer.INSTANCE);
+ } else if (flag instanceof ResourceStringFlag) {
+ setFlagValue(flag.getId(), value, StringFlagSerializer.INSTANCE);
+ } else {
+ throw new IllegalArgumentException("Unknown flag type");
+ }
+ }
+
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -327,24 +364,19 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
}
Object value = extras.get(EXTRA_VALUE);
- if (flag instanceof BooleanFlag && value instanceof Boolean) {
- setFlagValue(id, (Boolean) value, BooleanFlagSerializer.INSTANCE);
- } else if (flag instanceof ResourceBooleanFlag && value instanceof Boolean) {
- setFlagValue(id, (Boolean) value, BooleanFlagSerializer.INSTANCE);
- } else if (flag instanceof SysPropBooleanFlag && value instanceof Boolean) {
- // Store SysProp flags in SystemProperties where they can read by outside parties.
- mSystemProperties.setBoolean(
- ((SysPropBooleanFlag) flag).getName(), (Boolean) value);
- dispatchListenersAndMaybeRestart(flag.getId(),
- FeatureFlagsDebug.this::restartAndroid);
- } else if (flag instanceof StringFlag && value instanceof String) {
- setFlagValue(id, (String) value, StringFlagSerializer.INSTANCE);
- } else if (flag instanceof ResourceStringFlag && value instanceof String) {
- setFlagValue(id, (String) value, StringFlagSerializer.INSTANCE);
- } else {
+
+ try {
+ if (value instanceof Boolean) {
+ setBooleanFlagInternal(flag, (Boolean) value);
+ } else if (value instanceof String) {
+ setStringFlagInternal(flag, (String) value);
+ } else {
+ throw new IllegalArgumentException("Unknown value type");
+ }
+ } catch (IllegalArgumentException e) {
Log.w(TAG,
- "Unable to set " + id + " of type " + flag.getClass() + " to value of type "
- + (value == null ? null : value.getClass()));
+ "Unable to set " + flag.getId() + " of type " + flag.getClass()
+ + " to value of type " + (value == null ? null : value.getClass()));
}
}
@@ -388,4 +420,153 @@ public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
mStringFlagCache.forEach((key, value) -> pw.println(" sysui_flag_" + key
+ ": [length=" + value.length() + "] \"" + value + "\""));
}
+
+ class FlagCommand implements Command {
+ private final List<String> mOnCommands = List.of("true", "on", "1", "enabled");
+ private final List<String> mOffCommands = List.of("false", "off", "0", "disable");
+
+ @Override
+ public void execute(@NonNull PrintWriter pw, @NonNull List<String> args) {
+ if (args.size() == 0) {
+ pw.println("Error: no flag id supplied");
+ help(pw);
+ pw.println();
+ printKnownFlags(pw);
+ return;
+ }
+
+ if (args.size() > 2) {
+ pw.println("Invalid number of arguments.");
+ help(pw);
+ return;
+ }
+
+ int id = 0;
+ try {
+ id = Integer.parseInt(args.get(0));
+ if (!mAllFlags.containsKey(id)) {
+ pw.println("Unknown flag id: " + id);
+ pw.println();
+ printKnownFlags(pw);
+ return;
+ }
+ } catch (NumberFormatException e) {
+ id = flagNameToId(args.get(0));
+ if (id == 0) {
+ pw.println("Invalid flag. Must an integer id or flag name: " + args.get(0));
+ return;
+ }
+ }
+ Flag<?> flag = mAllFlags.get(id);
+
+ String cmd = "";
+ if (args.size() == 2) {
+ cmd = args.get(1).toLowerCase();
+ }
+
+ if ("erase".equals(cmd) || "reset".equals(cmd)) {
+ eraseFlag(flag);
+ return;
+ }
+
+ boolean newValue = true;
+ if (args.size() == 1 || "toggle".equals(cmd)) {
+ boolean enabled = isBooleanFlagEnabled(flag);
+
+ if (args.size() == 1) {
+ pw.println("Flag " + id + " is " + enabled);
+ return;
+ }
+
+ newValue = !enabled;
+ } else {
+ newValue = mOnCommands.contains(cmd);
+ if (!newValue && !mOffCommands.contains(cmd)) {
+ pw.println("Invalid on/off argument supplied");
+ help(pw);
+ return;
+ }
+ }
+
+ pw.flush(); // Next command will restart sysui, so flush before we do so.
+ setBooleanFlagInternal(flag, newValue);
+ }
+
+ @Override
+ public void help(PrintWriter pw) {
+ pw.println(
+ "Usage: adb shell cmd statusbar flag <id> "
+ + "[true|false|1|0|on|off|enable|disable|toggle|erase|reset]");
+ pw.println("The id can either be a numeric integer or the corresponding field name");
+ pw.println(
+ "If no argument is supplied after the id, the flags runtime value is output");
+ }
+
+ private boolean isBooleanFlagEnabled(Flag<?> flag) {
+ if (flag instanceof BooleanFlag) {
+ return isEnabled((BooleanFlag) flag);
+ } else if (flag instanceof ResourceBooleanFlag) {
+ return isEnabled((ResourceBooleanFlag) flag);
+ } else if (flag instanceof SysPropFlag) {
+ return isEnabled((SysPropBooleanFlag) flag);
+ }
+
+ return false;
+ }
+
+ private int flagNameToId(String flagName) {
+ List<Field> fields = Flags.getFlagFields();
+ for (Field field : fields) {
+ if (flagName.equals(field.getName())) {
+ return fieldToId(field);
+ }
+ }
+
+ return 0;
+ }
+
+ private int fieldToId(Field field) {
+ try {
+ Flag<?> flag = (Flag<?>) field.get(null);
+ return flag.getId();
+ } catch (IllegalAccessException e) {
+ // no-op
+ }
+
+ return 0;
+ }
+
+ private void printKnownFlags(PrintWriter pw) {
+ List<Field> fields = Flags.getFlagFields();
+
+ int longestFieldName = 0;
+ for (Field field : fields) {
+ longestFieldName = Math.max(longestFieldName, field.getName().length());
+ }
+
+ pw.println("Known Flags:");
+ pw.print("Flag Name");
+ for (int i = 0; i < longestFieldName - "Flag Name".length() + 1; i++) {
+ pw.print(" ");
+ }
+ pw.println("ID Enabled?");
+ for (int i = 0; i < longestFieldName; i++) {
+ pw.print("=");
+ }
+ pw.println(" ==== ========");
+ for (Field field : fields) {
+ int id = fieldToId(field);
+ if (id == 0 || !mAllFlags.containsKey(id)) {
+ continue;
+ }
+ pw.print(field.getName());
+ int fieldWidth = field.getName().length();
+ for (int i = 0; i < longestFieldName - fieldWidth + 1; i++) {
+ pw.print(" ");
+ }
+ pw.printf("%-4d ", id);
+ pw.println(isBooleanFlagEnabled(mAllFlags.get(id)));
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
index 44580aa4230a..afa7d5e0a9c4 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
@@ -20,7 +20,9 @@ import com.android.internal.annotations.Keep;
import com.android.systemui.R;
import java.lang.reflect.Field;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
/**
@@ -182,25 +184,36 @@ public class Flags {
if (sFlagMap != null) {
return sFlagMap;
}
+
Map<Integer, Flag<?>> flags = new HashMap<>();
+ List<Field> flagFields = getFlagFields();
+
+ for (Field field : flagFields) {
+ try {
+ Flag<?> flag = (Flag<?>) field.get(null);
+ flags.put(flag.getId(), flag);
+ } catch (IllegalAccessException e) {
+ // no-op
+ }
+ }
+ sFlagMap = flags;
+
+ return sFlagMap;
+ }
+
+ static List<Field> getFlagFields() {
Field[] fields = Flags.class.getFields();
+ List<Field> result = new ArrayList<>();
for (Field field : fields) {
Class<?> t = field.getType();
if (Flag.class.isAssignableFrom(t)) {
- try {
- Flag<?> flag = (Flag<?>) field.get(null);
- flags.put(flag.getId(), flag);
- } catch (IllegalAccessException e) {
- // no-op
- }
+ result.add(field);
}
}
- sFlagMap = flags;
-
- return sFlagMap;
+ return result;
}
// | . . . . . . . . . . . . . . . . . . . |
// | |
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index a264afd3e0ef..d3e2fc8f2424 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -100,8 +100,7 @@ public class MediaControlPanel {
+ ".android.apps.gsa.staticplugins.opa.smartspace.ExportedSmartspaceTrampolineActivity";
private static final String EXTRAS_SMARTSPACE_INTENT =
"com.google.android.apps.gsa.smartspace.extra.SMARTSPACE_INTENT";
- private static final int MEDIA_RECOMMENDATION_ITEMS_PER_ROW = 3;
- private static final int MEDIA_RECOMMENDATION_MAX_NUM = 6;
+ private static final int MEDIA_RECOMMENDATION_MAX_NUM = 3;
private static final String KEY_SMARTSPACE_ARTIST_NAME = "artist_name";
private static final String KEY_SMARTSPACE_OPEN_IN_FOREGROUND = "KEY_OPEN_IN_FOREGROUND";
private static final String KEY_SMARTSPACE_APP_NAME = "KEY_SMARTSPACE_APP_NAME";
@@ -1001,11 +1000,6 @@ public class MediaControlPanel {
appName = packageManager.getApplicationLabel(applicationInfo);
}
}
- // Set the app name as card's title.
- if (!TextUtils.isEmpty(appName)) {
- TextView headerTitleText = mRecommendationViewHolder.getCardText();
- headerTitleText.setText(appName);
- }
// Set up media rec card's tap action if applicable.
setSmartspaceRecItemOnClickListener(recommendationCard, data.getCardAction(),
@@ -1016,11 +1010,6 @@ public class MediaControlPanel {
List<ImageView> mediaCoverItems = mRecommendationViewHolder.getMediaCoverItems();
List<ViewGroup> mediaCoverContainers = mRecommendationViewHolder.getMediaCoverContainers();
- List<Integer> mediaCoverItemsResIds = mRecommendationViewHolder.getMediaCoverItemsResIds();
- List<Integer> mediaCoverContainersResIds =
- mRecommendationViewHolder.getMediaCoverContainersResIds();
- ConstraintSet expandedSet = mMediaViewController.getExpandedLayout();
- ConstraintSet collapsedSet = mMediaViewController.getCollapsedLayout();
int mediaRecommendationNum = Math.min(mediaRecommendationList.size(),
MEDIA_RECOMMENDATION_MAX_NUM);
int uiComponentIndex = 0;
@@ -1065,21 +1054,6 @@ public class MediaControlPanel {
recommendation.getTitle(), artistName, appName));
}
- if (uiComponentIndex < MEDIA_RECOMMENDATION_ITEMS_PER_ROW) {
- setVisibleAndAlpha(collapsedSet,
- mediaCoverItemsResIds.get(uiComponentIndex), true);
- setVisibleAndAlpha(collapsedSet,
- mediaCoverContainersResIds.get(uiComponentIndex), true);
- } else {
- setVisibleAndAlpha(collapsedSet,
- mediaCoverItemsResIds.get(uiComponentIndex), false);
- setVisibleAndAlpha(collapsedSet,
- mediaCoverContainersResIds.get(uiComponentIndex), false);
- }
- setVisibleAndAlpha(expandedSet,
- mediaCoverItemsResIds.get(uiComponentIndex), true);
- setVisibleAndAlpha(expandedSet,
- mediaCoverContainersResIds.get(uiComponentIndex), true);
uiComponentIndex++;
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt
index c0f79d575dc6..b2acc92fb30d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt
@@ -31,35 +31,14 @@ class RecommendationViewHolder private constructor(itemView: View) {
// Recommendation screen
val cardIcon = itemView.requireViewById<ImageView>(R.id.recommendation_card_icon)
- val cardText = itemView.requireViewById<TextView>(R.id.recommendation_card_text)
val mediaCoverItems = listOf<ImageView>(
itemView.requireViewById(R.id.media_cover1),
itemView.requireViewById(R.id.media_cover2),
- itemView.requireViewById(R.id.media_cover3),
- itemView.requireViewById(R.id.media_cover4),
- itemView.requireViewById(R.id.media_cover5),
- itemView.requireViewById(R.id.media_cover6))
+ itemView.requireViewById(R.id.media_cover3))
val mediaCoverContainers = listOf<ViewGroup>(
itemView.requireViewById(R.id.media_cover1_container),
itemView.requireViewById(R.id.media_cover2_container),
- itemView.requireViewById(R.id.media_cover3_container),
- itemView.requireViewById(R.id.media_cover4_container),
- itemView.requireViewById(R.id.media_cover5_container),
- itemView.requireViewById(R.id.media_cover6_container))
- val mediaCoverItemsResIds = listOf<Int>(
- R.id.media_cover1,
- R.id.media_cover2,
- R.id.media_cover3,
- R.id.media_cover4,
- R.id.media_cover5,
- R.id.media_cover6)
- val mediaCoverContainersResIds = listOf<Int>(
- R.id.media_cover1_container,
- R.id.media_cover2_container,
- R.id.media_cover3_container,
- R.id.media_cover4_container,
- R.id.media_cover5_container,
- R.id.media_cover6_container)
+ itemView.requireViewById(R.id.media_cover3_container))
// Settings/Guts screen
val longPressText = itemView.requireViewById<TextView>(R.id.remove_text)
@@ -107,19 +86,12 @@ class RecommendationViewHolder private constructor(itemView: View) {
// Res Ids for the control components on the recommendation view.
val controlsIds = setOf(
R.id.recommendation_card_icon,
- R.id.recommendation_card_text,
R.id.media_cover1,
R.id.media_cover2,
R.id.media_cover3,
- R.id.media_cover4,
- R.id.media_cover5,
- R.id.media_cover6,
R.id.media_cover1_container,
R.id.media_cover2_container,
R.id.media_cover3_container,
- R.id.media_cover4_container,
- R.id.media_cover5_container,
- R.id.media_cover6_container
)
// Res Ids for the components on the guts panel.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt b/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
index cc37ef40321c..13340b7245fa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
@@ -234,6 +234,7 @@ class FgsManagerController @Inject constructor(
val dialog = SystemUIDialog(context)
dialog.setTitle(R.string.fgs_manager_dialog_title)
+ dialog.setMessage(R.string.fgs_manager_dialog_message)
val dialogContext = dialog.context
@@ -241,7 +242,9 @@ class FgsManagerController @Inject constructor(
recyclerView.layoutManager = LinearLayoutManager(dialogContext)
recyclerView.adapter = appListAdapter
- dialog.setView(recyclerView)
+ val topSpacing = dialogContext.resources
+ .getDimensionPixelSize(R.dimen.fgs_manager_list_top_spacing)
+ dialog.setView(recyclerView, 0, topSpacing, 0, 0)
this.dialog = dialog
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 83138f0666c1..551e8b51ae11 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -502,8 +502,8 @@ public class KeyguardIndicationController {
private void updateLockScreenTrustMsg(int userId, CharSequence trustGrantedIndication,
CharSequence trustManagedIndication) {
- if (!TextUtils.isEmpty(trustGrantedIndication)
- && mKeyguardUpdateMonitor.getUserHasTrust(userId)) {
+ final boolean userHasTrust = mKeyguardUpdateMonitor.getUserHasTrust(userId);
+ if (!TextUtils.isEmpty(trustGrantedIndication) && userHasTrust) {
mRotateTextViewController.updateIndication(
INDICATION_TYPE_TRUST,
new KeyguardIndication.Builder()
@@ -513,7 +513,7 @@ public class KeyguardIndicationController {
false);
} else if (!TextUtils.isEmpty(trustManagedIndication)
&& mKeyguardUpdateMonitor.getUserTrustIsManaged(userId)
- && !mKeyguardUpdateMonitor.getUserHasTrust(userId)) {
+ && !userHasTrust) {
mRotateTextViewController.updateIndication(
INDICATION_TYPE_TRUST,
new KeyguardIndication.Builder()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
index 7db677ab6305..3e32b64ebe3a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
@@ -71,7 +71,13 @@ class KeyguardLiftController @Inject constructor(
isListening = false
updateListeningState()
keyguardUpdateMonitor.requestFaceAuth(true)
- keyguardUpdateMonitor.requestActiveUnlock()
+ if (keyguardUpdateMonitor.mRequestActiveUnlockOnWakeup) {
+ keyguardUpdateMonitor.requestActiveUnlock("wake-unlock," +
+ " extra=KeyguardLiftController")
+ } else if (keyguardUpdateMonitor.mInitiateActiveUnlockOnWakeup) {
+ keyguardUpdateMonitor.initiateActiveUnlock("wake-initiate," +
+ " extra=KeyguardLiftController")
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index c1142edec77c..f269c8d9b13e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -3336,6 +3336,12 @@ public class NotificationPanelViewController extends PanelViewController {
.log(LockscreenUiEvent.LOCKSCREEN_LOCK_SHOW_HINT);
startUnlockHintAnimation();
}
+ if (mUpdateMonitor.isFaceEnrolled()
+ && mUpdateMonitor.mRequestActiveUnlockOnUnlockIntent
+ && mKeyguardBypassController.canBypass()) {
+ mUpdateMonitor.requestActiveUnlock("unlock-intent,"
+ + " extra=lockScreenEmptySpaceTap", true);
+ }
}
return true;
case StatusBarState.SHADE_LOCKED:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
index 56c74bf98e6b..24660b261c51 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
@@ -288,7 +288,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
final boolean keyguardOrAod = state.mKeyguardShowing
|| (state.mDozing && mDozeParameters.getAlwaysOn());
if ((keyguardOrAod && !state.mBackdropShowing && !state.mLightRevealScrimOpaque)
- || mKeyguardViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe()) {
+ || mKeyguardViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehind()) {
// Show the wallpaper if we're on keyguard/AOD and the wallpaper is not occluded by a
// solid backdrop. Also, show it if we are currently animating between the
// keyguard and the surface behind the keyguard - we want to use the wallpaper as a
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 49cd56f0176d..8016ea598b03 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -589,10 +589,12 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
}
private void updateAlternateAuthShowing(boolean updateScrim) {
+ final boolean isShowingAltAuth = isShowingAlternateAuth();
if (mKeyguardMessageAreaController != null) {
- mKeyguardMessageAreaController.setAltBouncerShowing(isShowingAlternateAuth());
+ mKeyguardMessageAreaController.setAltBouncerShowing(isShowingAltAuth);
}
- mBypassController.setAltBouncerShowing(isShowingAlternateAuth());
+ mBypassController.setAltBouncerShowing(isShowingAltAuth);
+ mKeyguardUpdateManager.setUdfpsBouncerShowing(isShowingAltAuth);
if (updateScrim) {
mCentralSurfaces.updateScrimController();
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
index cc606de1b0b9..b1e2012ecd40 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
@@ -97,5 +97,6 @@ private fun faceModel(user: Int) = KeyguardFaceListenModel(
primaryUser = false,
scanningAllowedByStrongAuth = false,
secureCameraLaunched = false,
- switchingUser = false
+ switchingUser = false,
+ udfpsBouncerShowing = false
)
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index 14c903c86b62..ba058c71a7f4 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -291,7 +291,9 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
@Test
public void testTwoOrMoreUsersDoesAllowDropDown() {
// GIVEN one user has been setup
- when(mUserSwitcherController.getUsers()).thenReturn(buildUserRecords(2));
+ ArrayList<UserRecord> records = buildUserRecords(2);
+ when(mUserSwitcherController.getCurrentUserRecord()).thenReturn(records.get(0));
+ when(mUserSwitcherController.getUsers()).thenReturn(records);
// WHEN UserSwitcherViewMode is initialized
setupUserSwitcher();
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 775addd9390b..86a4f5ad43b0 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -269,7 +269,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.registerCallback(mTestCallback);
mTestableLooper.processAllMessages();
- when(mAuthController.areAllAuthenticatorsRegistered()).thenReturn(true);
+ when(mAuthController.areAllFingerprintAuthenticatorsRegistered()).thenReturn(true);
}
@After
@@ -499,7 +499,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
@Test
public void test_doesNotTryToAuthenticateFingerprint_whenAuthenticatorsNotRegistered() {
- when(mAuthController.areAllAuthenticatorsRegistered()).thenReturn(false);
+ when(mAuthController.areAllFingerprintAuthenticatorsRegistered()).thenReturn(false);
mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
mTestableLooper.processAllMessages();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index 4858ab5234f8..28da2f13eb69 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -50,6 +50,7 @@ import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricPrompt;
+import android.hardware.biometrics.BiometricStateListener;
import android.hardware.biometrics.ComponentInfoInternal;
import android.hardware.biometrics.IBiometricContextListener;
import android.hardware.biometrics.IBiometricSysuiReceiver;
@@ -60,7 +61,6 @@ import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorProperties;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.hardware.fingerprint.FingerprintStateListener;
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
import android.os.Bundle;
import android.os.Handler;
@@ -151,7 +151,7 @@ public class AuthControllerTest extends SysuiTestCase {
@Captor
ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mAuthenticatorsRegisteredCaptor;
@Captor
- ArgumentCaptor<FingerprintStateListener> mFingerprintStateCaptor;
+ ArgumentCaptor<BiometricStateListener> mBiometricStateCaptor;
@Captor
ArgumentCaptor<StatusBarStateController.StateListener> mStatusBarStateListenerCaptor;
@@ -226,7 +226,7 @@ public class AuthControllerTest extends SysuiTestCase {
// Callback tests
@Test
- public void testRegistersFingerprintStateListener_afterAllAuthenticatorsAreRegistered()
+ public void testRegistersBiometricStateListener_afterAllAuthenticatorsAreRegistered()
throws RemoteException {
// This test is sensitive to prior FingerprintManager interactions.
reset(mFingerprintManager);
@@ -242,12 +242,12 @@ public class AuthControllerTest extends SysuiTestCase {
mAuthenticatorsRegisteredCaptor.capture());
mTestableLooper.processAllMessages();
- verify(mFingerprintManager, never()).registerFingerprintStateListener(any());
+ verify(mFingerprintManager, never()).registerBiometricStateListener(any());
mAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(new ArrayList<>());
mTestableLooper.processAllMessages();
- verify(mFingerprintManager).registerFingerprintStateListener(any());
+ verify(mFingerprintManager).registerBiometricStateListener(any());
}
@Test
@@ -269,11 +269,11 @@ public class AuthControllerTest extends SysuiTestCase {
mAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(new ArrayList<>());
mTestableLooper.processAllMessages();
- verify(mFingerprintManager).registerFingerprintStateListener(
- mFingerprintStateCaptor.capture());
+ verify(mFingerprintManager).registerBiometricStateListener(
+ mBiometricStateCaptor.capture());
// Enrollments changed for an unknown sensor.
- mFingerprintStateCaptor.getValue().onEnrollmentsChanged(0 /* userId */,
+ mBiometricStateCaptor.getValue().onEnrollmentsChanged(0 /* userId */,
0xbeef /* sensorId */, true /* hasEnrollments */);
mTestableLooper.processAllMessages();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt
index 6626bbe69706..b43856aae4cf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt
@@ -24,7 +24,11 @@ import android.test.suitebuilder.annotation.SmallTest
import com.android.internal.statusbar.IStatusBarService
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.commandline.Command
+import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.nullable
import com.android.systemui.util.mockito.withArgCaptor
@@ -37,10 +41,12 @@ import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.Mockito.anyBoolean
import org.mockito.Mockito.anyString
+import org.mockito.Mockito.atLeastOnce
import org.mockito.Mockito.inOrder
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
+import org.mockito.Mockito.verifyZeroInteractions
import org.mockito.MockitoAnnotations
import java.io.PrintWriter
import java.io.Serializable
@@ -56,16 +62,18 @@ import org.mockito.Mockito.`when` as whenever
class FeatureFlagsDebugTest : SysuiTestCase() {
private lateinit var mFeatureFlagsDebug: FeatureFlagsDebug
- @Mock private lateinit var mFlagManager: FlagManager
- @Mock private lateinit var mMockContext: Context
- @Mock private lateinit var mSecureSettings: SecureSettings
- @Mock private lateinit var mSystemProperties: SystemPropertiesHelper
- @Mock private lateinit var mResources: Resources
- @Mock private lateinit var mDumpManager: DumpManager
- @Mock private lateinit var mBarService: IStatusBarService
- private val mFlagMap = mutableMapOf<Int, Flag<*>>()
- private lateinit var mBroadcastReceiver: BroadcastReceiver
- private lateinit var mClearCacheAction: Consumer<Int>
+ @Mock private lateinit var flagManager: FlagManager
+ @Mock private lateinit var mockContext: Context
+ @Mock private lateinit var secureSettings: SecureSettings
+ @Mock private lateinit var systemProperties: SystemPropertiesHelper
+ @Mock private lateinit var resources: Resources
+ @Mock private lateinit var dumpManager: DumpManager
+ @Mock private lateinit var commandRegistry: CommandRegistry
+ @Mock private lateinit var barService: IStatusBarService
+ @Mock private lateinit var pw: PrintWriter
+ private val flagMap = mutableMapOf<Int, Flag<*>>()
+ private lateinit var broadcastReceiver: BroadcastReceiver
+ private lateinit var clearCacheAction: Consumer<Int>
private val teamfoodableFlagA = BooleanFlag(500, false, true)
private val teamfoodableFlagB = BooleanFlag(501, true, true)
@@ -73,34 +81,35 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- mFlagMap.put(teamfoodableFlagA.id, teamfoodableFlagA)
- mFlagMap.put(teamfoodableFlagB.id, teamfoodableFlagB)
+ flagMap.put(teamfoodableFlagA.id, teamfoodableFlagA)
+ flagMap.put(teamfoodableFlagB.id, teamfoodableFlagB)
mFeatureFlagsDebug = FeatureFlagsDebug(
- mFlagManager,
- mMockContext,
- mSecureSettings,
- mSystemProperties,
- mResources,
- mDumpManager,
- mFlagMap,
- mBarService
+ flagManager,
+ mockContext,
+ secureSettings,
+ systemProperties,
+ resources,
+ dumpManager,
+ flagMap,
+ commandRegistry,
+ barService
)
- verify(mFlagManager).onSettingsChangedAction = any()
- mBroadcastReceiver = withArgCaptor {
- verify(mMockContext).registerReceiver(capture(), any(), nullable(), nullable(),
+ verify(flagManager).onSettingsChangedAction = any()
+ broadcastReceiver = withArgCaptor {
+ verify(mockContext).registerReceiver(capture(), any(), nullable(), nullable(),
any())
}
- mClearCacheAction = withArgCaptor {
- verify(mFlagManager).clearCacheAction = capture()
+ clearCacheAction = withArgCaptor {
+ verify(flagManager).clearCacheAction = capture()
}
- whenever(mFlagManager.idToSettingsKey(any())).thenAnswer { "key-${it.arguments[0]}" }
+ whenever(flagManager.idToSettingsKey(any())).thenAnswer { "key-${it.arguments[0]}" }
}
@Test
fun testReadBooleanFlag() {
// Remember that the TEAMFOOD flag is id#1 and has special behavior.
- whenever(mFlagManager.readFlagValue<Boolean>(eq(3), any())).thenReturn(true)
- whenever(mFlagManager.readFlagValue<Boolean>(eq(4), any())).thenReturn(false)
+ whenever(flagManager.readFlagValue<Boolean>(eq(3), any())).thenReturn(true)
+ whenever(flagManager.readFlagValue<Boolean>(eq(4), any())).thenReturn(false)
assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(2, true))).isTrue()
assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(3, false))).isTrue()
assertThat(mFeatureFlagsDebug.isEnabled(BooleanFlag(4, true))).isFalse()
@@ -109,7 +118,7 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
@Test
fun testTeamFoodFlag_False() {
- whenever(mFlagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(false)
+ whenever(flagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(false)
assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagA)).isFalse()
assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagB)).isTrue()
@@ -120,7 +129,7 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
@Test
fun testTeamFoodFlag_True() {
- whenever(mFlagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(true)
+ whenever(flagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(true)
assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagA)).isTrue()
assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagB)).isTrue()
@@ -131,11 +140,11 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
@Test
fun testTeamFoodFlag_Overridden() {
- whenever(mFlagManager.readFlagValue<Boolean>(eq(teamfoodableFlagA.id), any()))
+ whenever(flagManager.readFlagValue<Boolean>(eq(teamfoodableFlagA.id), any()))
.thenReturn(true)
- whenever(mFlagManager.readFlagValue<Boolean>(eq(teamfoodableFlagB.id), any()))
+ whenever(flagManager.readFlagValue<Boolean>(eq(teamfoodableFlagB.id), any()))
.thenReturn(false)
- whenever(mFlagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(true)
+ whenever(flagManager.readFlagValue<Boolean>(eq(1), any())).thenReturn(true)
assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagA)).isTrue()
assertThat(mFeatureFlagsDebug.isEnabled(teamfoodableFlagB)).isFalse()
@@ -146,14 +155,14 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
@Test
fun testReadResourceBooleanFlag() {
- whenever(mResources.getBoolean(1001)).thenReturn(false)
- whenever(mResources.getBoolean(1002)).thenReturn(true)
- whenever(mResources.getBoolean(1003)).thenReturn(false)
- whenever(mResources.getBoolean(1004)).thenAnswer { throw NameNotFoundException() }
- whenever(mResources.getBoolean(1005)).thenAnswer { throw NameNotFoundException() }
+ whenever(resources.getBoolean(1001)).thenReturn(false)
+ whenever(resources.getBoolean(1002)).thenReturn(true)
+ whenever(resources.getBoolean(1003)).thenReturn(false)
+ whenever(resources.getBoolean(1004)).thenAnswer { throw NameNotFoundException() }
+ whenever(resources.getBoolean(1005)).thenAnswer { throw NameNotFoundException() }
- whenever(mFlagManager.readFlagValue<Boolean>(eq(3), any())).thenReturn(true)
- whenever(mFlagManager.readFlagValue<Boolean>(eq(5), any())).thenReturn(false)
+ whenever(flagManager.readFlagValue<Boolean>(eq(3), any())).thenReturn(true)
+ whenever(flagManager.readFlagValue<Boolean>(eq(5), any())).thenReturn(false)
assertThat(mFeatureFlagsDebug.isEnabled(ResourceBooleanFlag(1, 1001))).isFalse()
assertThat(mFeatureFlagsDebug.isEnabled(ResourceBooleanFlag(2, 1002))).isTrue()
@@ -171,7 +180,7 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
@Test
fun testReadSysPropBooleanFlag() {
- whenever(mSystemProperties.getBoolean(anyString(), anyBoolean())).thenAnswer {
+ whenever(systemProperties.getBoolean(anyString(), anyBoolean())).thenAnswer {
if ("b".equals(it.getArgument<String?>(0))) {
return@thenAnswer true
}
@@ -187,8 +196,8 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
@Test
fun testReadStringFlag() {
- whenever(mFlagManager.readFlagValue<String>(eq(3), any())).thenReturn("foo")
- whenever(mFlagManager.readFlagValue<String>(eq(4), any())).thenReturn("bar")
+ whenever(flagManager.readFlagValue<String>(eq(3), any())).thenReturn("foo")
+ whenever(flagManager.readFlagValue<String>(eq(4), any())).thenReturn("bar")
assertThat(mFeatureFlagsDebug.getString(StringFlag(1, "biz"))).isEqualTo("biz")
assertThat(mFeatureFlagsDebug.getString(StringFlag(2, "baz"))).isEqualTo("baz")
assertThat(mFeatureFlagsDebug.getString(StringFlag(3, "buz"))).isEqualTo("foo")
@@ -197,16 +206,16 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
@Test
fun testReadResourceStringFlag() {
- whenever(mResources.getString(1001)).thenReturn("")
- whenever(mResources.getString(1002)).thenReturn("resource2")
- whenever(mResources.getString(1003)).thenReturn("resource3")
- whenever(mResources.getString(1004)).thenReturn(null)
- whenever(mResources.getString(1005)).thenAnswer { throw NameNotFoundException() }
- whenever(mResources.getString(1006)).thenAnswer { throw NameNotFoundException() }
+ whenever(resources.getString(1001)).thenReturn("")
+ whenever(resources.getString(1002)).thenReturn("resource2")
+ whenever(resources.getString(1003)).thenReturn("resource3")
+ whenever(resources.getString(1004)).thenReturn(null)
+ whenever(resources.getString(1005)).thenAnswer { throw NameNotFoundException() }
+ whenever(resources.getString(1006)).thenAnswer { throw NameNotFoundException() }
- whenever(mFlagManager.readFlagValue<String>(eq(3), any())).thenReturn("override3")
- whenever(mFlagManager.readFlagValue<String>(eq(4), any())).thenReturn("override4")
- whenever(mFlagManager.readFlagValue<String>(eq(6), any())).thenReturn("override6")
+ whenever(flagManager.readFlagValue<String>(eq(3), any())).thenReturn("override3")
+ whenever(flagManager.readFlagValue<String>(eq(4), any())).thenReturn("override4")
+ whenever(flagManager.readFlagValue<String>(eq(6), any())).thenReturn("override6")
assertThat(mFeatureFlagsDebug.getString(ResourceStringFlag(1, 1001))).isEqualTo("")
assertThat(mFeatureFlagsDebug.getString(ResourceStringFlag(2, 1002))).isEqualTo("resource2")
@@ -232,16 +241,16 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
addFlag(StringFlag(3, "flag3"))
addFlag(ResourceStringFlag(4, 1004))
- mBroadcastReceiver.onReceive(mMockContext, null)
- mBroadcastReceiver.onReceive(mMockContext, Intent())
- mBroadcastReceiver.onReceive(mMockContext, Intent("invalid action"))
- mBroadcastReceiver.onReceive(mMockContext, Intent(FlagManager.ACTION_SET_FLAG))
+ broadcastReceiver.onReceive(mockContext, null)
+ broadcastReceiver.onReceive(mockContext, Intent())
+ broadcastReceiver.onReceive(mockContext, Intent("invalid action"))
+ broadcastReceiver.onReceive(mockContext, Intent(FlagManager.ACTION_SET_FLAG))
setByBroadcast(0, false) // unknown id does nothing
setByBroadcast(1, "string") // wrong type does nothing
setByBroadcast(2, 123) // wrong type does nothing
setByBroadcast(3, false) // wrong type does nothing
setByBroadcast(4, 123) // wrong type does nothing
- verifyNoMoreInteractions(mFlagManager, mSecureSettings)
+ verifyNoMoreInteractions(flagManager, secureSettings)
}
@Test
@@ -249,15 +258,15 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
addFlag(BooleanFlag(1, false))
// trying to erase an id not in the map does noting
- mBroadcastReceiver.onReceive(
- mMockContext,
+ broadcastReceiver.onReceive(
+ mockContext,
Intent(FlagManager.ACTION_SET_FLAG).putExtra(FlagManager.EXTRA_ID, 0)
)
- verifyNoMoreInteractions(mFlagManager, mSecureSettings)
+ verifyNoMoreInteractions(flagManager, secureSettings)
// valid id with no value puts empty string in the setting
- mBroadcastReceiver.onReceive(
- mMockContext,
+ broadcastReceiver.onReceive(
+ mockContext,
Intent(FlagManager.ACTION_SET_FLAG).putExtra(FlagManager.EXTRA_ID, 1)
)
verifyPutData(1, "", numReads = 0)
@@ -298,48 +307,102 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
@Test
fun testSetFlagClearsCache() {
val flag1 = addFlag(StringFlag(1, "flag1"))
- whenever(mFlagManager.readFlagValue<String>(eq(1), any())).thenReturn("original")
+ whenever(flagManager.readFlagValue<String>(eq(1), any())).thenReturn("original")
// gets the flag & cache it
assertThat(mFeatureFlagsDebug.getString(flag1)).isEqualTo("original")
- verify(mFlagManager).readFlagValue(eq(1), eq(StringFlagSerializer))
+ verify(flagManager).readFlagValue(eq(1), eq(StringFlagSerializer))
// hit the cache
assertThat(mFeatureFlagsDebug.getString(flag1)).isEqualTo("original")
- verifyNoMoreInteractions(mFlagManager)
+ verifyNoMoreInteractions(flagManager)
// set the flag
setByBroadcast(1, "new")
verifyPutData(1, "{\"type\":\"string\",\"value\":\"new\"}", numReads = 2)
- whenever(mFlagManager.readFlagValue<String>(eq(1), any())).thenReturn("new")
+ whenever(flagManager.readFlagValue<String>(eq(1), any())).thenReturn("new")
assertThat(mFeatureFlagsDebug.getString(flag1)).isEqualTo("new")
- verify(mFlagManager, times(3)).readFlagValue(eq(1), eq(StringFlagSerializer))
+ verify(flagManager, times(3)).readFlagValue(eq(1), eq(StringFlagSerializer))
+ }
+
+ @Test
+ fun testRegisterCommand() {
+ verify(commandRegistry).registerCommand(anyString(), any())
+ }
+
+ @Test
+ fun testNoOpCommand() {
+ val cmd = captureCommand()
+
+ cmd.execute(pw, ArrayList())
+ verify(pw, atLeastOnce()).println()
+ verify(flagManager).readFlagValue<Boolean>(eq(1), any())
+ verifyZeroInteractions(secureSettings)
+ }
+
+ @Test
+ fun testReadFlagCommand() {
+ addFlag(BooleanFlag(1, false))
+ val cmd = captureCommand()
+ cmd.execute(pw, listOf("1"))
+ verify(flagManager).readFlagValue<Boolean>(eq(1), any())
+ }
+
+ @Test
+ fun testSetFlagCommand() {
+ addFlag(BooleanFlag(1, false))
+ val cmd = captureCommand()
+ cmd.execute(pw, listOf("1", "on"))
+ verifyPutData(1, "{\"type\":\"boolean\",\"value\":true}")
+ }
+
+ @Test
+ fun testToggleFlagCommand() {
+ addFlag(BooleanFlag(1, true))
+ val cmd = captureCommand()
+ cmd.execute(pw, listOf("1", "toggle"))
+ verifyPutData(1, "{\"type\":\"boolean\",\"value\":false}", 2)
+ }
+
+ @Test
+ fun testEraseFlagCommand() {
+ addFlag(BooleanFlag(1, true))
+ val cmd = captureCommand()
+ cmd.execute(pw, listOf("1", "erase"))
+ verify(secureSettings).putStringForUser(eq("key-1"), eq(""), anyInt())
}
private fun verifyPutData(id: Int, data: String, numReads: Int = 1) {
- inOrder(mFlagManager, mSecureSettings).apply {
- verify(mFlagManager, times(numReads)).readFlagValue(eq(id), any<FlagSerializer<*>>())
- verify(mFlagManager).idToSettingsKey(eq(id))
- verify(mSecureSettings).putStringForUser(eq("key-$id"), eq(data), anyInt())
- verify(mFlagManager).dispatchListenersAndMaybeRestart(eq(id), any())
+ inOrder(flagManager, secureSettings).apply {
+ verify(flagManager, times(numReads)).readFlagValue(eq(id), any<FlagSerializer<*>>())
+ verify(flagManager).idToSettingsKey(eq(id))
+ verify(secureSettings).putStringForUser(eq("key-$id"), eq(data), anyInt())
+ verify(flagManager).dispatchListenersAndMaybeRestart(eq(id), any())
}.verifyNoMoreInteractions()
- verifyNoMoreInteractions(mFlagManager, mSecureSettings)
+ verifyNoMoreInteractions(flagManager, secureSettings)
}
private fun setByBroadcast(id: Int, value: Serializable?) {
val intent = Intent(FlagManager.ACTION_SET_FLAG)
intent.putExtra(FlagManager.EXTRA_ID, id)
intent.putExtra(FlagManager.EXTRA_VALUE, value)
- mBroadcastReceiver.onReceive(mMockContext, intent)
+ broadcastReceiver.onReceive(mockContext, intent)
}
private fun <F : Flag<*>> addFlag(flag: F): F {
- val old = mFlagMap.put(flag.id, flag)
+ val old = flagMap.put(flag.id, flag)
check(old == null) { "Flag ${flag.id} already registered" }
return flag
}
+ private fun captureCommand(): Command {
+ val captor = argumentCaptor<Function0<Command>>()
+ verify(commandRegistry).registerCommand(anyString(), capture(captor))
+
+ return captor.value.invoke()
+ }
+
@Test
fun testDump() {
val flag1 = BooleanFlag(1, true)
@@ -350,10 +413,10 @@ class FeatureFlagsDebugTest : SysuiTestCase() {
val flag6 = ResourceStringFlag(6, 1006)
val flag7 = ResourceStringFlag(7, 1007)
- whenever(mResources.getBoolean(1002)).thenReturn(true)
- whenever(mResources.getString(1006)).thenReturn("resource1006")
- whenever(mResources.getString(1007)).thenReturn("resource1007")
- whenever(mFlagManager.readFlagValue(eq(7), eq(StringFlagSerializer)))
+ whenever(resources.getBoolean(1002)).thenReturn(true)
+ whenever(resources.getString(1006)).thenReturn("resource1006")
+ whenever(resources.getString(1007)).thenReturn("resource1007")
+ whenever(flagManager.readFlagValue(eq(7), eq(StringFlagSerializer)))
.thenReturn("override7")
// WHEN the flags have been accessed
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
index 74f1393ed457..607a873a73d1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
@@ -373,17 +373,12 @@ public class MediaControlPanelTest : SysuiTestCase() {
private fun initRecommendationViewHolderMocks() {
whenever(recommendationViewHolder.recommendations).thenReturn(view)
whenever(recommendationViewHolder.cardIcon).thenReturn(appIcon)
- whenever(recommendationViewHolder.cardText).thenReturn(titleText)
// Add a recommendation item
coverItem = ImageView(context).also { it.setId(R.id.media_cover1) }
whenever(coverContainer.id).thenReturn(R.id.media_cover1_container)
whenever(recommendationViewHolder.mediaCoverItems).thenReturn(listOf(coverItem))
whenever(recommendationViewHolder.mediaCoverContainers).thenReturn(listOf(coverContainer))
- whenever(recommendationViewHolder.mediaCoverItemsResIds)
- .thenReturn(listOf(R.id.media_cover1))
- whenever(recommendationViewHolder.mediaCoverContainersResIds)
- .thenReturn(listOf(R.id.media_cover1_container))
// Long press menu
whenever(recommendationViewHolder.settings).thenReturn(settings)
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index bc4b2a6f5247..5acae4859ee8 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -154,7 +154,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
private static final String TAG = "AppWidgetServiceImpl";
private static final boolean DEBUG = false;
- private static final boolean DEBUG_PROVIDER_INFO_CACHE = true;
+ static final boolean DEBUG_PROVIDER_INFO_CACHE = true;
private static final String OLD_KEYGUARD_HOST_PACKAGE = "android";
private static final String NEW_KEYGUARD_HOST_PACKAGE = "com.android.keyguard";
@@ -2001,6 +2001,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
}
}
+ @GuardedBy("mLock")
private void scheduleNotifyProviderChangedLocked(Widget widget) {
long requestId = UPDATE_COUNTER.incrementAndGet();
if (widget != null) {
@@ -2330,6 +2331,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
sendBroadcastAsUser(intent, widget.provider.id.getProfile());
}
+ @GuardedBy("mLock")
private void registerForBroadcastsLocked(Provider provider, int[] appWidgetIds) {
AppWidgetProviderInfo info = provider.getInfoLocked(mContext);
if (info.updatePeriodMillis > 0) {
@@ -3433,6 +3435,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
*
* @return whether any providers were updated
*/
+ @GuardedBy("mLock")
private boolean updateProvidersForPackageLocked(String packageName, int userId,
Set<ProviderId> removedProviders) {
boolean providersUpdated = false;
@@ -4218,6 +4221,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
/**
* Adds all pending updates in {@param outUpdates} keys by the update time.
*/
+ @GuardedBy("mLock")
public void getPendingUpdatesForIdLocked(Context context, int appWidgetId,
LongSparseArray<PendingHostUpdate> outUpdates) {
long updateSequenceNo = lastWidgetUpdateSequenceNo;
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java
index 297575ca168f..6a5dcc8c5945 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetXmlUtil.java
@@ -22,6 +22,7 @@ import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.os.Build;
import android.text.TextUtils;
+import android.util.Slog;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
@@ -33,6 +34,8 @@ import java.util.Objects;
*/
public class AppWidgetXmlUtil {
+ private static final String TAG = "AppWidgetXmlUtil";
+
private static final String ATTR_MIN_WIDTH = "min_width";
private static final String ATTR_MIN_HEIGHT = "min_height";
private static final String ATTR_MIN_RESIZE_WIDTH = "min_resize_width";
@@ -77,7 +80,11 @@ public class AppWidgetXmlUtil {
if (info.configure != null) {
out.attribute(null, ATTR_CONFIGURE, info.configure.flattenToShortString());
}
- out.attribute(null, ATTR_LABEL, info.label);
+ if (info.label != null) {
+ out.attribute(null, ATTR_LABEL, info.label);
+ } else if (AppWidgetServiceImpl.DEBUG_PROVIDER_INFO_CACHE) {
+ Slog.e(TAG, "Label is empty in " + info.provider);
+ }
out.attributeInt(null, ATTR_ICON, info.icon);
out.attributeInt(null, ATTR_PREVIEW_IMAGE, info.previewImage);
out.attributeInt(null, ATTR_PREVIEW_LAYOUT, info.previewLayout);
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index ac0944be9739..b4c107c1a2c1 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -671,6 +671,9 @@ public class CompanionDeviceManagerService extends SystemService {
association = AssociationInfo.builder(association)
.setNotifyOnDeviceNearby(active)
.build();
+ // Do not need to call {@link BleCompanionDeviceScanner#restartScan()} since it will
+ // trigger {@link BleCompanionDeviceScanner#restartScan(int, AssociationInfo)} when
+ // an application sets/unsets the mNotifyOnDeviceNearby flag.
mAssociationStore.updateAssociation(association);
// TODO(b/218615198): correctly handle the case when the device is currently present.
diff --git a/services/companion/java/com/android/server/companion/presence/BleCompanionDeviceScanner.java b/services/companion/java/com/android/server/companion/presence/BleCompanionDeviceScanner.java
index 33301b180619..ad09f7cd3dde 100644
--- a/services/companion/java/com/android/server/companion/presence/BleCompanionDeviceScanner.java
+++ b/services/companion/java/com/android/server/companion/presence/BleCompanionDeviceScanner.java
@@ -194,6 +194,8 @@ class BleCompanionDeviceScanner implements AssociationStore.OnChangeListener {
// Collect MAC addresses from all associations.
final Set<String> macAddresses = new HashSet<>();
for (AssociationInfo association : mAssociationStore.getAssociations()) {
+ if (!association.isNotifyOnDeviceNearby()) continue;
+
// Beware that BT stack does not consider low-case MAC addresses valid, while
// MacAddress.toString() return a low-case String.
final String macAddress = association.getDeviceMacAddressAsString();
diff --git a/services/core/java/com/android/server/BinaryTransparencyService.java b/services/core/java/com/android/server/BinaryTransparencyService.java
index 1f8ef8226c32..877ee8218ea6 100644
--- a/services/core/java/com/android/server/BinaryTransparencyService.java
+++ b/services/core/java/com/android/server/BinaryTransparencyService.java
@@ -441,6 +441,7 @@ public class BinaryTransparencyService extends SystemService {
final JobInfo jobInfo = new JobInfo.Builder(COMPUTE_APEX_MODULE_SHA256_JOB_ID,
new ComponentName(context, UpdateMeasurementsJobService.class))
.setRequiresDeviceIdle(true)
+ .setRequiresCharging(true)
.build();
if (jobScheduler.schedule(jobInfo) != JobScheduler.RESULT_SUCCESS) {
Slog.e(TAG, "Failed to schedule job to update binary measurements.");
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index 210532a88a8c..eefeee3918b3 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -87,6 +87,7 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -172,7 +173,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
@NonNull private final VcnNetworkProvider mNetworkProvider;
@NonNull private final TelephonySubscriptionTrackerCallback mTelephonySubscriptionTrackerCb;
@NonNull private final TelephonySubscriptionTracker mTelephonySubscriptionTracker;
- @NonNull private final BroadcastReceiver mPkgChangeReceiver;
+ @NonNull private final BroadcastReceiver mVcnBroadcastReceiver;
@NonNull
private final TrackingNetworkCallback mTrackingNetworkCallback = new TrackingNetworkCallback();
@@ -217,28 +218,17 @@ public class VcnManagementService extends IVcnManagementService.Stub {
mConfigDiskRwHelper = mDeps.newPersistableBundleLockingReadWriteHelper(VCN_CONFIG_FILE);
- mPkgChangeReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
-
- if (Intent.ACTION_PACKAGE_ADDED.equals(action)
- || Intent.ACTION_PACKAGE_REPLACED.equals(action)
- || Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
- mTelephonySubscriptionTracker.handleSubscriptionsChanged();
- } else {
- Log.wtf(TAG, "received unexpected intent: " + action);
- }
- }
- };
+ mVcnBroadcastReceiver = new VcnBroadcastReceiver();
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ intentFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
+ intentFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
intentFilter.addDataScheme("package");
mContext.registerReceiver(
- mPkgChangeReceiver, intentFilter, null /* broadcastPermission */, mHandler);
+ mVcnBroadcastReceiver, intentFilter, null /* broadcastPermission */, mHandler);
// Run on handler to ensure I/O does not block system server startup
mHandler.post(() -> {
@@ -443,6 +433,53 @@ public class VcnManagementService extends IVcnManagementService.Stub {
return Objects.equals(subGrp, snapshot.getActiveDataSubscriptionGroup());
}
+ private class VcnBroadcastReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+
+ switch (action) {
+ case Intent.ACTION_PACKAGE_ADDED: // Fallthrough
+ case Intent.ACTION_PACKAGE_REPLACED: // Fallthrough
+ case Intent.ACTION_PACKAGE_REMOVED:
+ // Reevaluate subscriptions
+ mTelephonySubscriptionTracker.handleSubscriptionsChanged();
+
+ break;
+ case Intent.ACTION_PACKAGE_FULLY_REMOVED:
+ case Intent.ACTION_PACKAGE_DATA_CLEARED:
+ final String pkgName = intent.getData().getSchemeSpecificPart();
+
+ if (pkgName == null || pkgName.isEmpty()) {
+ logWtf("Package name was empty or null for intent with action" + action);
+ return;
+ }
+
+ // Clear configs for the packages that had data cleared, or removed.
+ synchronized (mLock) {
+ final List<ParcelUuid> toRemove = new ArrayList<>();
+ for (Entry<ParcelUuid, VcnConfig> entry : mConfigs.entrySet()) {
+ if (pkgName.equals(entry.getValue().getProvisioningPackageName())) {
+ toRemove.add(entry.getKey());
+ }
+ }
+
+ for (ParcelUuid subGrp : toRemove) {
+ stopAndClearVcnConfigInternalLocked(subGrp);
+ }
+
+ if (!toRemove.isEmpty()) {
+ writeConfigsToDiskLocked();
+ }
+ }
+
+ break;
+ default:
+ Slog.wtf(TAG, "received unexpected intent: " + action);
+ }
+ }
+ }
+
private class VcnSubscriptionTrackerCallback implements TelephonySubscriptionTrackerCallback {
/**
* Handles subscription group changes, as notified by {@link TelephonySubscriptionTracker}
@@ -504,6 +541,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
final Map<ParcelUuid, Set<Integer>> currSubGrpMappings =
getSubGroupToSubIdMappings(mLastSnapshot);
if (!currSubGrpMappings.equals(oldSubGrpMappings)) {
+ garbageCollectAndWriteVcnConfigsLocked();
notifyAllPolicyListenersLocked();
}
}
@@ -645,6 +683,39 @@ public class VcnManagementService extends IVcnManagementService.Stub {
});
}
+ private void enforceCarrierPrivilegeOrProvisioningPackage(
+ @NonNull ParcelUuid subscriptionGroup, @NonNull String pkg) {
+ // Only apps running in the primary (system) user are allowed to configure the VCN. This is
+ // in line with Telephony's behavior with regards to binding to a Carrier App provided
+ // CarrierConfigService.
+ enforcePrimaryUser();
+
+ if (isProvisioningPackageForConfig(subscriptionGroup, pkg)) {
+ return;
+ }
+
+ // Must NOT be called from cleared binder identity, since this checks user calling identity
+ enforceCallingUserAndCarrierPrivilege(subscriptionGroup, pkg);
+ }
+
+ private boolean isProvisioningPackageForConfig(
+ @NonNull ParcelUuid subscriptionGroup, @NonNull String pkg) {
+ // Try-finally to return early if matching owned subscription found.
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ final VcnConfig config = mConfigs.get(subscriptionGroup);
+ if (config != null && pkg.equals(config.getProvisioningPackageName())) {
+ return true;
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+
+ return false;
+ }
+
/**
* Clears the VcnManagementService for a given subscription group.
*
@@ -658,31 +729,56 @@ public class VcnManagementService extends IVcnManagementService.Stub {
mContext.getSystemService(AppOpsManager.class)
.checkPackage(mDeps.getBinderCallingUid(), opPkgName);
- enforceCallingUserAndCarrierPrivilege(subscriptionGroup, opPkgName);
+ enforceCarrierPrivilegeOrProvisioningPackage(subscriptionGroup, opPkgName);
Binder.withCleanCallingIdentity(() -> {
synchronized (mLock) {
- mConfigs.remove(subscriptionGroup);
- final boolean vcnExists = mVcns.containsKey(subscriptionGroup);
+ stopAndClearVcnConfigInternalLocked(subscriptionGroup);
+ writeConfigsToDiskLocked();
+ }
+ });
+ }
- stopVcnLocked(subscriptionGroup);
+ private void stopAndClearVcnConfigInternalLocked(@NonNull ParcelUuid subscriptionGroup) {
+ mConfigs.remove(subscriptionGroup);
+ final boolean vcnExists = mVcns.containsKey(subscriptionGroup);
- if (vcnExists) {
- // TODO(b/181789060): invoke asynchronously after Vcn notifies through
- // VcnCallback
- notifyAllPermissionedStatusCallbacksLocked(
- subscriptionGroup, VCN_STATUS_CODE_NOT_CONFIGURED);
- }
+ stopVcnLocked(subscriptionGroup);
- writeConfigsToDiskLocked();
+ if (vcnExists) {
+ // TODO(b/181789060): invoke asynchronously after Vcn notifies through
+ // VcnCallback
+ notifyAllPermissionedStatusCallbacksLocked(
+ subscriptionGroup, VCN_STATUS_CODE_NOT_CONFIGURED);
+ }
+ }
+
+ private void garbageCollectAndWriteVcnConfigsLocked() {
+ final SubscriptionManager subMgr = mContext.getSystemService(SubscriptionManager.class);
+
+ boolean shouldWrite = false;
+
+ final Iterator<ParcelUuid> configsIterator = mConfigs.keySet().iterator();
+ while (configsIterator.hasNext()) {
+ final ParcelUuid subGrp = configsIterator.next();
+
+ final List<SubscriptionInfo> subscriptions = subMgr.getSubscriptionsInGroup(subGrp);
+ if (subscriptions == null || subscriptions.isEmpty()) {
+ // Trim subGrps with no more subscriptions; must have moved to another subGrp
+ configsIterator.remove();
+ shouldWrite = true;
}
- });
+ }
+
+ if (shouldWrite) {
+ writeConfigsToDiskLocked();
+ }
}
/**
* Retrieves the list of subscription groups with configured VcnConfigs
*
- * <p>Limited to subscription groups for which the caller is carrier privileged.
+ * <p>Limited to subscription groups for which the caller had configured.
*
* <p>Implements the IVcnManagementService Binder interface.
*/
@@ -698,7 +794,8 @@ public class VcnManagementService extends IVcnManagementService.Stub {
final List<ParcelUuid> result = new ArrayList<>();
synchronized (mLock) {
for (ParcelUuid subGrp : mConfigs.keySet()) {
- if (mLastSnapshot.packageHasPermissionsForSubscriptionGroup(subGrp, opPkgName)) {
+ if (mLastSnapshot.packageHasPermissionsForSubscriptionGroup(subGrp, opPkgName)
+ || isProvisioningPackageForConfig(subGrp, opPkgName)) {
result.add(subGrp);
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java b/services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java
new file mode 100644
index 000000000000..1b24aa896652
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors;
+
+import static android.hardware.biometrics.BiometricStateListener.STATE_AUTH_OTHER;
+import static android.hardware.biometrics.BiometricStateListener.STATE_BP_AUTH;
+import static android.hardware.biometrics.BiometricStateListener.STATE_ENROLLING;
+import static android.hardware.biometrics.BiometricStateListener.STATE_IDLE;
+import static android.hardware.biometrics.BiometricStateListener.STATE_KEYGUARD_AUTH;
+
+import android.annotation.NonNull;
+import android.hardware.biometrics.BiometricStateListener;
+import android.hardware.biometrics.IBiometricStateListener;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.server.biometrics.Utils;
+
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * A callback for receiving notifications about biometric sensor state changes.
+ */
+public class BiometricStateCallback implements ClientMonitorCallback {
+
+ private static final String TAG = "BiometricStateCallback";
+
+ @NonNull
+ private final CopyOnWriteArrayList<IBiometricStateListener>
+ mBiometricStateListeners = new CopyOnWriteArrayList<>();
+
+ private @BiometricStateListener.State int mBiometricState;
+
+ public BiometricStateCallback() {
+ mBiometricState = STATE_IDLE;
+ }
+
+ public int getBiometricState() {
+ return mBiometricState;
+ }
+
+ @Override
+ public void onClientStarted(@NonNull BaseClientMonitor client) {
+ final int previousBiometricState = mBiometricState;
+
+ if (client instanceof AuthenticationClient) {
+ final AuthenticationClient<?> authClient = (AuthenticationClient<?>) client;
+ if (authClient.isKeyguard()) {
+ mBiometricState = STATE_KEYGUARD_AUTH;
+ } else if (authClient.isBiometricPrompt()) {
+ mBiometricState = STATE_BP_AUTH;
+ } else {
+ mBiometricState = STATE_AUTH_OTHER;
+ }
+ } else if (client instanceof EnrollClient) {
+ mBiometricState = STATE_ENROLLING;
+ } else {
+ Slog.w(TAG, "Other authentication client: " + Utils.getClientName(client));
+ mBiometricState = STATE_IDLE;
+ }
+
+ Slog.d(TAG, "State updated from " + previousBiometricState + " to " + mBiometricState
+ + ", client " + client);
+ notifyBiometricStateListeners(mBiometricState);
+ }
+
+ @Override
+ public void onClientFinished(@NonNull BaseClientMonitor client, boolean success) {
+ mBiometricState = STATE_IDLE;
+ Slog.d(TAG, "Client finished, state updated to " + mBiometricState + ", client "
+ + client);
+
+ if (client instanceof EnrollmentModifier) {
+ EnrollmentModifier enrollmentModifier = (EnrollmentModifier) client;
+ final boolean enrollmentStateChanged = enrollmentModifier.hasEnrollmentStateChanged();
+ Slog.d(TAG, "Enrollment state changed: " + enrollmentStateChanged);
+ if (enrollmentStateChanged) {
+ notifyAllEnrollmentStateChanged(client.getTargetUserId(),
+ client.getSensorId(),
+ enrollmentModifier.hasEnrollments());
+ }
+ }
+
+ notifyBiometricStateListeners(mBiometricState);
+ }
+
+ private void notifyBiometricStateListeners(@BiometricStateListener.State int newState) {
+ for (IBiometricStateListener listener : mBiometricStateListeners) {
+ try {
+ listener.onStateChanged(newState);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception in biometric state change", e);
+ }
+ }
+ }
+
+ /**
+ * This should be invoked when:
+ * 1) Enrolled --> None-enrolled
+ * 2) None-enrolled --> enrolled
+ * 3) HAL becomes ready
+ * 4) Listener is registered
+ */
+ public void notifyAllEnrollmentStateChanged(int userId, int sensorId,
+ boolean hasEnrollments) {
+ for (IBiometricStateListener listener : mBiometricStateListeners) {
+ notifyEnrollmentStateChanged(listener, userId, sensorId, hasEnrollments);
+ }
+ }
+
+ /**
+ * Notifies the listener of enrollment state changes.
+ */
+ public void notifyEnrollmentStateChanged(@NonNull IBiometricStateListener listener,
+ int userId, int sensorId, boolean hasEnrollments) {
+ try {
+ listener.onEnrollmentsChanged(userId, sensorId, hasEnrollments);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote exception", e);
+ }
+ }
+
+ /**
+ * Enables clients to register a BiometricStateListener. For example, this is used to forward
+ * fingerprint sensor state changes to SideFpsEventHandler.
+ *
+ * @param listener
+ */
+ public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) {
+ mBiometricStateListeners.add(listener);
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index 5727ffc468df..97efc7813230 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -42,6 +42,7 @@ import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.IBiometricSensorReceiver;
import android.hardware.biometrics.IBiometricService;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
+import android.hardware.biometrics.IBiometricStateListener;
import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
import android.hardware.biometrics.ITestSessionCallback;
@@ -55,7 +56,6 @@ import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback
import android.hardware.fingerprint.IFingerprintClientActiveCallback;
import android.hardware.fingerprint.IFingerprintService;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
-import android.hardware.fingerprint.IFingerprintStateListener;
import android.hardware.fingerprint.ISidefpsController;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.Binder;
@@ -84,6 +84,7 @@ import com.android.server.ServiceThread;
import com.android.server.SystemService;
import com.android.server.biometrics.Utils;
import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.sensors.BiometricStateCallback;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.LockoutTracker;
@@ -114,7 +115,7 @@ public class FingerprintService extends SystemService {
private final LockPatternUtils mLockPatternUtils;
private final FingerprintServiceWrapper mServiceWrapper;
@NonNull private final List<ServiceProvider> mServiceProviders;
- @NonNull private final FingerprintStateCallback mFingerprintStateCallback;
+ @NonNull private final BiometricStateCallback mBiometricStateCallback;
@NonNull private final Handler mHandler;
@GuardedBy("mLock")
@@ -125,20 +126,20 @@ public class FingerprintService extends SystemService {
@NonNull private final List<FingerprintSensorPropertiesInternal> mSensorProps;
/**
- * Registers FingerprintStateListener in list stored by FingerprintService
- * @param listener new FingerprintStateListener being added
+ * Registers BiometricStateListener in list stored by FingerprintService
+ * @param listener new BiometricStateListener being added
*/
- public void registerFingerprintStateListener(@NonNull IFingerprintStateListener listener) {
- mFingerprintStateCallback.registerFingerprintStateListener(listener);
+ public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) {
+ mBiometricStateCallback.registerBiometricStateListener(listener);
broadcastCurrentEnrollmentState(listener);
}
/**
* @param listener if non-null, notifies only this listener. if null, notifies all listeners
- * in {@link FingerprintStateCallback}. This is slightly ugly, but reduces
+ * in {@link BiometricStateCallback}. This is slightly ugly, but reduces
* redundant code.
*/
- private void broadcastCurrentEnrollmentState(@Nullable IFingerprintStateListener listener) {
+ private void broadcastCurrentEnrollmentState(@Nullable IBiometricStateListener listener) {
final UserManager um = UserManager.get(getContext());
synchronized (mLock) {
// Update the new listener with current state of all sensors
@@ -151,10 +152,10 @@ public class FingerprintService extends SystemService {
// Defer this work and allow the loop to release the lock sooner
mHandler.post(() -> {
if (listener != null) {
- mFingerprintStateCallback.notifyFingerprintEnrollmentStateChanged(
+ mBiometricStateCallback.notifyEnrollmentStateChanged(
listener, userInfo.id, prop.sensorId, enrolled);
} else {
- mFingerprintStateCallback.notifyAllFingerprintEnrollmentStateChanged(
+ mBiometricStateCallback.notifyAllEnrollmentStateChanged(
userInfo.id, prop.sensorId, enrolled);
}
});
@@ -651,7 +652,7 @@ public class FingerprintService extends SystemService {
pw.println("Dumping for sensorId: " + props.sensorId
+ ", provider: " + provider.getClass().getSimpleName());
pw.println("Fps state: "
- + mFingerprintStateCallback.getFingerprintState());
+ + mBiometricStateCallback.getBiometricState());
provider.dumpInternal(props.sensorId, pw);
pw.println();
}
@@ -847,12 +848,12 @@ public class FingerprintService extends SystemService {
Fingerprint21UdfpsMock.CONFIG_ENABLE_TEST_UDFPS, 0 /* default */,
UserHandle.USER_CURRENT) != 0) {
fingerprint21 = Fingerprint21UdfpsMock.newInstance(getContext(),
- mFingerprintStateCallback, hidlSensor,
+ mBiometricStateCallback, hidlSensor,
mLockoutResetDispatcher, mGestureAvailabilityDispatcher,
BiometricContext.getInstance(getContext()));
} else {
fingerprint21 = Fingerprint21.newInstance(getContext(),
- mFingerprintStateCallback, hidlSensor, mHandler,
+ mBiometricStateCallback, hidlSensor, mHandler,
mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
}
mServiceProviders.add(fingerprint21);
@@ -875,7 +876,7 @@ public class FingerprintService extends SystemService {
try {
final SensorProps[] props = fp.getSensorProps();
final FingerprintProvider provider =
- new FingerprintProvider(getContext(), mFingerprintStateCallback, props,
+ new FingerprintProvider(getContext(), mBiometricStateCallback, props,
instance, mLockoutResetDispatcher,
mGestureAvailabilityDispatcher,
BiometricContext.getInstance(getContext()));
@@ -1015,8 +1016,8 @@ public class FingerprintService extends SystemService {
}
@Override
- public void registerFingerprintStateListener(@NonNull IFingerprintStateListener listener) {
- FingerprintService.this.registerFingerprintStateListener(listener);
+ public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) {
+ FingerprintService.this.registerBiometricStateListener(listener);
}
}
@@ -1028,7 +1029,7 @@ public class FingerprintService extends SystemService {
mLockoutResetDispatcher = new LockoutResetDispatcher(context);
mLockPatternUtils = new LockPatternUtils(context);
mServiceProviders = new ArrayList<>();
- mFingerprintStateCallback = new FingerprintStateCallback();
+ mBiometricStateCallback = new BiometricStateCallback();
mAuthenticatorsRegisteredCallbacks = new RemoteCallbackList<>();
mSensorProps = new ArrayList<>();
mHandler = new Handler(Looper.getMainLooper());
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java
deleted file mode 100644
index 04fd534adb3b..000000000000
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.biometrics.sensors.fingerprint;
-
-import static android.hardware.fingerprint.FingerprintStateListener.STATE_AUTH_OTHER;
-import static android.hardware.fingerprint.FingerprintStateListener.STATE_BP_AUTH;
-import static android.hardware.fingerprint.FingerprintStateListener.STATE_ENROLLING;
-import static android.hardware.fingerprint.FingerprintStateListener.STATE_IDLE;
-import static android.hardware.fingerprint.FingerprintStateListener.STATE_KEYGUARD_AUTH;
-
-import android.annotation.NonNull;
-import android.hardware.fingerprint.FingerprintStateListener;
-import android.hardware.fingerprint.IFingerprintStateListener;
-import android.os.RemoteException;
-import android.util.Slog;
-
-import com.android.server.biometrics.Utils;
-import com.android.server.biometrics.sensors.AuthenticationClient;
-import com.android.server.biometrics.sensors.BaseClientMonitor;
-import com.android.server.biometrics.sensors.ClientMonitorCallback;
-import com.android.server.biometrics.sensors.EnrollClient;
-import com.android.server.biometrics.sensors.EnrollmentModifier;
-
-import java.util.concurrent.CopyOnWriteArrayList;
-
-/**
- * A callback for receiving notifications about changes in fingerprint state.
- */
-public class FingerprintStateCallback implements ClientMonitorCallback {
-
- @NonNull private final CopyOnWriteArrayList<IFingerprintStateListener>
- mFingerprintStateListeners = new CopyOnWriteArrayList<>();
-
- private @FingerprintStateListener.State int mFingerprintState;
-
- public FingerprintStateCallback() {
- mFingerprintState = STATE_IDLE;
- }
-
- public int getFingerprintState() {
- return mFingerprintState;
- }
-
- @Override
- public void onClientStarted(@NonNull BaseClientMonitor client) {
- final int previousFingerprintState = mFingerprintState;
-
- if (client instanceof AuthenticationClient) {
- final AuthenticationClient<?> authClient = (AuthenticationClient<?>) client;
- if (authClient.isKeyguard()) {
- mFingerprintState = STATE_KEYGUARD_AUTH;
- } else if (authClient.isBiometricPrompt()) {
- mFingerprintState = STATE_BP_AUTH;
- } else {
- mFingerprintState = STATE_AUTH_OTHER;
- }
- } else if (client instanceof EnrollClient) {
- mFingerprintState = STATE_ENROLLING;
- } else {
- Slog.w(FingerprintService.TAG,
- "Other authentication client: " + Utils.getClientName(client));
- mFingerprintState = STATE_IDLE;
- }
-
- Slog.d(FingerprintService.TAG, "Fps state updated from " + previousFingerprintState
- + " to " + mFingerprintState + ", client " + client);
- notifyFingerprintStateListeners(mFingerprintState);
- }
-
- @Override
- public void onClientFinished(@NonNull BaseClientMonitor client, boolean success) {
- mFingerprintState = STATE_IDLE;
- Slog.d(FingerprintService.TAG,
- "Client finished, fps state updated to " + mFingerprintState + ", client "
- + client);
-
- if (client instanceof EnrollmentModifier) {
- EnrollmentModifier enrollmentModifier = (EnrollmentModifier) client;
- final boolean enrollmentStateChanged = enrollmentModifier.hasEnrollmentStateChanged();
- Slog.d(FingerprintService.TAG, "Enrollment state changed: " + enrollmentStateChanged);
- if (enrollmentStateChanged) {
- notifyAllFingerprintEnrollmentStateChanged(client.getTargetUserId(),
- client.getSensorId(),
- enrollmentModifier.hasEnrollments());
- }
- }
-
- notifyFingerprintStateListeners(mFingerprintState);
- }
-
- private void notifyFingerprintStateListeners(@FingerprintStateListener.State int newState) {
- for (IFingerprintStateListener listener : mFingerprintStateListeners) {
- try {
- listener.onStateChanged(newState);
- } catch (RemoteException e) {
- Slog.e(FingerprintService.TAG, "Remote exception in fingerprint state change", e);
- }
- }
- }
-
- /**
- * This should be invoked when:
- * 1) Enrolled --> None-enrolled
- * 2) None-enrolled --> enrolled
- * 3) HAL becomes ready
- * 4) Listener is registered
- */
- void notifyAllFingerprintEnrollmentStateChanged(int userId, int sensorId,
- boolean hasEnrollments) {
- for (IFingerprintStateListener listener : mFingerprintStateListeners) {
- notifyFingerprintEnrollmentStateChanged(listener, userId, sensorId, hasEnrollments);
- }
- }
-
- /**
- * Notifies the listener of enrollment state changes.
- */
- void notifyFingerprintEnrollmentStateChanged(@NonNull IFingerprintStateListener listener,
- int userId, int sensorId, boolean hasEnrollments) {
- try {
- listener.onEnrollmentsChanged(userId, sensorId, hasEnrollments);
- } catch (RemoteException e) {
- Slog.e(FingerprintService.TAG, "Remote exception", e);
- }
- }
-
- /**
- * Enables clients to register a FingerprintStateListener. Used by FingerprintService to forward
- * updates in fingerprint sensor state to the SideFpNsEventHandler
- *
- * @param listener
- */
- public void registerFingerprintStateListener(@NonNull IFingerprintStateListener listener) {
- mFingerprintStateListeners.add(listener);
- }
-}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java
index 0528cd489ae5..ba7202fec93b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/BiometricTestSessionImpl.java
@@ -32,8 +32,8 @@ import android.util.Slog;
import com.android.server.biometrics.HardwareAuthTokenUtils;
import com.android.server.biometrics.Utils;
import com.android.server.biometrics.sensors.BaseClientMonitor;
+import com.android.server.biometrics.sensors.BiometricStateCallback;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
-import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback;
import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
import java.util.HashSet;
@@ -52,7 +52,7 @@ class BiometricTestSessionImpl extends ITestSession.Stub {
@NonNull private final Context mContext;
private final int mSensorId;
@NonNull private final ITestSessionCallback mCallback;
- @NonNull private final FingerprintStateCallback mFingerprintStateCallback;
+ @NonNull private final BiometricStateCallback mBiometricStateCallback;
@NonNull private final FingerprintProvider mProvider;
@NonNull private final Sensor mSensor;
@NonNull private final Set<Integer> mEnrollmentIds;
@@ -118,13 +118,13 @@ class BiometricTestSessionImpl extends ITestSession.Stub {
BiometricTestSessionImpl(@NonNull Context context, int sensorId,
@NonNull ITestSessionCallback callback,
- @NonNull FingerprintStateCallback fingerprintStateCallback,
+ @NonNull BiometricStateCallback biometricStateCallback,
@NonNull FingerprintProvider provider,
@NonNull Sensor sensor) {
mContext = context;
mSensorId = sensorId;
mCallback = callback;
- mFingerprintStateCallback = fingerprintStateCallback;
+ mBiometricStateCallback = biometricStateCallback;
mProvider = provider;
mSensor = sensor;
mEnrollmentIds = new HashSet<>();
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 1fac8a8ce5c9..7d5b77c2d711 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
@@ -58,13 +58,13 @@ import com.android.server.biometrics.log.BiometricContext;
import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.AuthenticationClient;
import com.android.server.biometrics.sensors.BaseClientMonitor;
+import com.android.server.biometrics.sensors.BiometricStateCallback;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback;
import com.android.server.biometrics.sensors.InvalidationRequesterClient;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.PerformanceTracker;
-import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback;
import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
import com.android.server.biometrics.sensors.fingerprint.ServiceProvider;
@@ -91,7 +91,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
private boolean mTestHalEnabled;
@NonNull private final Context mContext;
- @NonNull private final FingerprintStateCallback mFingerprintStateCallback;
+ @NonNull private final BiometricStateCallback mBiometricStateCallback;
@NonNull private final String mHalInstanceName;
@NonNull @VisibleForTesting
final SparseArray<Sensor> mSensors; // Map of sensors that this HAL supports
@@ -141,13 +141,13 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
}
public FingerprintProvider(@NonNull Context context,
- @NonNull FingerprintStateCallback fingerprintStateCallback,
+ @NonNull BiometricStateCallback biometricStateCallback,
@NonNull SensorProps[] props, @NonNull String halInstanceName,
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
@NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
@NonNull BiometricContext biometricContext) {
mContext = context;
- mFingerprintStateCallback = fingerprintStateCallback;
+ mBiometricStateCallback = biometricStateCallback;
mHalInstanceName = halInstanceName;
mSensors = new SparseArray<>();
mHandler = new Handler(Looper.getMainLooper());
@@ -389,13 +389,13 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
@Override
public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
- mFingerprintStateCallback.onClientStarted(clientMonitor);
+ mBiometricStateCallback.onClientStarted(clientMonitor);
}
@Override
public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
boolean success) {
- mFingerprintStateCallback.onClientFinished(clientMonitor, success);
+ mBiometricStateCallback.onClientFinished(clientMonitor, success);
if (success) {
scheduleLoadAuthenticatorIdsForUser(sensorId, userId);
scheduleInvalidationRequest(sensorId, userId);
@@ -425,7 +425,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
mBiometricContext,
mUdfpsOverlayController, isStrongBiometric);
- scheduleForSensor(sensorId, client, mFingerprintStateCallback);
+ scheduleForSensor(sensorId, client, mBiometricStateCallback);
});
return id;
@@ -447,7 +447,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
mTaskStackListener, mSensors.get(sensorId).getLockoutCache(),
mUdfpsOverlayController, mSidefpsController, allowBackgroundAuthentication,
mSensors.get(sensorId).getSensorProperties());
- scheduleForSensor(sensorId, client, mFingerprintStateCallback);
+ scheduleForSensor(sensorId, client, mBiometricStateCallback);
});
}
@@ -509,7 +509,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
BiometricsProtoEnums.CLIENT_UNKNOWN),
mBiometricContext,
mSensors.get(sensorId).getAuthenticatorIds());
- scheduleForSensor(sensorId, client, mFingerprintStateCallback);
+ scheduleForSensor(sensorId, client, mBiometricStateCallback);
});
}
@@ -528,7 +528,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
enrolledList, FingerprintUtils.getInstance(sensorId),
mSensors.get(sensorId).getAuthenticatorIds());
scheduleForSensor(sensorId, client, new ClientMonitorCompositeCallback(callback,
- mFingerprintStateCallback));
+ mBiometricStateCallback));
});
}
@@ -680,7 +680,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
@Override
public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
@NonNull String opPackageName) {
- return mSensors.get(sensorId).createTestSession(callback, mFingerprintStateCallback);
+ return mSensors.get(sensorId).createTestSession(callback, mBiometricStateCallback);
}
@Override
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 024d611732c1..1dcf4e9528d2 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
@@ -55,6 +55,7 @@ import com.android.server.biometrics.sensors.AcquisitionClient;
import com.android.server.biometrics.sensors.AuthenticationConsumer;
import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.BiometricScheduler;
+import com.android.server.biometrics.sensors.BiometricStateCallback;
import com.android.server.biometrics.sensors.EnumerateConsumer;
import com.android.server.biometrics.sensors.ErrorConsumer;
import com.android.server.biometrics.sensors.LockoutCache;
@@ -64,7 +65,6 @@ import com.android.server.biometrics.sensors.RemovalConsumer;
import com.android.server.biometrics.sensors.StartUserClient;
import com.android.server.biometrics.sensors.StopUserClient;
import com.android.server.biometrics.sensors.UserAwareBiometricScheduler;
-import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback;
import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
@@ -527,9 +527,9 @@ public class Sensor {
}
@NonNull ITestSession createTestSession(@NonNull ITestSessionCallback callback,
- @NonNull FingerprintStateCallback fingerprintStateCallback) {
+ @NonNull BiometricStateCallback biometricStateCallback) {
return new BiometricTestSessionImpl(mContext, mSensorProperties.sensorId, callback,
- fingerprintStateCallback, mProvider, this);
+ biometricStateCallback, mProvider, this);
}
@NonNull BiometricScheduler getScheduler() {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java
index 033855f822a4..a58bb8981cf6 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/BiometricTestSessionImpl.java
@@ -31,8 +31,8 @@ import android.util.Slog;
import com.android.server.biometrics.Utils;
import com.android.server.biometrics.sensors.BaseClientMonitor;
+import com.android.server.biometrics.sensors.BiometricStateCallback;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
-import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback;
import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
import java.util.ArrayList;
@@ -53,7 +53,7 @@ public class BiometricTestSessionImpl extends ITestSession.Stub {
@NonNull private final Context mContext;
private final int mSensorId;
@NonNull private final ITestSessionCallback mCallback;
- @NonNull private final FingerprintStateCallback mFingerprintStateCallback;
+ @NonNull private final BiometricStateCallback mBiometricStateCallback;
@NonNull private final Fingerprint21 mFingerprint21;
@NonNull private final Fingerprint21.HalResultController mHalResultController;
@NonNull private final Set<Integer> mEnrollmentIds;
@@ -119,14 +119,14 @@ public class BiometricTestSessionImpl extends ITestSession.Stub {
BiometricTestSessionImpl(@NonNull Context context, int sensorId,
@NonNull ITestSessionCallback callback,
- @NonNull FingerprintStateCallback fingerprintStateCallback,
+ @NonNull BiometricStateCallback biometricStateCallback,
@NonNull Fingerprint21 fingerprint21,
@NonNull Fingerprint21.HalResultController halResultController) {
mContext = context;
mSensorId = sensorId;
mCallback = callback;
mFingerprint21 = fingerprint21;
- mFingerprintStateCallback = fingerprintStateCallback;
+ mBiometricStateCallback = biometricStateCallback;
mHalResultController = halResultController;
mEnrollmentIds = new HashSet<>();
mRandom = new Random();
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
index 1d2a3655021c..52dbe2460e1c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
@@ -64,6 +64,7 @@ import com.android.server.biometrics.sensors.AuthenticationClient;
import com.android.server.biometrics.sensors.AuthenticationConsumer;
import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.BiometricScheduler;
+import com.android.server.biometrics.sensors.BiometricStateCallback;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback;
@@ -73,7 +74,6 @@ import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.LockoutTracker;
import com.android.server.biometrics.sensors.PerformanceTracker;
import com.android.server.biometrics.sensors.RemovalConsumer;
-import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback;
import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
import com.android.server.biometrics.sensors.fingerprint.ServiceProvider;
@@ -105,7 +105,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
private boolean mTestHalEnabled;
final Context mContext;
- @NonNull private final FingerprintStateCallback mFingerprintStateCallback;
+ @NonNull private final BiometricStateCallback mBiometricStateCallback;
private final ActivityTaskManager mActivityTaskManager;
@NonNull private final FingerprintSensorPropertiesInternal mSensorProperties;
private final BiometricScheduler mScheduler;
@@ -323,7 +323,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
@VisibleForTesting
Fingerprint21(@NonNull Context context,
- @NonNull FingerprintStateCallback fingerprintStateCallback,
+ @NonNull BiometricStateCallback biometricStateCallback,
@NonNull FingerprintSensorPropertiesInternal sensorProps,
@NonNull BiometricScheduler scheduler,
@NonNull Handler handler,
@@ -331,7 +331,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
@NonNull HalResultController controller,
@NonNull BiometricContext biometricContext) {
mContext = context;
- mFingerprintStateCallback = fingerprintStateCallback;
+ mBiometricStateCallback = biometricStateCallback;
mBiometricContext = biometricContext;
mSensorProperties = sensorProps;
@@ -362,7 +362,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
}
public static Fingerprint21 newInstance(@NonNull Context context,
- @NonNull FingerprintStateCallback fingerprintStateCallback,
+ @NonNull BiometricStateCallback biometricStateCallback,
@NonNull FingerprintSensorPropertiesInternal sensorProps,
@NonNull Handler handler,
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
@@ -373,7 +373,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
gestureAvailabilityDispatcher);
final HalResultController controller = new HalResultController(sensorProps.sensorId,
context, handler, scheduler);
- return new Fingerprint21(context, fingerprintStateCallback, sensorProps, scheduler, handler,
+ return new Fingerprint21(context, biometricStateCallback, sensorProps, scheduler, handler,
lockoutResetDispatcher, controller, BiometricContext.getInstance(context));
}
@@ -604,13 +604,13 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() {
@Override
public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
- mFingerprintStateCallback.onClientStarted(clientMonitor);
+ mBiometricStateCallback.onClientStarted(clientMonitor);
}
@Override
public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
boolean success) {
- mFingerprintStateCallback.onClientFinished(clientMonitor, success);
+ mBiometricStateCallback.onClientFinished(clientMonitor, success);
if (success) {
// Update authenticatorIds
scheduleUpdateActiveUserWithoutHandler(clientMonitor.getTargetUserId(),
@@ -642,7 +642,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
mBiometricContext, mUdfpsOverlayController,
isStrongBiometric);
- mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback);
+ mScheduler.scheduleClientMonitor(client, mBiometricStateCallback);
});
return id;
@@ -666,7 +666,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
mTaskStackListener, mLockoutTracker,
mUdfpsOverlayController, mSidefpsController,
allowBackgroundAuthentication, mSensorProperties);
- mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback);
+ mScheduler.scheduleClientMonitor(client, mBiometricStateCallback);
});
}
@@ -708,7 +708,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
createLogger(BiometricsProtoEnums.ACTION_REMOVE,
BiometricsProtoEnums.CLIENT_UNKNOWN),
mBiometricContext, mAuthenticatorIds);
- mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback);
+ mScheduler.scheduleClientMonitor(client, mBiometricStateCallback);
});
}
@@ -728,7 +728,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
createLogger(BiometricsProtoEnums.ACTION_REMOVE,
BiometricsProtoEnums.CLIENT_UNKNOWN),
mBiometricContext, mAuthenticatorIds);
- mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback);
+ mScheduler.scheduleClientMonitor(client, mBiometricStateCallback);
});
}
@@ -754,7 +754,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
public void scheduleInternalCleanup(int sensorId, int userId,
@Nullable ClientMonitorCallback callback) {
scheduleInternalCleanup(userId, new ClientMonitorCompositeCallback(callback,
- mFingerprintStateCallback));
+ mBiometricStateCallback));
}
private BiometricLogger createLogger(int statsAction, int statsClient) {
@@ -967,6 +967,6 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
@NonNull String opPackageName) {
return new BiometricTestSessionImpl(mContext, mSensorProperties.sensorId, callback,
- mFingerprintStateCallback, this, mHalResultController);
+ mBiometricStateCallback, this, mHalResultController);
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
index a4e343e786c1..485a674dda92 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java
@@ -41,9 +41,9 @@ import com.android.server.biometrics.log.BiometricContext;
import com.android.server.biometrics.sensors.AuthenticationConsumer;
import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.BiometricScheduler;
+import com.android.server.biometrics.sensors.BiometricStateCallback;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
-import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback;
import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
import java.util.ArrayList;
@@ -245,7 +245,7 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
}
public static Fingerprint21UdfpsMock newInstance(@NonNull Context context,
- @NonNull FingerprintStateCallback fingerprintStateCallback,
+ @NonNull BiometricStateCallback biometricStateCallback,
@NonNull FingerprintSensorPropertiesInternal sensorProps,
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
@NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
@@ -257,7 +257,7 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
new TestableBiometricScheduler(TAG, handler, gestureAvailabilityDispatcher);
final MockHalResultController controller =
new MockHalResultController(sensorProps.sensorId, context, handler, scheduler);
- return new Fingerprint21UdfpsMock(context, fingerprintStateCallback, sensorProps, scheduler,
+ return new Fingerprint21UdfpsMock(context, biometricStateCallback, sensorProps, scheduler,
handler, lockoutResetDispatcher, controller, biometricContext);
}
@@ -382,14 +382,14 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
}
private Fingerprint21UdfpsMock(@NonNull Context context,
- @NonNull FingerprintStateCallback fingerprintStateCallback,
+ @NonNull BiometricStateCallback biometricStateCallback,
@NonNull FingerprintSensorPropertiesInternal sensorProps,
@NonNull TestableBiometricScheduler scheduler,
@NonNull Handler handler,
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
@NonNull MockHalResultController controller,
@NonNull BiometricContext biometricContext) {
- super(context, fingerprintStateCallback, sensorProps, scheduler, handler,
+ super(context, biometricStateCallback, sensorProps, scheduler, handler,
lockoutResetDispatcher, controller, biometricContext);
mScheduler = scheduler;
mScheduler.init(this);
diff --git a/services/core/java/com/android/server/location/gnss/hal/GnssNative.java b/services/core/java/com/android/server/location/gnss/hal/GnssNative.java
index af87677ecb66..1fa56bc3e055 100644
--- a/services/core/java/com/android/server/location/gnss/hal/GnssNative.java
+++ b/services/core/java/com/android/server/location/gnss/hal/GnssNative.java
@@ -47,6 +47,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.List;
import java.util.Objects;
+import java.util.concurrent.TimeUnit;
/**
* Entry point for most GNSS HAL commands and callbacks.
@@ -1271,7 +1272,8 @@ public class GnssNative {
@NativeEntryPoint
boolean isInEmergencySession() {
return Binder.withCleanCallingIdentity(
- () -> mEmergencyHelper.isInEmergency(mConfiguration.getEsExtensionSec()));
+ () -> mEmergencyHelper.isInEmergency(
+ TimeUnit.SECONDS.toMillis(mConfiguration.getEsExtensionSec())));
}
/**
diff --git a/services/core/java/com/android/server/policy/SideFpsEventHandler.java b/services/core/java/com/android/server/policy/SideFpsEventHandler.java
index f36869859170..41d02727d9eb 100644
--- a/services/core/java/com/android/server/policy/SideFpsEventHandler.java
+++ b/services/core/java/com/android/server/policy/SideFpsEventHandler.java
@@ -16,9 +16,9 @@
package com.android.server.policy;
-import static android.hardware.fingerprint.FingerprintStateListener.STATE_BP_AUTH;
-import static android.hardware.fingerprint.FingerprintStateListener.STATE_ENROLLING;
-import static android.hardware.fingerprint.FingerprintStateListener.STATE_IDLE;
+import static android.hardware.biometrics.BiometricStateListener.STATE_BP_AUTH;
+import static android.hardware.biometrics.BiometricStateListener.STATE_ENROLLING;
+import static android.hardware.biometrics.BiometricStateListener.STATE_IDLE;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -30,9 +30,9 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
+import android.hardware.biometrics.BiometricStateListener;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.hardware.fingerprint.FingerprintStateListener;
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
import android.os.Handler;
import android.os.PowerManager;
@@ -67,7 +67,7 @@ public class SideFpsEventHandler {
}
};
- private @FingerprintStateListener.State int mFingerprintState;
+ private @BiometricStateListener.State int mBiometricState;
SideFpsEventHandler(Context context, Handler handler, PowerManager powerManager) {
this(context, handler, powerManager, () -> new AlertDialog.Builder(context));
@@ -80,7 +80,7 @@ public class SideFpsEventHandler {
mHandler = handler;
mPowerManager = powerManager;
mDialogSupplier = dialogSupplier;
- mFingerprintState = STATE_IDLE;
+ mBiometricState = STATE_IDLE;
mSideFpsEventHandlerReady = new AtomicBoolean(false);
// ensure dialog is dismissed if screen goes off for unrelated reasons
@@ -108,7 +108,7 @@ public class SideFpsEventHandler {
return false;
}
- switch (mFingerprintState) {
+ switch (mBiometricState) {
case STATE_ENROLLING:
case STATE_BP_AUTH:
mHandler.post(() -> {
@@ -116,7 +116,7 @@ public class SideFpsEventHandler {
mDialog.dismiss();
}
mDialog = showConfirmDialog(mDialogSupplier.get(),
- mPowerManager, eventTime, mFingerprintState, mDialogDismissListener);
+ mPowerManager, eventTime, mBiometricState, mDialogDismissListener);
});
return true;
default:
@@ -127,9 +127,9 @@ public class SideFpsEventHandler {
@NonNull
private static Dialog showConfirmDialog(@NonNull AlertDialog.Builder dialogBuilder,
@NonNull PowerManager powerManager, long eventTime,
- @FingerprintStateListener.State int fingerprintState,
+ @BiometricStateListener.State int biometricState,
@NonNull DialogInterface.OnDismissListener dismissListener) {
- final boolean enrolling = fingerprintState == STATE_ENROLLING;
+ final boolean enrolling = biometricState == STATE_ENROLLING;
final int title = enrolling ? R.string.fp_power_button_enrollment_title
: R.string.fp_power_button_bp_title;
final int message = enrolling ? R.string.fp_power_button_enrollment_message
@@ -165,8 +165,8 @@ public class SideFpsEventHandler {
/**
* Awaits notification from PhoneWindowManager that fingerprint service is ready
* to send updates about power button fps sensor state. Then configures a
- * FingerprintStateListener to receive and record updates to fps state, and
- * registers the FingerprintStateListener in FingerprintManager.
+ * BiometricStateListener to receive and record updates to fps state, and
+ * registers the BiometricStateListener in FingerprintManager.
*/
public void onFingerprintSensorReady() {
final PackageManager pm = mContext.getPackageManager();
@@ -182,13 +182,14 @@ public class SideFpsEventHandler {
public void onAllAuthenticatorsRegistered(
List<FingerprintSensorPropertiesInternal> sensors) {
if (fingerprintManager.isPowerbuttonFps()) {
- fingerprintManager.registerFingerprintStateListener(
- new FingerprintStateListener() {
- @Nullable private Runnable mStateRunnable = null;
+ fingerprintManager.registerBiometricStateListener(
+ new BiometricStateListener() {
+ @Nullable
+ private Runnable mStateRunnable = null;
@Override
public void onStateChanged(
- @FingerprintStateListener.State int newState) {
+ @BiometricStateListener.State int newState) {
if (mStateRunnable != null) {
mHandler.removeCallbacks(mStateRunnable);
mStateRunnable = null;
@@ -198,11 +199,11 @@ public class SideFpsEventHandler {
// arrive in any order (success auth & power). Add a
// damper when moving to idle in case auth is first
if (newState == STATE_IDLE) {
- mStateRunnable = () -> mFingerprintState = newState;
+ mStateRunnable = () -> mBiometricState = newState;
mHandler.postDelayed(mStateRunnable,
DEBOUNCE_DELAY_MILLIS);
} else {
- mFingerprintState = newState;
+ mBiometricState = newState;
}
}
});
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallbackTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java
index 38e8dfa45262..5f88c99b1d1e 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallbackTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java
@@ -24,12 +24,13 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.hardware.fingerprint.FingerprintStateListener;
+import android.hardware.biometrics.BiometricStateListener;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
import com.android.server.biometrics.sensors.AuthenticationClient;
+import com.android.server.biometrics.sensors.BiometricStateCallback;
import com.android.server.biometrics.sensors.EnrollClient;
import org.junit.Before;
@@ -39,19 +40,19 @@ import org.mockito.MockitoAnnotations;
@Presubmit
@SmallTest
-public class FingerprintStateCallbackTest {
+public class BiometricStateCallbackTest {
- private FingerprintStateCallback mCallback;
+ private BiometricStateCallback mCallback;
@Mock
- FingerprintStateListener mFingerprintStateListener;
+ BiometricStateListener mBiometricStateListener;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- mCallback = new FingerprintStateCallback();
- mCallback.registerFingerprintStateListener(mFingerprintStateListener);
+ mCallback = new BiometricStateCallback();
+ mCallback.registerBiometricStateListener(mBiometricStateListener);
}
@Test
@@ -86,10 +87,10 @@ public class FingerprintStateCallbackTest {
mCallback.onClientFinished(client, true /* success */);
if (expectCallback) {
- verify(mFingerprintStateListener).onEnrollmentsChanged(eq(userId), eq(sensorId),
+ verify(mBiometricStateListener).onEnrollmentsChanged(eq(userId), eq(sensorId),
eq(expectedCallbackValue));
} else {
- verify(mFingerprintStateListener, never()).onEnrollmentsChanged(anyInt(), anyInt(),
+ verify(mBiometricStateListener, never()).onEnrollmentsChanged(anyInt(), anyInt(),
anyBoolean());
}
}
@@ -98,7 +99,7 @@ public class FingerprintStateCallbackTest {
public void testAuthentication_enrollmentCallbackNeverNotified() {
AuthenticationClient<?> client = mock(AuthenticationClient.class);
mCallback.onClientFinished(client, true /* success */);
- verify(mFingerprintStateListener, never()).onEnrollmentsChanged(anyInt(), anyInt(),
+ verify(mBiometricStateListener, never()).onEnrollmentsChanged(anyInt(), anyInt(),
anyBoolean());
}
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java
index 5a1a02eb39c8..c6ddf27f96b2 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProviderTest.java
@@ -42,9 +42,9 @@ import androidx.test.filters.SmallTest;
import com.android.server.biometrics.log.BiometricContext;
import com.android.server.biometrics.sensors.BiometricScheduler;
+import com.android.server.biometrics.sensors.BiometricStateCallback;
import com.android.server.biometrics.sensors.HalClientMonitor;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
-import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback;
import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;
import org.junit.Before;
@@ -71,7 +71,7 @@ public class FingerprintProviderTest {
@Mock
private GestureAvailabilityDispatcher mGestureAvailabilityDispatcher;
@Mock
- private FingerprintStateCallback mFingerprintStateCallback;
+ private BiometricStateCallback mBiometricStateCallback;
@Mock
private BiometricContext mBiometricContext;
@@ -107,7 +107,7 @@ public class FingerprintProviderTest {
mLockoutResetDispatcher = new LockoutResetDispatcher(mContext);
mFingerprintProvider = new TestableFingerprintProvider(mDaemon, mContext,
- mFingerprintStateCallback, mSensorProps, TAG, mLockoutResetDispatcher,
+ mBiometricStateCallback, mSensorProps, TAG, mLockoutResetDispatcher,
mGestureAvailabilityDispatcher, mBiometricContext);
}
@@ -156,13 +156,13 @@ public class FingerprintProviderTest {
TestableFingerprintProvider(@NonNull IFingerprint daemon,
@NonNull Context context,
- @NonNull FingerprintStateCallback fingerprintStateCallback,
+ @NonNull BiometricStateCallback biometricStateCallback,
@NonNull SensorProps[] props,
@NonNull String halInstanceName,
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
@NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher,
@NonNull BiometricContext biometricContext) {
- super(context, fingerprintStateCallback, props, halInstanceName, lockoutResetDispatcher,
+ super(context, biometricStateCallback, props, halInstanceName, lockoutResetDispatcher,
gestureAvailabilityDispatcher, biometricContext);
mDaemon = daemon;
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java
index 529f994f2773..b32b89aaefb0 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java
@@ -41,8 +41,8 @@ import androidx.test.filters.SmallTest;
import com.android.internal.R;
import com.android.server.biometrics.log.BiometricContext;
import com.android.server.biometrics.sensors.BiometricScheduler;
+import com.android.server.biometrics.sensors.BiometricStateCallback;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
-import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback;
import org.junit.Before;
import org.junit.Test;
@@ -70,7 +70,7 @@ public class Fingerprint21Test {
@Mock
private BiometricScheduler mScheduler;
@Mock
- private FingerprintStateCallback mFingerprintStateCallback;
+ private BiometricStateCallback mBiometricStateCallback;
@Mock
private BiometricContext mBiometricContext;
@@ -102,7 +102,7 @@ public class Fingerprint21Test {
componentInfo, FingerprintSensorProperties.TYPE_UNKNOWN,
resetLockoutRequiresHardwareAuthToken);
- mFingerprint21 = new TestableFingerprint21(mContext, mFingerprintStateCallback, sensorProps,
+ mFingerprint21 = new TestableFingerprint21(mContext, mBiometricStateCallback, sensorProps,
mScheduler, new Handler(Looper.getMainLooper()), mLockoutResetDispatcher,
mHalResultController, mBiometricContext);
}
@@ -125,13 +125,13 @@ public class Fingerprint21Test {
private static class TestableFingerprint21 extends Fingerprint21 {
TestableFingerprint21(@NonNull Context context,
- @NonNull FingerprintStateCallback fingerprintStateCallback,
+ @NonNull BiometricStateCallback biometricStateCallback,
@NonNull FingerprintSensorPropertiesInternal sensorProps,
@NonNull BiometricScheduler scheduler, @NonNull Handler handler,
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
@NonNull HalResultController controller,
@NonNull BiometricContext biometricContext) {
- super(context, fingerprintStateCallback, sensorProps, scheduler, handler,
+ super(context, biometricStateCallback, sensorProps, scheduler, handler,
lockoutResetDispatcher, controller, biometricContext);
}
diff --git a/services/tests/servicestests/src/com/android/server/policy/SideFpsEventHandlerTest.java b/services/tests/servicestests/src/com/android/server/policy/SideFpsEventHandlerTest.java
index 41c7e31147a5..371861f74871 100644
--- a/services/tests/servicestests/src/com/android/server/policy/SideFpsEventHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/policy/SideFpsEventHandlerTest.java
@@ -26,9 +26,9 @@ import static org.mockito.Mockito.when;
import android.app.AlertDialog;
import android.content.pm.PackageManager;
+import android.hardware.biometrics.BiometricStateListener;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.hardware.fingerprint.FingerprintStateListener;
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
import android.os.Handler;
import android.os.PowerManager;
@@ -61,11 +61,11 @@ import java.util.List;
public class SideFpsEventHandlerTest {
private static final List<Integer> sAllStates = List.of(
- FingerprintStateListener.STATE_IDLE,
- FingerprintStateListener.STATE_ENROLLING,
- FingerprintStateListener.STATE_KEYGUARD_AUTH,
- FingerprintStateListener.STATE_BP_AUTH,
- FingerprintStateListener.STATE_AUTH_OTHER);
+ BiometricStateListener.STATE_IDLE,
+ BiometricStateListener.STATE_ENROLLING,
+ BiometricStateListener.STATE_KEYGUARD_AUTH,
+ BiometricStateListener.STATE_BP_AUTH,
+ BiometricStateListener.STATE_AUTH_OTHER);
@Rule
public TestableContext mContext =
@@ -83,7 +83,7 @@ public class SideFpsEventHandlerTest {
private TestLooper mLooper = new TestLooper();
private SideFpsEventHandler mEventHandler;
- private FingerprintStateListener mFingerprintStateListener;
+ private BiometricStateListener mBiometricStateListener;
@Before
public void setup() {
@@ -116,7 +116,7 @@ public class SideFpsEventHandlerTest {
setupWithSensor(false /* hasSfps */, true /* initialized */);
for (int state : sAllStates) {
- setFingerprintState(state);
+ setBiometricState(state);
assertThat(mEventHandler.onSinglePressDetected(200L)).isFalse();
mLooper.dispatchAll();
@@ -129,7 +129,7 @@ public class SideFpsEventHandlerTest {
setupWithSensor(true /* hasSfps */, false /* initialized */);
for (int state : sAllStates) {
- setFingerprintState(state);
+ setBiometricState(state);
assertThat(mEventHandler.onSinglePressDetected(400L)).isFalse();
mLooper.dispatchAll();
@@ -141,10 +141,10 @@ public class SideFpsEventHandlerTest {
public void ignoresWhenIdleOrUnknown() throws Exception {
setupWithSensor(true /* hasSfps */, true /* initialized */);
- setFingerprintState(FingerprintStateListener.STATE_IDLE);
+ setBiometricState(BiometricStateListener.STATE_IDLE);
assertThat(mEventHandler.onSinglePressDetected(80000L)).isFalse();
- setFingerprintState(FingerprintStateListener.STATE_AUTH_OTHER);
+ setBiometricState(BiometricStateListener.STATE_AUTH_OTHER);
assertThat(mEventHandler.onSinglePressDetected(90000L)).isFalse();
mLooper.dispatchAll();
@@ -155,7 +155,7 @@ public class SideFpsEventHandlerTest {
public void ignoresOnKeyguard() throws Exception {
setupWithSensor(true /* hasSfps */, true /* initialized */);
- setFingerprintState(FingerprintStateListener.STATE_KEYGUARD_AUTH);
+ setBiometricState(BiometricStateListener.STATE_KEYGUARD_AUTH);
assertThat(mEventHandler.onSinglePressDetected(80000L)).isFalse();
mLooper.dispatchAll();
@@ -166,7 +166,7 @@ public class SideFpsEventHandlerTest {
public void promptsWhenBPisActive() throws Exception {
setupWithSensor(true /* hasSfps */, true /* initialized */);
- setFingerprintState(FingerprintStateListener.STATE_BP_AUTH);
+ setBiometricState(BiometricStateListener.STATE_BP_AUTH);
assertThat(mEventHandler.onSinglePressDetected(80000L)).isTrue();
mLooper.dispatchAll();
@@ -177,16 +177,16 @@ public class SideFpsEventHandlerTest {
public void promptsWhenEnrolling() throws Exception {
setupWithSensor(true /* hasSfps */, true /* initialized */);
- setFingerprintState(FingerprintStateListener.STATE_ENROLLING);
+ setBiometricState(BiometricStateListener.STATE_ENROLLING);
assertThat(mEventHandler.onSinglePressDetected(80000L)).isTrue();
mLooper.dispatchAll();
verify(mAlertDialog).show();
}
- private void setFingerprintState(@FingerprintStateListener.State int newState) {
- if (mFingerprintStateListener != null) {
- mFingerprintStateListener.onStateChanged(newState);
+ private void setBiometricState(@BiometricStateListener.State int newState) {
+ if (mBiometricStateListener != null) {
+ mBiometricStateListener.onStateChanged(newState);
mLooper.dispatchAll();
}
}
@@ -204,10 +204,10 @@ public class SideFpsEventHandlerTest {
fpCallbackCaptor.getValue().onAllAuthenticatorsRegistered(
List.of(mock(FingerprintSensorPropertiesInternal.class)));
if (hasSfps) {
- ArgumentCaptor<FingerprintStateListener> captor = ArgumentCaptor.forClass(
- FingerprintStateListener.class);
- verify(mFingerprintManager).registerFingerprintStateListener(captor.capture());
- mFingerprintStateListener = captor.getValue();
+ ArgumentCaptor<BiometricStateListener> captor = ArgumentCaptor.forClass(
+ BiometricStateListener.class);
+ verify(mFingerprintManager).registerBiometricStateListener(captor.capture());
+ mBiometricStateListener = captor.getValue();
}
}
}
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index bb98bc0bab53..54b3c400af4f 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -65,6 +65,7 @@ import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.TelephonyNetworkSpecifier;
+import android.net.Uri;
import android.net.vcn.IVcnStatusCallback;
import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
import android.net.vcn.VcnConfig;
@@ -114,18 +115,24 @@ import java.util.UUID;
public class VcnManagementServiceTest {
private static final String TEST_PACKAGE_NAME =
VcnManagementServiceTest.class.getPackage().getName();
+ private static final String TEST_PACKAGE_NAME_2 = "TEST_PKG_2";
private static final String TEST_CB_PACKAGE_NAME =
VcnManagementServiceTest.class.getPackage().getName() + ".callback";
private static final ParcelUuid TEST_UUID_1 = new ParcelUuid(new UUID(0, 0));
private static final ParcelUuid TEST_UUID_2 = new ParcelUuid(new UUID(1, 1));
+ private static final ParcelUuid TEST_UUID_3 = new ParcelUuid(new UUID(2, 2));
private static final VcnConfig TEST_VCN_CONFIG;
+ private static final VcnConfig TEST_VCN_CONFIG_PKG_2;
private static final int TEST_UID = Process.FIRST_APPLICATION_UID;
static {
final Context mockConfigContext = mock(Context.class);
- doReturn(TEST_PACKAGE_NAME).when(mockConfigContext).getOpPackageName();
+ doReturn(TEST_PACKAGE_NAME).when(mockConfigContext).getOpPackageName();
TEST_VCN_CONFIG = VcnConfigTest.buildTestConfig(mockConfigContext);
+
+ doReturn(TEST_PACKAGE_NAME_2).when(mockConfigContext).getOpPackageName();
+ TEST_VCN_CONFIG_PKG_2 = VcnConfigTest.buildTestConfig(mockConfigContext);
}
private static final Map<ParcelUuid, VcnConfig> TEST_VCN_CONFIG_MAP =
@@ -246,18 +253,24 @@ public class VcnManagementServiceTest {
eq(android.Manifest.permission.NETWORK_FACTORY), any());
}
+
private void setupMockedCarrierPrivilege(boolean isPrivileged) {
+ setupMockedCarrierPrivilege(isPrivileged, TEST_PACKAGE_NAME);
+ }
+
+ private void setupMockedCarrierPrivilege(boolean isPrivileged, String pkg) {
doReturn(Collections.singletonList(TEST_SUBSCRIPTION_INFO))
.when(mSubMgr)
.getSubscriptionsInGroup(any());
doReturn(mTelMgr)
.when(mTelMgr)
.createForSubscriptionId(eq(TEST_SUBSCRIPTION_INFO.getSubscriptionId()));
- doReturn(isPrivileged
- ? CARRIER_PRIVILEGE_STATUS_HAS_ACCESS
- : CARRIER_PRIVILEGE_STATUS_NO_ACCESS)
+ doReturn(
+ isPrivileged
+ ? CARRIER_PRIVILEGE_STATUS_HAS_ACCESS
+ : CARRIER_PRIVILEGE_STATUS_NO_ACCESS)
.when(mTelMgr)
- .checkCarrierPrivilegesForPackage(eq(TEST_PACKAGE_NAME));
+ .checkCarrierPrivilegesForPackage(eq(pkg));
}
@Test
@@ -414,7 +427,13 @@ public class VcnManagementServiceTest {
private BroadcastReceiver getPackageChangeReceiver() {
final ArgumentCaptor<BroadcastReceiver> captor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
- verify(mMockContext).registerReceiver(captor.capture(), any(), any(), any());
+ verify(mMockContext).registerReceiver(captor.capture(), argThat(filter -> {
+ return filter.hasAction(Intent.ACTION_PACKAGE_ADDED)
+ && filter.hasAction(Intent.ACTION_PACKAGE_REPLACED)
+ && filter.hasAction(Intent.ACTION_PACKAGE_REMOVED)
+ && filter.hasAction(Intent.ACTION_PACKAGE_DATA_CLEARED)
+ && filter.hasAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
+ }), any(), any());
return captor.getValue();
}
@@ -539,6 +558,44 @@ public class VcnManagementServiceTest {
}
@Test
+ public void testPackageChangeListener_packageDataCleared() throws Exception {
+ triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_1, Collections.singleton(TEST_UUID_1));
+ final Vcn vcn = mVcnMgmtSvc.getAllVcns().get(TEST_UUID_1);
+
+ final BroadcastReceiver receiver = getPackageChangeReceiver();
+ assertEquals(TEST_VCN_CONFIG_MAP, mVcnMgmtSvc.getConfigs());
+
+ final Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED);
+ intent.setData(Uri.parse("package:" + TEST_PACKAGE_NAME));
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(TEST_UID));
+
+ receiver.onReceive(mMockContext, intent);
+ mTestLooper.dispatchAll();
+ verify(vcn).teardownAsynchronously();
+ assertTrue(mVcnMgmtSvc.getConfigs().isEmpty());
+ verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class));
+ }
+
+ @Test
+ public void testPackageChangeListener_packageFullyRemoved() throws Exception {
+ triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_1, Collections.singleton(TEST_UUID_1));
+ final Vcn vcn = mVcnMgmtSvc.getAllVcns().get(TEST_UUID_1);
+
+ final BroadcastReceiver receiver = getPackageChangeReceiver();
+ assertEquals(TEST_VCN_CONFIG_MAP, mVcnMgmtSvc.getConfigs());
+
+ final Intent intent = new Intent(Intent.ACTION_PACKAGE_FULLY_REMOVED);
+ intent.setData(Uri.parse("package:" + TEST_PACKAGE_NAME));
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(TEST_UID));
+
+ receiver.onReceive(mMockContext, intent);
+ mTestLooper.dispatchAll();
+ verify(vcn).teardownAsynchronously();
+ assertTrue(mVcnMgmtSvc.getConfigs().isEmpty());
+ verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class));
+ }
+
+ @Test
public void testSetVcnConfigRequiresNonSystemServer() throws Exception {
doReturn(Process.SYSTEM_UID).when(mMockDeps).getBinderCallingUid();
@@ -578,7 +635,7 @@ public class VcnManagementServiceTest {
@Test
public void testSetVcnConfigMismatchedPackages() throws Exception {
try {
- mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, TEST_VCN_CONFIG, "IncorrectPackage");
+ mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, TEST_VCN_CONFIG, TEST_PACKAGE_NAME_2);
fail("Expected exception due to mismatched packages in config and method call");
} catch (IllegalArgumentException expected) {
verify(mMockPolicyListener, never()).onPolicyChanged();
@@ -678,11 +735,12 @@ public class VcnManagementServiceTest {
}
@Test
- public void testClearVcnConfigRequiresCarrierPrivileges() throws Exception {
+ public void testClearVcnConfigRequiresCarrierPrivilegesOrProvisioningPackage()
+ throws Exception {
setupMockedCarrierPrivilege(false);
try {
- mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME);
+ mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME_2);
fail("Expected security exception for missing carrier privileges");
} catch (SecurityException expected) {
}
@@ -691,20 +749,32 @@ public class VcnManagementServiceTest {
@Test
public void testClearVcnConfigMismatchedPackages() throws Exception {
try {
- mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, "IncorrectPackage");
+ mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME_2);
fail("Expected security exception due to mismatched packages");
} catch (SecurityException expected) {
}
}
@Test
- public void testClearVcnConfig() throws Exception {
+ public void testClearVcnConfig_callerIsProvisioningPackage() throws Exception {
+ // Lose carrier privileges to test that provisioning package is sufficient.
+ setupMockedCarrierPrivilege(false);
+
mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME);
assertTrue(mVcnMgmtSvc.getConfigs().isEmpty());
verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class));
}
@Test
+ public void testClearVcnConfig_callerIsCarrierPrivileged() throws Exception {
+ setupMockedCarrierPrivilege(true, TEST_PACKAGE_NAME_2);
+
+ mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1, TEST_PACKAGE_NAME_2);
+ assertTrue(mVcnMgmtSvc.getConfigs().isEmpty());
+ verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class));
+ }
+
+ @Test
public void testClearVcnConfigNotifiesStatusCallback() throws Exception {
setupSubscriptionAndStartVcn(TEST_SUBSCRIPTION_ID, TEST_UUID_2, true /* isActive */);
mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_2, mMockStatusCallback, TEST_PACKAGE_NAME);
@@ -755,11 +825,12 @@ public class VcnManagementServiceTest {
@Test
public void testGetConfiguredSubscriptionGroupsMismatchedPackages() throws Exception {
- final String badPackage = "IncorrectPackage";
- doThrow(new SecurityException()).when(mAppOpsMgr).checkPackage(TEST_UID, badPackage);
+ doThrow(new SecurityException())
+ .when(mAppOpsMgr)
+ .checkPackage(TEST_UID, TEST_PACKAGE_NAME_2);
try {
- mVcnMgmtSvc.getConfiguredSubscriptionGroups(badPackage);
+ mVcnMgmtSvc.getConfiguredSubscriptionGroups(TEST_PACKAGE_NAME_2);
fail("Expected security exception due to mismatched packages");
} catch (SecurityException expected) {
}
@@ -767,14 +838,16 @@ public class VcnManagementServiceTest {
@Test
public void testGetConfiguredSubscriptionGroups() throws Exception {
+ setupMockedCarrierPrivilege(true, TEST_PACKAGE_NAME_2);
mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME);
+ mVcnMgmtSvc.setVcnConfig(TEST_UUID_3, TEST_VCN_CONFIG_PKG_2, TEST_PACKAGE_NAME_2);
- // Assert that if both UUID 1 and 2 are provisioned, the caller only gets ones that they are
- // privileged for.
+ // Assert that if UUIDs 1, 2 and 3 are provisioned, the caller only gets ones that they are
+ // privileged for, or are the provisioning package of.
triggerSubscriptionTrackerCbAndGetSnapshot(TEST_UUID_1, Collections.singleton(TEST_UUID_1));
final List<ParcelUuid> subGrps =
mVcnMgmtSvc.getConfiguredSubscriptionGroups(TEST_PACKAGE_NAME);
- assertEquals(Collections.singletonList(TEST_UUID_1), subGrps);
+ assertEquals(Arrays.asList(new ParcelUuid[] {TEST_UUID_1, TEST_UUID_2}), subGrps);
}
@Test