Merge "Systemservice change to propagate userId to MMSService" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index ed46cdd..21b1b17 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -856,6 +856,11 @@
java_aconfig_library {
name: "android.app.flags-aconfig-java",
aconfig_declarations: "android.app.flags-aconfig",
+ min_sdk_version: "34",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.nfcservices",
+ ],
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
diff --git a/core/api/current.txt b/core/api/current.txt
index 3effcc6..e3a2455 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -1491,6 +1491,7 @@
field public static final int shadowRadius = 16843108; // 0x1010164
field public static final int shape = 16843162; // 0x101019a
field public static final int shareInterpolator = 16843195; // 0x10101bb
+ field @FlaggedApi("android.nfc.nfc_associated_role_services") public static final int shareRolePriority;
field @Deprecated public static final int sharedUserId = 16842763; // 0x101000b
field @Deprecated public static final int sharedUserLabel = 16843361; // 0x1010261
field public static final int sharedUserMaxSdkVersion = 16844365; // 0x101064d
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 6b2cfee..903e18d 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -10463,6 +10463,7 @@
method @FlaggedApi("android.nfc.enable_nfc_mainline") public void setDynamicAidGroup(@NonNull android.nfc.cardemulation.AidGroup);
method @FlaggedApi("android.nfc.enable_nfc_mainline") public void setOffHostSecureElement(@NonNull String);
method @FlaggedApi("android.nfc.nfc_observe_mode") public void setShouldDefaultToObserveMode(boolean);
+ method @FlaggedApi("android.nfc.nfc_associated_role_services") public boolean shareRolePriority();
method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean shouldDefaultToObserveMode();
method @FlaggedApi("android.nfc.enable_nfc_mainline") public void writeToParcel(@NonNull android.os.Parcel, int);
field @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public static final android.os.Parcelable.Creator<android.nfc.cardemulation.ApduServiceInfo> CREATOR;
diff --git a/core/java/android/content/EventLogTags.logtags b/core/java/android/content/EventLogTags.logtags
index 21ea90a..861a5b7 100644
--- a/core/java/android/content/EventLogTags.logtags
+++ b/core/java/android/content/EventLogTags.logtags
@@ -1,4 +1,4 @@
-# See system/core/logcat/event.logtags for a description of the format of this file.
+# See system/logging/logcat/event.logtags for a description of the format of this file.
option java_package android.content;
diff --git a/core/java/android/os/EventLogTags.logtags b/core/java/android/os/EventLogTags.logtags
index b143a74..f57aad0 100644
--- a/core/java/android/os/EventLogTags.logtags
+++ b/core/java/android/os/EventLogTags.logtags
@@ -1,4 +1,4 @@
-# See system/core/logcat/event.logtags for a description of the format of this file.
+# See system/logging/logcat/event.logtags for a description of the format of this file.
option java_package android.os
diff --git a/core/java/android/view/EventLogTags.logtags b/core/java/android/view/EventLogTags.logtags
index f1cd671..a43ba17 100644
--- a/core/java/android/view/EventLogTags.logtags
+++ b/core/java/android/view/EventLogTags.logtags
@@ -1,4 +1,4 @@
-# See system/core/logcat/event.logtags for a description of the format of this file.
+# See system/logging/logcat/event.logtags for a description of the format of this file.
option java_package android.view
@@ -35,7 +35,7 @@
# 6: Percent
# Default value for data of type int/long is 2 (bytes).
#
-# See system/core/logcat/event.logtags for the master copy of the tags.
+# See system/logging/logcat/event.logtags for the master copy of the tags.
# 32000 - 32999 reserved for input method framework
# IME animation is started.
diff --git a/core/java/com/android/internal/app/EventLogTags.logtags b/core/java/com/android/internal/app/EventLogTags.logtags
index d681a8d..a18a824 100644
--- a/core/java/com/android/internal/app/EventLogTags.logtags
+++ b/core/java/com/android/internal/app/EventLogTags.logtags
@@ -1,4 +1,4 @@
-# See system/core/logcat/event.logtags for a description of the format of this file.
+# See system/logging/logcat/event.logtags for a description of the format of this file.
option java_package com.android.internal.app;
diff --git a/core/java/com/android/internal/logging/EventLogTags.logtags b/core/java/com/android/internal/logging/EventLogTags.logtags
index 693bd16..db47797 100644
--- a/core/java/com/android/internal/logging/EventLogTags.logtags
+++ b/core/java/com/android/internal/logging/EventLogTags.logtags
@@ -1,4 +1,4 @@
-# See system/core/logcat/event.logtags for a description of the format of this file.
+# See system/logging/logcat/event.logtags for a description of the format of this file.
option java_package com.android.internal.logging;
diff --git a/core/java/org/chromium/arc/EventLogTags.logtags b/core/java/org/chromium/arc/EventLogTags.logtags
index 1b7160e..8102d6f 100644
--- a/core/java/org/chromium/arc/EventLogTags.logtags
+++ b/core/java/org/chromium/arc/EventLogTags.logtags
@@ -1,4 +1,4 @@
-# See system/core/logcat/event.logtags for a description of the format of this file.
+# See system/logging/logcat/event.logtags for a description of the format of this file.
option java_package org.chromium.arc
diff --git a/core/jni/android_os_SELinux.cpp b/core/jni/android_os_SELinux.cpp
index 805d5ad..cd39e6f 100644
--- a/core/jni/android_os_SELinux.cpp
+++ b/core/jni/android_os_SELinux.cpp
@@ -34,23 +34,27 @@
namespace android {
namespace {
-std::atomic<selabel_handle*> sehandle{nullptr};
+std::atomic<selabel_handle *> file_sehandle{nullptr};
-selabel_handle* GetSELabelHandle() {
- selabel_handle* h = sehandle.load();
+selabel_handle *GetSELabelHandle_impl(selabel_handle *(*handle_func)(),
+ std::atomic<selabel_handle *> *handle_cache) {
+ selabel_handle *h = handle_cache->load();
if (h != nullptr) {
return h;
}
- h = selinux_android_file_context_handle();
+ h = handle_func();
selabel_handle* expected = nullptr;
- if (!sehandle.compare_exchange_strong(expected, h)) {
+ if (!handle_cache->compare_exchange_strong(expected, h)) {
selabel_close(h);
- return sehandle.load();
+ return handle_cache->load();
}
return h;
}
+selabel_handle *GetSELabelFileBackendHandle() {
+ return GetSELabelHandle_impl(selinux_android_file_context_handle, &file_sehandle);
+}
}
struct SecurityContext_Delete {
@@ -106,7 +110,7 @@
return NULL;
}
- auto* selabel_handle = GetSELabelHandle();
+ auto *selabel_handle = GetSELabelFileBackendHandle();
if (selabel_handle == NULL) {
ALOGE("fileSelabelLookup => Failed to get SEHandle");
return NULL;
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 9846b71..4952400 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4460,6 +4460,12 @@
<!-- Whether the device should default to observe mode when this service is
default or in the foreground. -->
<attr name="shouldDefaultToObserveMode" format="boolean"/>
+ <!-- Whether this service should share the same AID routing priority as the role
+ owner. This package and the role owner must have the same signature, and the
+ role owner must opt into this behavior by using the property named by
+ {@link android.nfc.cardemulation.CardEmulation.PROPERTY_ALLOW_SHARED_ROLE_PRIORITY }
+ in the <code><application&rt;</code> tag. -->
+ <attr name="shareRolePriority" format="boolean"/>
</declare-styleable>
<!-- Use <code>offhost-apdu-service</code> as the root tag of the XML resource that
@@ -4487,6 +4493,7 @@
<!-- Whether the device should default to observe mode when this service is
default or in the foreground. -->
<attr name="shouldDefaultToObserveMode"/>
+ <attr name="shareRolePriority"/>
</declare-styleable>
<!-- Specify one or more <code>aid-group</code> elements inside a
diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml
index b64334f..d084632 100644
--- a/core/res/res/values/public-staging.xml
+++ b/core/res/res/values/public-staging.xml
@@ -118,6 +118,8 @@
<public name="languageSettingsActivity"/>
<!-- @FlaggedApi("android.service.controls.flags.Flags.FLAG_HOME_PANEL_DREAM") -->
<public name="dreamCategory"/>
+ <!-- @FlaggedApi(android.nfc.Flags.FLAG_NFC_ASSOCIATED_ROLE_SERVICES) -->
+ <public name="shareRolePriority"/>
</staging-public-group>
<staging-public-group type="id" first-id="0x01b60000">
diff --git a/core/tests/overlaytests/host/Android.bp b/core/tests/overlaytests/host/Android.bp
index 6340980..9b72004 100644
--- a/core/tests/overlaytests/host/Android.bp
+++ b/core/tests/overlaytests/host/Android.bp
@@ -28,14 +28,14 @@
test_suites: [
"device-tests",
],
- target_required: [
- "OverlayHostTests_NonPlatformSignatureOverlay",
- "OverlayHostTests_PlatformSignatureStaticOverlay",
- "OverlayHostTests_PlatformSignatureOverlay",
- "OverlayHostTests_UpdateOverlay",
- "OverlayHostTests_FrameworkOverlayV1",
- "OverlayHostTests_FrameworkOverlayV2",
- "OverlayHostTests_AppOverlayV1",
- "OverlayHostTests_AppOverlayV2",
+ device_common_data: [
+ ":OverlayHostTests_NonPlatformSignatureOverlay",
+ ":OverlayHostTests_PlatformSignatureStaticOverlay",
+ ":OverlayHostTests_PlatformSignatureOverlay",
+ ":OverlayHostTests_UpdateOverlay",
+ ":OverlayHostTests_FrameworkOverlayV1",
+ ":OverlayHostTests_FrameworkOverlayV2",
+ ":OverlayHostTests_AppOverlayV1",
+ ":OverlayHostTests_AppOverlayV2",
],
}
diff --git a/nfc/Android.bp b/nfc/Android.bp
index 7ad8c4c..abe0ab7 100644
--- a/nfc/Android.bp
+++ b/nfc/Android.bp
@@ -37,6 +37,7 @@
java_sdk_library {
name: "framework-nfc",
libs: [
+ "androidx.annotation_annotation",
"unsupportedappusage", // for android.compat.annotation.UnsupportedAppUsage
"framework-permission-s.stubs.module_lib",
"framework-permission.stubs.module_lib",
diff --git a/nfc/api/current.txt b/nfc/api/current.txt
index 2aa73db..0ee81cb 100644
--- a/nfc/api/current.txt
+++ b/nfc/api/current.txt
@@ -233,6 +233,7 @@
field @FlaggedApi("android.nfc.nfc_event_listener") public static final int NFC_INTERNAL_ERROR_NFC_CRASH_RESTART = 1; // 0x1
field @FlaggedApi("android.nfc.nfc_event_listener") public static final int NFC_INTERNAL_ERROR_NFC_HARDWARE_ERROR = 2; // 0x2
field @FlaggedApi("android.nfc.nfc_event_listener") public static final int NFC_INTERNAL_ERROR_UNKNOWN = 0; // 0x0
+ field @FlaggedApi("android.nfc.nfc_associated_role_services") public static final String PROPERTY_ALLOW_SHARED_ROLE_PRIORITY = "android.nfc.cardemulation.PROPERTY_ALLOW_SHARED_ROLE_PRIORITY";
field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_DEFAULT = 3; // 0x3
field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_DH = 0; // 0x0
field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE = 1; // 0x1
diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt
index e97b15d..cf11ac0 100644
--- a/nfc/api/system-current.txt
+++ b/nfc/api/system-current.txt
@@ -85,6 +85,10 @@
field public static final int HCE_ACTIVATE = 1; // 0x1
field public static final int HCE_DATA_TRANSFERRED = 2; // 0x2
field public static final int HCE_DEACTIVATE = 3; // 0x3
+ field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int NFCEE_TECH_A = 1; // 0x1
+ field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int NFCEE_TECH_B = 2; // 0x2
+ field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int NFCEE_TECH_F = 4; // 0x4
+ field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int NFCEE_TECH_NONE = 0; // 0x0
field public static final int POLLING_STATE_CHANGE_ALREADY_IN_REQUESTED_STATE = 2; // 0x2
field public static final int POLLING_STATE_CHANGE_SUCCEEDED = 1; // 0x1
field public static final int STATUS_OK = 0; // 0x0
@@ -250,6 +254,7 @@
field @FlaggedApi("android.nfc.enable_card_emulation_euicc") public static final int SET_SUBSCRIPTION_ID_STATUS_FAILED_INVALID_SUBSCRIPTION_ID = 1; // 0x1
field @FlaggedApi("android.nfc.enable_card_emulation_euicc") public static final int SET_SUBSCRIPTION_ID_STATUS_FAILED_NOT_SUPPORTED = 3; // 0x3
field @FlaggedApi("android.nfc.enable_card_emulation_euicc") public static final int SET_SUBSCRIPTION_ID_STATUS_SUCCESS = 0; // 0x0
+ field @FlaggedApi("android.nfc.enable_card_emulation_euicc") public static final int SET_SUBSCRIPTION_ID_STATUS_UNKNOWN = -1; // 0xffffffff
}
}
diff --git a/nfc/java/android/nfc/NfcOemExtension.java b/nfc/java/android/nfc/NfcOemExtension.java
index fb11875..b46e343 100644
--- a/nfc/java/android/nfc/NfcOemExtension.java
+++ b/nfc/java/android/nfc/NfcOemExtension.java
@@ -150,28 +150,24 @@
/**
* Technology Type for {@link #getActiveNfceeList()}.
- * @hide
*/
@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
public static final int NFCEE_TECH_NONE = 0;
/**
* Technology Type for {@link #getActiveNfceeList()}.
- * @hide
*/
@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
public static final int NFCEE_TECH_A = 1;
/**
* Technology Type for {@link #getActiveNfceeList()}.
- * @hide
*/
@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
public static final int NFCEE_TECH_B = 1 << 1;
/**
* Technology Type for {@link #getActiveNfceeList()}.
- * @hide
*/
@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
public static final int NFCEE_TECH_F = 1 << 2;
@@ -670,12 +666,15 @@
/**
* Get the Active NFCEE (NFC Execution Environment) List
*
- * @see Reader#getName() for the list of possible NFCEE names.
- *
* @return Map< String, @NfceeTechnology Integer >
* A HashMap where keys are activated secure elements and
- * the values are bitmap of technologies supported by each secure element
- * on success keys can contain "eSE" and "UICC", otherwise empty map.
+ * the values are bitmap of technologies supported by each secure element:
+ * NFCEE_TECH_A == 0x1
+ * NFCEE_TECH_B == 0x2
+ * NFCEE_TECH_F == 0x4
+ * and keys can contain "eSE" and "SIM" with a number,
+ * in case of failure an empty map is returned.
+ * @see Reader#getName() for the list of possible NFCEE names.
*/
@NonNull
@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
diff --git a/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java b/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java
index 3d293f7..eac7836 100644
--- a/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/nfc/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -148,6 +148,12 @@
private boolean mShouldDefaultToObserveMode;
/**
+ * Whether or not this service wants to share the same routing priority as the
+ * Wallet role owner.
+ */
+ private boolean mShareRolePriority;
+
+ /**
* @hide
*/
@UnsupportedAppUsage
@@ -284,6 +290,12 @@
mShouldDefaultToObserveMode = sa.getBoolean(
R.styleable.HostApduService_shouldDefaultToObserveMode,
false);
+ if (Flags.nfcAssociatedRoleServices()) {
+ mShareRolePriority = sa.getBoolean(
+ R.styleable.HostApduService_shareRolePriority,
+ false
+ );
+ }
sa.recycle();
} else {
TypedArray sa = res.obtainAttributes(attrs,
@@ -314,6 +326,12 @@
}
}
mStaticOffHostName = mOffHostName;
+ if (Flags.nfcAssociatedRoleServices()) {
+ mShareRolePriority = sa.getBoolean(
+ R.styleable.OffHostApduService_shareRolePriority,
+ false
+ );
+ }
sa.recycle();
}
@@ -705,6 +723,17 @@
}
/**
+ * Returns whether or not this service wants to share the Wallet role holder priority
+ * with other packages/services with the same signature.
+ *
+ * @return whether or not this service wants to share priority
+ */
+ @FlaggedApi(Flags.FLAG_NFC_ASSOCIATED_ROLE_SERVICES)
+ public boolean shareRolePriority() {
+ return mShareRolePriority;
+ }
+
+ /**
* Returns description of service.
* @return user readable description of service
*/
diff --git a/nfc/java/android/nfc/cardemulation/CardEmulation.java b/nfc/java/android/nfc/cardemulation/CardEmulation.java
index cb364fb..e0bc15f 100644
--- a/nfc/java/android/nfc/cardemulation/CardEmulation.java
+++ b/nfc/java/android/nfc/cardemulation/CardEmulation.java
@@ -246,6 +246,25 @@
@Retention(RetentionPolicy.SOURCE)
public @interface SetServiceEnabledStatusCode {}
+ /**
+ * Property name used to indicate that an application wants to allow associated services
+ * to share the same AID routing priority when this application is the role holder.
+ * <p>
+ * Example:
+ * <pre>
+ * {@code
+ * <application>
+ * ...
+ * <property android:name="android.nfc.cardemulation.PROPERTY_ALLOW_SHARED_ROLE_PRIORITY"
+ * android:value="true"/>
+ * </application>
+ * }
+ * </pre>
+ */
+ @FlaggedApi(Flags.FLAG_NFC_ASSOCIATED_ROLE_SERVICES)
+ public static final String PROPERTY_ALLOW_SHARED_ROLE_PRIORITY =
+ "android.nfc.cardemulation.PROPERTY_ALLOW_SHARED_ROLE_PRIORITY";
+
static boolean sIsInitialized = false;
static HashMap<Context, CardEmulation> sCardEmus = new HashMap<Context, CardEmulation>();
static INfcCardEmulation sService;
@@ -1095,6 +1114,14 @@
@FlaggedApi(android.nfc.Flags.FLAG_ENABLE_CARD_EMULATION_EUICC)
public static final int SET_SUBSCRIPTION_ID_STATUS_FAILED_NOT_SUPPORTED = 3;
+ /**
+ * Setting the default subscription ID failed because of unknown error.
+ * @hide
+ */
+ @SystemApi
+ @FlaggedApi(Flags.FLAG_ENABLE_CARD_EMULATION_EUICC)
+ public static final int SET_SUBSCRIPTION_ID_STATUS_UNKNOWN = -1;
+
/** @hide */
@IntDef(prefix = "SET_SUBSCRIPTION_ID_STATUS_",
value = {
@@ -1102,6 +1129,7 @@
SET_SUBSCRIPTION_ID_STATUS_FAILED_INVALID_SUBSCRIPTION_ID,
SET_SUBSCRIPTION_ID_STATUS_FAILED_INTERNAL_ERROR,
SET_SUBSCRIPTION_ID_STATUS_FAILED_NOT_SUPPORTED,
+ SET_SUBSCRIPTION_ID_STATUS_UNKNOWN
})
@Retention(RetentionPolicy.SOURCE)
public @interface SetSubscriptionIdStatus {}
@@ -1110,9 +1138,10 @@
* Sets the system's default NFC subscription id.
*
* <p> For devices with multiple UICC/EUICC that is configured to be NFCEE, this sets the
- * default UICC NFCEE that will handle NFC offhost CE transactoions </p>
+ * default UICC NFCEE that will handle NFC offhost CE transactions </p>
*
- * @param subscriptionId the default NFC subscription Id to set.
+ * @param subscriptionId the default NFC subscription Id to set. User can get subscription id
+ * from {@link SubscriptionManager#getSubscriptionId(int)}
* @return status of the operation.
*
* @throws UnsupportedOperationException If the device does not have
@@ -1134,7 +1163,7 @@
* Returns the system's default NFC subscription id.
*
* <p> For devices with multiple UICC/EUICC that is configured to be NFCEE, this returns the
- * default UICC NFCEE that will handle NFC offhost CE transactoions </p>
+ * default UICC NFCEE that will handle NFC offhost CE transactions </p>
* <p> If the device has no UICC that can serve as NFCEE, this will return
* {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}.</p>
*
diff --git a/nfc/lint-baseline.xml b/nfc/lint-baseline.xml
index d0f797e..c6c627e 100644
--- a/nfc/lint-baseline.xml
+++ b/nfc/lint-baseline.xml
@@ -2,215 +2,6 @@
<issues format="6" by="lint 8.4.0-alpha01" type="baseline" client="" dependencies="true" name="" variant="all" version="8.4.0-alpha01">
<issue
- id="NewApi"
- message="Call requires API level 35 (current min is 34): `new android.nfc.cardemulation.AidGroup`"
- errorLine1=" AidGroup aidGroup = new AidGroup(aids, category);"
- errorLine2=" ~~~~~~~~~~~~">
- <location
- file="frameworks/base/nfc/java/android/nfc/cardemulation/CardEmulation.java"
- line="377"
- column="29"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 35 (current min is 34): `android.nfc.cardemulation.AidGroup#getAids`"
- errorLine1=" return (group != null ? group.getAids() : null);"
- errorLine2=" ~~~~~~~">
- <location
- file="frameworks/base/nfc/java/android/nfc/cardemulation/CardEmulation.java"
- line="537"
- column="43"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 35 (current min is 34): `android.nfc.cardemulation.AidGroup#getAids`"
- errorLine1=" return (group != null ? group.getAids() : null);"
- errorLine2=" ~~~~~~~">
- <location
- file="frameworks/base/nfc/java/android/nfc/cardemulation/CardEmulation.java"
- line="547"
- column="47"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 35 (current min is 34): `android.nfc.cardemulation.ApduServiceInfo#getAids`"
- errorLine1=" return (serviceInfo != null ? serviceInfo.getAids() : null);"
- errorLine2=" ~~~~~~~">
- <location
- file="frameworks/base/nfc/java/android/nfc/cardemulation/CardEmulation.java"
- line="714"
- column="55"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 35 (current min is 34): `android.nfc.cardemulation.ApduServiceInfo#getAids`"
- errorLine1=" return (serviceInfo != null ? serviceInfo.getAids() : null);"
- errorLine2=" ~~~~~~~">
- <location
- file="frameworks/base/nfc/java/android/nfc/cardemulation/CardEmulation.java"
- line="724"
- column="59"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 35 (current min is 34): `android.nfc.cardemulation.ApduServiceInfo#isOnHost`"
- errorLine1=" if (!serviceInfo.isOnHost()) {"
- errorLine2=" ~~~~~~~~">
- <location
- file="frameworks/base/nfc/java/android/nfc/cardemulation/CardEmulation.java"
- line="755"
- column="34"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 35 (current min is 34): `android.nfc.cardemulation.ApduServiceInfo#getOffHostSecureElement`"
- errorLine1=" return serviceInfo.getOffHostSecureElement() == null ?"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/nfc/java/android/nfc/cardemulation/CardEmulation.java"
- line="756"
- column="40"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 35 (current min is 34): `android.nfc.cardemulation.ApduServiceInfo#getOffHostSecureElement`"
- errorLine1=' "OffHost" : serviceInfo.getOffHostSecureElement();'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/nfc/java/android/nfc/cardemulation/CardEmulation.java"
- line="757"
- column="53"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 35 (current min is 34): `android.nfc.cardemulation.ApduServiceInfo#isOnHost`"
- errorLine1=" if (!serviceInfo.isOnHost()) {"
- errorLine2=" ~~~~~~~~">
- <location
- file="frameworks/base/nfc/java/android/nfc/cardemulation/CardEmulation.java"
- line="772"
- column="38"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 35 (current min is 34): `android.nfc.cardemulation.ApduServiceInfo#getOffHostSecureElement`"
- errorLine1=" return serviceInfo.getOffHostSecureElement() == null ?"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/nfc/java/android/nfc/cardemulation/CardEmulation.java"
- line="773"
- column="44"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 35 (current min is 34): `android.nfc.cardemulation.ApduServiceInfo#getOffHostSecureElement`"
- errorLine1=' "Offhost" : serviceInfo.getOffHostSecureElement();'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/nfc/java/android/nfc/cardemulation/CardEmulation.java"
- line="774"
- column="57"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 35 (current min is 34): `android.nfc.cardemulation.ApduServiceInfo#getDescription`"
- errorLine1=" return (serviceInfo != null ? serviceInfo.getDescription() : null);"
- errorLine2=" ~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/nfc/java/android/nfc/cardemulation/CardEmulation.java"
- line="798"
- column="55"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 35 (current min is 34): `android.nfc.cardemulation.ApduServiceInfo#getDescription`"
- errorLine1=" return (serviceInfo != null ? serviceInfo.getDescription() : null);"
- errorLine2=" ~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/nfc/java/android/nfc/cardemulation/CardEmulation.java"
- line="808"
- column="59"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 35 (current min is 34): `android.app.Activity#isResumed`"
- errorLine1=" if (!activity.isResumed()) {"
- errorLine2=" ~~~~~~~~~">
- <location
- file="frameworks/base/nfc/java/android/nfc/cardemulation/CardEmulation.java"
- line="1032"
- column="23"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 35 (current min is 34): `android.app.Activity#isResumed`"
- errorLine1=" if (!activity.isResumed()) {"
- errorLine2=" ~~~~~~~~~">
- <location
- file="frameworks/base/nfc/java/android/nfc/cardemulation/CardEmulation.java"
- line="1066"
- column="23"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 35 (current min is 34): `android.app.Activity#isResumed`"
- errorLine1=" resumed = activity.isResumed();"
- errorLine2=" ~~~~~~~~~">
- <location
- file="frameworks/base/nfc/java/android/nfc/NfcActivityManager.java"
- line="124"
- column="32"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 35 (current min is 34): `android.app.Activity#isResumed`"
- errorLine1=" if (!activity.isResumed()) {"
- errorLine2=" ~~~~~~~~~">
- <location
- file="frameworks/base/nfc/java/android/nfc/NfcAdapter.java"
- line="2457"
- column="23"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 35 (current min is 34): `android.app.Activity#isResumed`"
- errorLine1=" if (!activity.isResumed()) {"
- errorLine2=" ~~~~~~~~~">
- <location
- file="frameworks/base/nfc/java/android/nfc/cardemulation/NfcFCardEmulation.java"
- line="315"
- column="23"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 35 (current min is 34): `android.app.Activity#isResumed`"
- errorLine1=" if (!activity.isResumed()) {"
- errorLine2=" ~~~~~~~~~">
- <location
- file="frameworks/base/nfc/java/android/nfc/cardemulation/NfcFCardEmulation.java"
- line="351"
- column="23"/>
- </issue>
-
- <issue
id="FlaggedApi"
message="Method `PollingFrame()` is a flagged API and should be inside an `if (Flags.nfcReadPollingLoop())` check (or annotate the surrounding method `handleMessage` with `@FlaggedApi(Flags.FLAG_NFC_READ_POLLING_LOOP) to transfer requirement to caller`)"
errorLine1=" pollingFrames.add(new PollingFrame(frame));"
@@ -265,4 +56,4 @@
column="44"/>
</issue>
-</issues>
\ No newline at end of file
+</issues>
diff --git a/nfc/tests/Android.bp b/nfc/tests/Android.bp
index bfa814d..b6090e8 100644
--- a/nfc/tests/Android.bp
+++ b/nfc/tests/Android.bp
@@ -25,17 +25,36 @@
android_test {
name: "NfcManagerTests",
static_libs: [
- "androidx.test.ext.junit",
+ "androidx.test.core",
"androidx.test.rules",
- "mockito-target-minus-junit4",
+ "androidx.test.runner",
+ "androidx.test.ext.junit",
+ "framework-nfc.impl",
+ "mockito-target-extended-minus-junit4",
+ "frameworks-base-testutils",
"truth",
+ "androidx.annotation_annotation",
+ "androidx.appcompat_appcompat",
+ "flag-junit",
+ "platform-test-annotations",
+ "testables",
],
libs: [
- "framework-nfc.impl",
+ "android.test.base.stubs.system",
+ "android.test.mock.stubs.system",
"android.test.runner.stubs.system",
],
+ jni_libs: [
+ // Required for ExtendedMockito
+ "libdexmakerjvmtiagent",
+ "libstaticjvmtiagent",
+ ],
srcs: ["src/**/*.java"],
platform_apis: true,
certificate: "platform",
- test_suites: ["device-tests"],
+ test_suites: [
+ "device-tests",
+ "mts-nfc",
+ ],
+ min_sdk_version: "35", // Should be 36 later.
}
diff --git a/nfc/tests/AndroidManifest.xml b/nfc/tests/AndroidManifest.xml
index 99e2c34c..9564672 100644
--- a/nfc/tests/AndroidManifest.xml
+++ b/nfc/tests/AndroidManifest.xml
@@ -17,7 +17,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.nfc">
- <application>
+ <application android:debuggable="true">
<uses-library android:name="android.test.runner" />
</application>
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt
index 0329794..0a4198a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt
@@ -32,7 +32,8 @@
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.test.runBlockingTest
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -125,14 +126,11 @@
)
underTest =
- HomeControlsKeyguardQuickAffordanceConfig(
- context = context,
- component = component,
- )
+ HomeControlsKeyguardQuickAffordanceConfig(context = context, component = component)
}
@Test
- fun state() = runBlockingTest {
+ fun state() = runTest(UnconfinedTestDispatcher()) {
whenever(component.isEnabled()).thenReturn(isFeatureEnabled)
whenever(controlsController.getFavorites())
.thenReturn(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt
index 7d68cc0..c9b4366 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt
@@ -19,19 +19,20 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.res.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.Expandable
import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.controls.dagger.ControlsComponent
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig.OnTriggeredResult
+import com.android.systemui.res.R
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import java.util.Optional
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.test.runBlockingTest
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -54,14 +55,11 @@
whenever(component.canShowWhileLockedSetting).thenReturn(MutableStateFlow(true))
underTest =
- HomeControlsKeyguardQuickAffordanceConfig(
- context = context,
- component = component,
- )
+ HomeControlsKeyguardQuickAffordanceConfig(context = context, component = component)
}
@Test
- fun state_whenCannotShowWhileLocked_returnsHidden() = runBlockingTest {
+ fun state_whenCannotShowWhileLocked_returnsHidden() = runTest(UnconfinedTestDispatcher()) {
whenever(component.canShowWhileLockedSetting).thenReturn(MutableStateFlow(false))
whenever(component.isEnabled()).thenReturn(true)
whenever(component.getTileImageId()).thenReturn(R.drawable.controls_icon)
@@ -81,7 +79,7 @@
}
@Test
- fun state_whenListingControllerIsMissing_returnsHidden() = runBlockingTest {
+ fun state_whenListingControllerIsMissing_returnsHidden() = runTest(UnconfinedTestDispatcher()) {
whenever(component.isEnabled()).thenReturn(true)
whenever(component.getTileImageId()).thenReturn(R.drawable.controls_icon)
whenever(component.getTileTitleId()).thenReturn(R.string.quick_controls_title)
@@ -100,23 +98,25 @@
}
@Test
- fun onQuickAffordanceTriggered_canShowWhileLockedSettingIsTrue() = runBlockingTest {
- whenever(component.canShowWhileLockedSetting).thenReturn(MutableStateFlow(true))
+ fun onQuickAffordanceTriggered_canShowWhileLockedSettingIsTrue() =
+ runTest(UnconfinedTestDispatcher()) {
+ whenever(component.canShowWhileLockedSetting).thenReturn(MutableStateFlow(true))
- val onClickedResult = underTest.onTriggered(expandable)
+ val onClickedResult = underTest.onTriggered(expandable)
- assertThat(onClickedResult).isInstanceOf(OnTriggeredResult.StartActivity::class.java)
- assertThat((onClickedResult as OnTriggeredResult.StartActivity).canShowWhileLocked).isTrue()
- }
+ assertThat(onClickedResult).isInstanceOf(OnTriggeredResult.StartActivity::class.java)
+ assertThat((onClickedResult as OnTriggeredResult.StartActivity).canShowWhileLocked).isTrue()
+ }
@Test
- fun onQuickAffordanceTriggered_canShowWhileLockedSettingIsFalse() = runBlockingTest {
- whenever(component.canShowWhileLockedSetting).thenReturn(MutableStateFlow(false))
+ fun onQuickAffordanceTriggered_canShowWhileLockedSettingIsFalse() =
+ runTest(UnconfinedTestDispatcher()) {
+ whenever(component.canShowWhileLockedSetting).thenReturn(MutableStateFlow(false))
- val onClickedResult = underTest.onTriggered(expandable)
+ val onClickedResult = underTest.onTriggered(expandable)
- assertThat(onClickedResult).isInstanceOf(OnTriggeredResult.StartActivity::class.java)
- assertThat((onClickedResult as OnTriggeredResult.StartActivity).canShowWhileLocked)
- .isFalse()
- }
+ assertThat(onClickedResult).isInstanceOf(OnTriggeredResult.StartActivity::class.java)
+ assertThat((onClickedResult as OnTriggeredResult.StartActivity).canShowWhileLocked)
+ .isFalse()
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt
index ca64cec..a3f0763 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/quickaffordance/QrCodeScannerKeyguardQuickAffordanceConfigTest.kt
@@ -29,7 +29,7 @@
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
-import kotlinx.coroutines.test.runBlockingTest
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -56,60 +56,63 @@
}
@Test
- fun affordance_setsUpRegistrationAndDeliversInitialModel() = runBlockingTest {
- whenever(controller.isEnabledForLockScreenButton).thenReturn(true)
- var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
+ fun affordance_setsUpRegistrationAndDeliversInitialModel() =
+ runTest(UnconfinedTestDispatcher()) {
+ whenever(controller.isEnabledForLockScreenButton).thenReturn(true)
+ var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
- val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this)
+ val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this)
- val callbackCaptor = argumentCaptor<QRCodeScannerController.Callback>()
- verify(controller).addCallback(callbackCaptor.capture())
- verify(controller)
- .registerQRCodeScannerChangeObservers(
- QRCodeScannerController.DEFAULT_QR_CODE_SCANNER_CHANGE,
- QRCodeScannerController.QR_CODE_SCANNER_PREFERENCE_CHANGE
- )
- assertVisibleState(latest)
+ val callbackCaptor = argumentCaptor<QRCodeScannerController.Callback>()
+ verify(controller).addCallback(callbackCaptor.capture())
+ verify(controller)
+ .registerQRCodeScannerChangeObservers(
+ QRCodeScannerController.DEFAULT_QR_CODE_SCANNER_CHANGE,
+ QRCodeScannerController.QR_CODE_SCANNER_PREFERENCE_CHANGE,
+ )
+ assertVisibleState(latest)
- job.cancel()
- verify(controller).removeCallback(callbackCaptor.value)
- }
+ job.cancel()
+ verify(controller).removeCallback(callbackCaptor.value)
+ }
@Test
- fun affordance_scannerActivityChanged_deliversModelWithUpdatedIntent() = runBlockingTest {
- whenever(controller.isEnabledForLockScreenButton).thenReturn(true)
- var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
- val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this)
- val callbackCaptor = argumentCaptor<QRCodeScannerController.Callback>()
- verify(controller).addCallback(callbackCaptor.capture())
+ fun affordance_scannerActivityChanged_deliversModelWithUpdatedIntent() =
+ runTest(UnconfinedTestDispatcher()) {
+ whenever(controller.isEnabledForLockScreenButton).thenReturn(true)
+ var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
+ val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this)
+ val callbackCaptor = argumentCaptor<QRCodeScannerController.Callback>()
+ verify(controller).addCallback(callbackCaptor.capture())
- whenever(controller.intent).thenReturn(INTENT_2)
- callbackCaptor.value.onQRCodeScannerActivityChanged()
+ whenever(controller.intent).thenReturn(INTENT_2)
+ callbackCaptor.value.onQRCodeScannerActivityChanged()
- assertVisibleState(latest)
+ assertVisibleState(latest)
- job.cancel()
- verify(controller).removeCallback(callbackCaptor.value)
- }
+ job.cancel()
+ verify(controller).removeCallback(callbackCaptor.value)
+ }
@Test
- fun affordance_scannerPreferenceChanged_deliversVisibleModel() = runBlockingTest {
- var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
- val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this)
- val callbackCaptor = argumentCaptor<QRCodeScannerController.Callback>()
- verify(controller).addCallback(callbackCaptor.capture())
+ fun affordance_scannerPreferenceChanged_deliversVisibleModel() =
+ runTest(UnconfinedTestDispatcher()) {
+ var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
+ val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this)
+ val callbackCaptor = argumentCaptor<QRCodeScannerController.Callback>()
+ verify(controller).addCallback(callbackCaptor.capture())
- whenever(controller.isEnabledForLockScreenButton).thenReturn(true)
- callbackCaptor.value.onQRCodeScannerPreferenceChanged()
+ whenever(controller.isEnabledForLockScreenButton).thenReturn(true)
+ callbackCaptor.value.onQRCodeScannerPreferenceChanged()
- assertVisibleState(latest)
+ assertVisibleState(latest)
- job.cancel()
- verify(controller).removeCallback(callbackCaptor.value)
- }
+ job.cancel()
+ verify(controller).removeCallback(callbackCaptor.value)
+ }
@Test
- fun affordance_scannerPreferenceChanged_deliversNone() = runBlockingTest {
+ fun affordance_scannerPreferenceChanged_deliversNone() = runTest(UnconfinedTestDispatcher()) {
var latest: KeyguardQuickAffordanceConfig.LockScreenState? = null
val job = underTest.lockScreenState.onEach { latest = it }.launchIn(this)
val callbackCaptor = argumentCaptor<QRCodeScannerController.Callback>()
@@ -128,30 +131,29 @@
fun onQuickAffordanceTriggered() {
assertThat(underTest.onTriggered(mock()))
.isEqualTo(
- OnTriggeredResult.StartActivity(
- intent = INTENT_1,
- canShowWhileLocked = true,
- )
+ OnTriggeredResult.StartActivity(intent = INTENT_1, canShowWhileLocked = true)
)
}
@Test
- fun getPickerScreenState_enabledIfConfiguredOnDevice_isEnabledForPickerState() = runTest {
- whenever(controller.isAllowedOnLockScreen).thenReturn(true)
- whenever(controller.isAbleToLaunchScannerActivity).thenReturn(true)
+ fun getPickerScreenState_enabledIfConfiguredOnDevice_isEnabledForPickerState() =
+ runTest(UnconfinedTestDispatcher()) {
+ whenever(controller.isAllowedOnLockScreen).thenReturn(true)
+ whenever(controller.isAbleToLaunchScannerActivity).thenReturn(true)
- assertThat(underTest.getPickerScreenState())
- .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.Default())
- }
+ assertThat(underTest.getPickerScreenState())
+ .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.Default())
+ }
@Test
- fun getPickerScreenState_disabledIfConfiguredOnDevice_isDisabledForPickerState() = runTest {
- whenever(controller.isAllowedOnLockScreen).thenReturn(true)
- whenever(controller.isAbleToLaunchScannerActivity).thenReturn(false)
+ fun getPickerScreenState_disabledIfConfiguredOnDevice_isDisabledForPickerState() =
+ runTest(UnconfinedTestDispatcher()) {
+ whenever(controller.isAllowedOnLockScreen).thenReturn(true)
+ whenever(controller.isAbleToLaunchScannerActivity).thenReturn(false)
- assertThat(underTest.getPickerScreenState())
- .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice)
- }
+ assertThat(underTest.getPickerScreenState())
+ .isEqualTo(KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice)
+ }
private fun assertVisibleState(latest: KeyguardQuickAffordanceConfig.LockScreenState?) {
assertThat(latest)
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/OWNERS b/packages/SystemUI/src/com/android/systemui/media/dialog/OWNERS
index 95b8fa7..4976d94 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/OWNERS
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/OWNERS
@@ -1,3 +1,3 @@
# Bug component: 1280508
-# Files in this directory should still be reviewed by a member of SystemUI team
+asapperstein@google.com
diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
index 2c17181..bfbdc50 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
@@ -24,9 +24,9 @@
import android.os.Looper
import android.os.PatternMatcher
import android.os.UserHandle
-import androidx.test.filters.SmallTest
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger
import com.android.systemui.dump.DumpManager
@@ -40,8 +40,9 @@
import junit.framework.Assert.assertSame
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.advanceUntilIdle
-import kotlinx.coroutines.test.runBlockingTest
+import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -68,39 +69,28 @@
val DEFAULT_PERMISSION: String? = null
fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
+
const val TEST_ACTION = "TEST_ACTION"
const val TEST_SCHEME = "TEST_SCHEME"
const val TEST_PATH = "TEST_PATH"
const val TEST_TYPE = "test/type"
}
- @Mock
- private lateinit var mockContext: Context
- @Mock
- private lateinit var mockUBRUser0: UserBroadcastDispatcher
- @Mock
- private lateinit var mockUBRUser1: UserBroadcastDispatcher
- @Mock
- private lateinit var broadcastReceiver: BroadcastReceiver
- @Mock
- private lateinit var broadcastReceiverOther: BroadcastReceiver
- @Mock
- private lateinit var intentFilter: IntentFilter
- @Mock
- private lateinit var intentFilterOther: IntentFilter
- @Mock
- private lateinit var mockHandler: Handler
- @Mock
- private lateinit var logger: BroadcastDispatcherLogger
- @Mock
- private lateinit var userTracker: UserTracker
- @Mock
- private lateinit var removalPendingStore: PendingRemovalStore
+ @Mock private lateinit var mockContext: Context
+ @Mock private lateinit var mockUBRUser0: UserBroadcastDispatcher
+ @Mock private lateinit var mockUBRUser1: UserBroadcastDispatcher
+ @Mock private lateinit var broadcastReceiver: BroadcastReceiver
+ @Mock private lateinit var broadcastReceiverOther: BroadcastReceiver
+ @Mock private lateinit var intentFilter: IntentFilter
+ @Mock private lateinit var intentFilterOther: IntentFilter
+ @Mock private lateinit var mockHandler: Handler
+ @Mock private lateinit var logger: BroadcastDispatcherLogger
+ @Mock private lateinit var userTracker: UserTracker
+ @Mock private lateinit var removalPendingStore: PendingRemovalStore
private lateinit var mainExecutor: Executor
- @Captor
- private lateinit var argumentCaptor: ArgumentCaptor<ReceiverData>
+ @Captor private lateinit var argumentCaptor: ArgumentCaptor<ReceiverData>
private lateinit var testableLooper: TestableLooper
private lateinit var broadcastDispatcher: BroadcastDispatcher
@@ -112,7 +102,8 @@
mainExecutor = FakeExecutor(FakeSystemClock())
`when`(mockContext.mainExecutor).thenReturn(mainExecutor)
- broadcastDispatcher = TestBroadcastDispatcher(
+ broadcastDispatcher =
+ TestBroadcastDispatcher(
mockContext,
mainExecutor,
testableLooper.looper,
@@ -121,7 +112,8 @@
logger,
userTracker,
removalPendingStore,
- mapOf(0 to mockUBRUser0, 1 to mockUBRUser1))
+ mapOf(0 to mockUBRUser0, 1 to mockUBRUser1),
+ )
// These should be valid filters
`when`(intentFilter.countActions()).thenReturn(1)
@@ -131,10 +123,18 @@
@Test
fun testAddingReceiverToCorrectUBR() {
- broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter,
- mockHandler, user0)
broadcastDispatcher.registerReceiverWithHandler(
- broadcastReceiverOther, intentFilterOther, mockHandler, user1)
+ broadcastReceiver,
+ intentFilter,
+ mockHandler,
+ user0,
+ )
+ broadcastDispatcher.registerReceiverWithHandler(
+ broadcastReceiverOther,
+ intentFilterOther,
+ mockHandler,
+ user1,
+ )
testableLooper.processAllMessages()
@@ -152,7 +152,11 @@
fun testAddingReceiverToCorrectUBR_executor() {
broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, mainExecutor, user0)
broadcastDispatcher.registerReceiver(
- broadcastReceiverOther, intentFilterOther, mainExecutor, user1)
+ broadcastReceiverOther,
+ intentFilterOther,
+ mainExecutor,
+ user1,
+ )
testableLooper.processAllMessages()
@@ -169,7 +173,10 @@
@Test
fun testAddReceiverDefaultFlag_handler() {
broadcastDispatcher.registerReceiverWithHandler(
- broadcastReceiver, intentFilter, mockHandler)
+ broadcastReceiver,
+ intentFilter,
+ mockHandler,
+ )
testableLooper.processAllMessages()
verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG))
@@ -183,7 +190,11 @@
val flag = 3
broadcastDispatcher.registerReceiverWithHandler(
- broadcastReceiver, intentFilter, mockHandler, flags = flag)
+ broadcastReceiver,
+ intentFilter,
+ mockHandler,
+ flags = flag,
+ )
testableLooper.processAllMessages()
verify(mockUBRUser0).registerReceiver(capture(argumentCaptor), eq(flag))
@@ -212,7 +223,7 @@
broadcastReceiver,
intentFilter,
flags = flag,
- permission = permission
+ permission = permission,
)
testableLooper.processAllMessages()
@@ -250,10 +261,18 @@
@Test
fun testRemovingReceiversRemovesFromAllUBR() {
- broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter,
- mockHandler, user0)
- broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter,
- mockHandler, user1)
+ broadcastDispatcher.registerReceiverWithHandler(
+ broadcastReceiver,
+ intentFilter,
+ mockHandler,
+ user0,
+ )
+ broadcastDispatcher.registerReceiverWithHandler(
+ broadcastReceiver,
+ intentFilter,
+ mockHandler,
+ user1,
+ )
broadcastDispatcher.unregisterReceiver(broadcastReceiver)
@@ -265,10 +284,18 @@
@Test
fun testRemoveReceiverFromUser() {
- broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter,
- mockHandler, user0)
- broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter,
- mockHandler, user1)
+ broadcastDispatcher.registerReceiverWithHandler(
+ broadcastReceiver,
+ intentFilter,
+ mockHandler,
+ user0,
+ )
+ broadcastDispatcher.registerReceiverWithHandler(
+ broadcastReceiver,
+ intentFilter,
+ mockHandler,
+ user1,
+ )
broadcastDispatcher.unregisterReceiverForUser(broadcastReceiver, user0)
@@ -282,13 +309,17 @@
fun testRegisterCurrentAsActualUser() {
`when`(userTracker.userId).thenReturn(user1.identifier)
- broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter,
- mockHandler, UserHandle.CURRENT)
+ broadcastDispatcher.registerReceiverWithHandler(
+ broadcastReceiver,
+ intentFilter,
+ mockHandler,
+ UserHandle.CURRENT,
+ )
testableLooper.processAllMessages()
- verify(mockUBRUser1).registerReceiver(
- capture(argumentCaptor), eq(Context.RECEIVER_EXPORTED))
+ verify(mockUBRUser1)
+ .registerReceiver(capture(argumentCaptor), eq(Context.RECEIVER_EXPORTED))
assertSame(broadcastReceiver, argumentCaptor.value.receiver)
}
@@ -300,41 +331,38 @@
@Test(expected = IllegalArgumentException::class)
fun testFilterMustNotContainDataScheme() {
- val testFilter = IntentFilter(TEST_ACTION).apply {
- addDataScheme(TEST_SCHEME)
- }
+ val testFilter = IntentFilter(TEST_ACTION).apply { addDataScheme(TEST_SCHEME) }
broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter)
}
@Test(expected = IllegalArgumentException::class)
fun testFilterMustNotContainDataAuthority() {
- val testFilter = IntentFilter(TEST_ACTION).apply {
- addDataAuthority(mock(IntentFilter.AuthorityEntry::class.java))
- }
+ val testFilter =
+ IntentFilter(TEST_ACTION).apply {
+ addDataAuthority(mock(IntentFilter.AuthorityEntry::class.java))
+ }
broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter)
}
@Test(expected = IllegalArgumentException::class)
fun testFilterMustNotContainDataPath() {
- val testFilter = IntentFilter(TEST_ACTION).apply {
- addDataPath(TEST_PATH, PatternMatcher.PATTERN_LITERAL)
- }
+ val testFilter =
+ IntentFilter(TEST_ACTION).apply {
+ addDataPath(TEST_PATH, PatternMatcher.PATTERN_LITERAL)
+ }
broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter)
}
@Test(expected = IllegalArgumentException::class)
fun testFilterMustNotContainDataType() {
- val testFilter = IntentFilter(TEST_ACTION).apply {
- addDataType(TEST_TYPE)
- }
+ val testFilter = IntentFilter(TEST_ACTION).apply { addDataType(TEST_TYPE) }
broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter)
}
@Test(expected = IllegalArgumentException::class)
fun testFilterMustNotSetPriority() {
- val testFilter = IntentFilter(TEST_ACTION).apply {
- priority = IntentFilter.SYSTEM_HIGH_PRIORITY
- }
+ val testFilter =
+ IntentFilter(TEST_ACTION).apply { priority = IntentFilter.SYSTEM_HIGH_PRIORITY }
broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter)
}
@@ -366,12 +394,14 @@
val inOrderUser0 = inOrder(mockUBRUser0, removalPendingStore)
inOrderUser0.verify(mockUBRUser0).unregisterReceiver(broadcastReceiver)
- inOrderUser0.verify(removalPendingStore)
+ inOrderUser0
+ .verify(removalPendingStore)
.clearPendingRemoval(broadcastReceiver, UserHandle.USER_ALL)
val inOrderUser1 = inOrder(mockUBRUser1, removalPendingStore)
inOrderUser1.verify(mockUBRUser1).unregisterReceiver(broadcastReceiver)
- inOrderUser1.verify(removalPendingStore)
+ inOrderUser1
+ .verify(removalPendingStore)
.clearPendingRemoval(broadcastReceiver, UserHandle.USER_ALL)
}
@@ -385,21 +415,21 @@
val inOrderUser1 = inOrder(mockUBRUser1, removalPendingStore)
inOrderUser1.verify(mockUBRUser1).unregisterReceiver(broadcastReceiver)
- inOrderUser1.verify(removalPendingStore)
+ inOrderUser1
+ .verify(removalPendingStore)
.clearPendingRemoval(broadcastReceiver, user1.identifier)
}
@Test
- fun testBroadcastFlow() = runBlockingTest {
- val flow = broadcastDispatcher.broadcastFlow(intentFilter, user1) { intent, receiver ->
- intent to receiver
- }
+ fun testBroadcastFlow() = runTest(UnconfinedTestDispatcher()) {
+ val flow =
+ broadcastDispatcher.broadcastFlow(intentFilter, user1) { intent, receiver ->
+ intent to receiver
+ }
// Collect the values into collectedValues.
val collectedValues = mutableListOf<Pair<Intent, BroadcastReceiver>>()
- val job = launch {
- flow.collect { collectedValues.add(it) }
- }
+ val job = launch { flow.collect { collectedValues.add(it) } }
testableLooper.processAllMessages()
verify(mockUBRUser1).registerReceiver(capture(argumentCaptor), eq(DEFAULT_FLAG))
@@ -436,17 +466,18 @@
logger: BroadcastDispatcherLogger,
userTracker: UserTracker,
removalPendingStore: PendingRemovalStore,
- var mockUBRMap: Map<Int, UserBroadcastDispatcher>
- ) : BroadcastDispatcher(
- context,
- mainExecutor,
- backgroundRunningLooper,
- backgroundRunningExecutor,
- dumpManager,
- logger,
- userTracker,
- removalPendingStore
- ) {
+ var mockUBRMap: Map<Int, UserBroadcastDispatcher>,
+ ) :
+ BroadcastDispatcher(
+ context,
+ mainExecutor,
+ backgroundRunningLooper,
+ backgroundRunningExecutor,
+ dumpManager,
+ logger,
+ userTracker,
+ removalPendingStore,
+ ) {
override fun createUBRForUser(userId: Int): UserBroadcastDispatcher {
return mockUBRMap.getOrDefault(userId, mock(UserBroadcastDispatcher::class.java))
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
index 0669cb8..fceeb75 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
@@ -37,7 +37,7 @@
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.test.TestCoroutineScope
+import kotlinx.coroutines.test.TestScope
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -125,11 +125,7 @@
whenever(mainUser.identifier).thenReturn(mainUserId)
underTest = create(this)
- val initialExpectedValue =
- setUpUsers(
- count = 3,
- selectedIndex = 0,
- )
+ val initialExpectedValue = setUpUsers(count = 3, selectedIndex = 0)
var userInfos: List<UserInfo>? = null
var selectedUserInfo: UserInfo? = null
underTest.userInfos.onEach { userInfos = it }.launchIn(this)
@@ -140,23 +136,14 @@
assertThat(selectedUserInfo).isEqualTo(initialExpectedValue[0])
assertThat(underTest.lastSelectedNonGuestUserId).isEqualTo(selectedUserInfo?.id)
- val secondExpectedValue =
- setUpUsers(
- count = 4,
- selectedIndex = 1,
- )
+ val secondExpectedValue = setUpUsers(count = 4, selectedIndex = 1)
underTest.refreshUsers()
assertThat(userInfos).isEqualTo(secondExpectedValue)
assertThat(selectedUserInfo).isEqualTo(secondExpectedValue[1])
assertThat(underTest.lastSelectedNonGuestUserId).isEqualTo(selectedUserInfo?.id)
val selectedNonGuestUserId = selectedUserInfo?.id
- val thirdExpectedValue =
- setUpUsers(
- count = 2,
- isLastGuestUser = true,
- selectedIndex = 1,
- )
+ val thirdExpectedValue = setUpUsers(count = 2, isLastGuestUser = true, selectedIndex = 1)
underTest.refreshUsers()
assertThat(userInfos).isEqualTo(thirdExpectedValue)
assertThat(selectedUserInfo).isEqualTo(thirdExpectedValue[1])
@@ -168,12 +155,7 @@
@Test
fun refreshUsers_sortsByCreationTime_guestUserLast() = runSelfCancelingTest {
underTest = create(this)
- val unsortedUsers =
- setUpUsers(
- count = 3,
- selectedIndex = 0,
- isLastGuestUser = true,
- )
+ val unsortedUsers = setUpUsers(count = 3, selectedIndex = 0, isLastGuestUser = true)
unsortedUsers[0].creationTime = 999
unsortedUsers[1].creationTime = 900
unsortedUsers[2].creationTime = 950
@@ -197,30 +179,22 @@
): List<UserInfo> {
val userInfos =
(0 until count).map { index ->
- createUserInfo(
- index,
- isGuest = isLastGuestUser && index == count - 1,
- )
+ createUserInfo(index, isGuest = isLastGuestUser && index == count - 1)
}
whenever(manager.aliveUsers).thenReturn(userInfos)
tracker.set(userInfos, selectedIndex)
return userInfos
}
+
@Test
fun userTrackerCallback_updatesSelectedUserInfo() = runSelfCancelingTest {
underTest = create(this)
var selectedUserInfo: UserInfo? = null
underTest.selectedUserInfo.onEach { selectedUserInfo = it }.launchIn(this)
- setUpUsers(
- count = 2,
- selectedIndex = 0,
- )
+ setUpUsers(count = 2, selectedIndex = 0)
tracker.onProfileChanged()
assertThat(selectedUserInfo?.id).isEqualTo(0)
- setUpUsers(
- count = 2,
- selectedIndex = 1,
- )
+ setUpUsers(count = 2, selectedIndex = 1)
tracker.onProfileChanged()
assertThat(selectedUserInfo?.id).isEqualTo(1)
}
@@ -259,10 +233,7 @@
assertThat(selectedUser!!.selectionStatus).isEqualTo(SelectionStatus.SELECTION_IN_PROGRESS)
}
- private fun createUserInfo(
- id: Int,
- isGuest: Boolean,
- ): UserInfo {
+ private fun createUserInfo(id: Int, isGuest: Boolean): UserInfo {
val flags = 0
return UserInfo(
id,
@@ -312,16 +283,14 @@
* Executes the given block of execution within the scope of a dedicated [CoroutineScope] which
* is then automatically canceled and cleaned-up.
*/
- private fun runSelfCancelingTest(
- block: suspend CoroutineScope.() -> Unit,
- ) =
+ private fun runSelfCancelingTest(block: suspend CoroutineScope.() -> Unit) =
runBlocking(Dispatchers.Main.immediate) {
val scope = CoroutineScope(coroutineContext + Job())
block(scope)
scope.cancel()
}
- private fun create(scope: CoroutineScope = TestCoroutineScope()): UserRepositoryImpl {
+ private fun create(scope: CoroutineScope = TestScope()): UserRepositoryImpl {
return UserRepositoryImpl(
appContext = context,
manager = manager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt
index 01795e9..670c84d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/GuestUserInteractorTest.kt
@@ -27,6 +27,7 @@
import com.android.systemui.GuestResetOrExitSessionReceiver
import com.android.systemui.GuestResumeSessionReceiver
import com.android.systemui.SysuiTestCase
+import com.android.systemui.kosmos.testScope
import com.android.systemui.statusbar.policy.DeviceProvisionedController
import com.android.systemui.user.data.repository.FakeUserRepository
import com.android.systemui.user.domain.model.ShowDialogRequestModel
@@ -34,8 +35,9 @@
import com.android.systemui.util.mockito.kotlinArgumentCaptor
import com.android.systemui.util.mockito.whenever
import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.runBlocking
-import kotlinx.coroutines.test.TestCoroutineScope
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -62,9 +64,10 @@
@Mock private lateinit var resetOrExitSessionReceiver: GuestResetOrExitSessionReceiver
@Mock private lateinit var otherContext: Context
+ private val testDispatcher = UnconfinedTestDispatcher()
+ private val testScope = TestScope(testDispatcher)
private lateinit var underTest: GuestUserInteractor
- private lateinit var scope: TestCoroutineScope
private lateinit var repository: FakeUserRepository
@Before
@@ -72,7 +75,6 @@
MockitoAnnotations.initMocks(this)
whenever(manager.createGuest(any())).thenReturn(GUEST_USER_INFO)
- scope = TestCoroutineScope()
repository = FakeUserRepository()
repository.setUserInfos(ALL_USERS)
@@ -82,17 +84,17 @@
private fun initGuestUserInteractor(context: Context) =
GuestUserInteractor(
applicationContext = context,
- applicationScope = scope,
- mainDispatcher = IMMEDIATE,
- backgroundDispatcher = IMMEDIATE,
+ applicationScope = testScope,
+ mainDispatcher = testDispatcher,
+ backgroundDispatcher = testDispatcher,
manager = manager,
repository = repository,
deviceProvisionedController = deviceProvisionedController,
devicePolicyManager = devicePolicyManager,
refreshUsersScheduler =
RefreshUsersScheduler(
- applicationScope = scope,
- mainDispatcher = IMMEDIATE,
+ applicationScope = testScope,
+ mainDispatcher = testDispatcher,
repository = repository,
),
uiEventLogger = uiEventLogger,
@@ -118,7 +120,7 @@
@Test
fun onDeviceBootCompleted_allowedToAdd_createGuest() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
setAllowedToAdd()
underTest.onDeviceBootCompleted()
@@ -129,7 +131,7 @@
@Test
fun onDeviceBootCompleted_awaitProvisioning_andCreateGuest() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
setAllowedToAdd(isAllowed = false)
underTest.onDeviceBootCompleted()
val captor =
@@ -145,7 +147,7 @@
@Test
fun createAndSwitchTo() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
underTest.createAndSwitchTo(
showDialog = showDialog,
dismissDialog = dismissDialog,
@@ -160,7 +162,7 @@
@Test
fun createAndSwitchTo_failsToCreate_doesNotSwitchTo() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
whenever(manager.createGuest(any())).thenReturn(null)
underTest.createAndSwitchTo(
@@ -177,7 +179,7 @@
@Test
fun exit_returnsToTargetUser() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
repository.setSelectedUserInfo(GUEST_USER_INFO)
val targetUserId = NON_GUEST_USER_INFO.id
@@ -197,7 +199,7 @@
@Test
fun exit_returnsToLastNonGuest() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
val expectedUserId = NON_GUEST_USER_INFO.id
whenever(manager.getUserInfo(expectedUserId)).thenReturn(NON_GUEST_USER_INFO)
repository.lastSelectedNonGuestUserId = expectedUserId
@@ -219,7 +221,7 @@
@Test
fun exit_lastNonGuestWasRemoved_returnsToMainUser() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
val removedUserId = 310
val mainUserId = 10
repository.lastSelectedNonGuestUserId = removedUserId
@@ -242,7 +244,7 @@
@Test
fun exit_guestWasEphemeral_itIsRemoved() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
whenever(manager.markGuestForDeletion(anyInt())).thenReturn(true)
repository.setUserInfos(listOf(NON_GUEST_USER_INFO, EPHEMERAL_GUEST_USER_INFO))
repository.setSelectedUserInfo(EPHEMERAL_GUEST_USER_INFO)
@@ -265,7 +267,7 @@
@Test
fun exit_forceRemoveGuest_itIsRemoved() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
whenever(manager.markGuestForDeletion(anyInt())).thenReturn(true)
repository.setSelectedUserInfo(GUEST_USER_INFO)
val targetUserId = NON_GUEST_USER_INFO.id
@@ -287,7 +289,7 @@
@Test
fun exit_selectedDifferentFromGuestUser_doNothing() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
repository.setSelectedUserInfo(NON_GUEST_USER_INFO)
underTest.exit(
@@ -304,7 +306,7 @@
@Test
fun exit_selectedIsActuallyNotAguestUser_doNothing() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
repository.setSelectedUserInfo(NON_GUEST_USER_INFO)
underTest.exit(
@@ -321,7 +323,7 @@
@Test
fun remove_returnsToTargetUser() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
whenever(manager.markGuestForDeletion(anyInt())).thenReturn(true)
repository.setSelectedUserInfo(GUEST_USER_INFO)
@@ -342,7 +344,7 @@
@Test
fun remove_selectedDifferentFromGuestUser_doNothing() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
whenever(manager.markGuestForDeletion(anyInt())).thenReturn(true)
repository.setSelectedUserInfo(NON_GUEST_USER_INFO)
@@ -359,7 +361,7 @@
@Test
fun remove_selectedIsActuallyNotAguestUser_doNothing() =
- runBlocking(IMMEDIATE) {
+ testScope.runTest {
whenever(manager.markGuestForDeletion(anyInt())).thenReturn(true)
repository.setSelectedUserInfo(NON_GUEST_USER_INFO)
@@ -395,11 +397,7 @@
companion object {
private val IMMEDIATE = Dispatchers.Main.immediate
private val NON_GUEST_USER_INFO =
- UserInfo(
- /* id= */ 818,
- /* name= */ "non_guest",
- /* flags= */ UserInfo.FLAG_FULL,
- )
+ UserInfo(/* id= */ 818, /* name= */ "non_guest", /* flags= */ UserInfo.FLAG_FULL)
private val GUEST_USER_INFO =
UserInfo(
/* id= */ 669,
@@ -416,10 +414,6 @@
/* flags= */ UserInfo.FLAG_EPHEMERAL or UserInfo.FLAG_FULL,
UserManager.USER_TYPE_FULL_GUEST,
)
- private val ALL_USERS =
- listOf(
- NON_GUEST_USER_INFO,
- GUEST_USER_INFO,
- )
+ private val ALL_USERS = listOf(NON_GUEST_USER_INFO, GUEST_USER_INFO)
}
}
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index d9926a4..674e149 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -1849,15 +1849,19 @@
bootMitigationCounts.put(observer.name, observer.getBootMitigationCount());
}
+ FileOutputStream fileStream = null;
+ ObjectOutputStream objectStream = null;
try {
- FileOutputStream fileStream = new FileOutputStream(new File(filePath));
- ObjectOutputStream objectStream = new ObjectOutputStream(fileStream);
+ fileStream = new FileOutputStream(new File(filePath));
+ objectStream = new ObjectOutputStream(fileStream);
objectStream.writeObject(bootMitigationCounts);
objectStream.flush();
- objectStream.close();
- fileStream.close();
} catch (Exception e) {
Slog.i(TAG, "Could not save observers metadata to file: " + e);
+ return;
+ } finally {
+ IoUtils.closeQuietly(objectStream);
+ IoUtils.closeQuietly(fileStream);
}
}
@@ -2008,23 +2012,32 @@
void readAllObserversBootMitigationCountIfNecessary(String filePath) {
File metadataFile = new File(filePath);
if (metadataFile.exists()) {
+ FileInputStream fileStream = null;
+ ObjectInputStream objectStream = null;
+ HashMap<String, Integer> bootMitigationCounts = null;
try {
- FileInputStream fileStream = new FileInputStream(metadataFile);
- ObjectInputStream objectStream = new ObjectInputStream(fileStream);
- HashMap<String, Integer> bootMitigationCounts =
+ fileStream = new FileInputStream(metadataFile);
+ objectStream = new ObjectInputStream(fileStream);
+ bootMitigationCounts =
(HashMap<String, Integer>) objectStream.readObject();
- objectStream.close();
- fileStream.close();
-
- for (int i = 0; i < mAllObservers.size(); i++) {
- final ObserverInternal observer = mAllObservers.valueAt(i);
- if (bootMitigationCounts.containsKey(observer.name)) {
- observer.setBootMitigationCount(
- bootMitigationCounts.get(observer.name));
- }
- }
} catch (Exception e) {
Slog.i(TAG, "Could not read observer metadata file: " + e);
+ return;
+ } finally {
+ IoUtils.closeQuietly(objectStream);
+ IoUtils.closeQuietly(fileStream);
+ }
+
+ if (bootMitigationCounts == null || bootMitigationCounts.isEmpty()) {
+ Slog.i(TAG, "No observer in metadata file");
+ return;
+ }
+ for (int i = 0; i < mAllObservers.size(); i++) {
+ final ObserverInternal observer = mAllObservers.valueAt(i);
+ if (bootMitigationCounts.containsKey(observer.name)) {
+ observer.setBootMitigationCount(
+ bootMitigationCounts.get(observer.name));
+ }
}
}
}
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index f79256d..c4a787d 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -39,6 +39,7 @@
import android.aconfigd.Aconfigd.StorageReturnMessage;
import android.aconfigd.Aconfigd.StorageReturnMessages;
import static com.android.aconfig_new_storage.Flags.enableAconfigStorageDaemon;
+import static com.android.aconfig_new_storage.Flags.enableAconfigdFromMainline;
import java.io.DataInputStream;
import java.io.DataOutputStream;
@@ -388,16 +389,38 @@
* @param requests: request proto output stream
* @return aconfigd socket return as proto input stream
*/
- static ProtoInputStream sendAconfigdRequests(ProtoOutputStream requests) {
+ static void sendAconfigdRequests(ProtoOutputStream requests) {
+ ProtoInputStream returns = sendAconfigdRequests("aconfigd_system", requests);
+ try {
+ parseAndLogAconfigdReturn(returns);
+ } catch (IOException ioe) {
+ logErr("failed to parse aconfigd return", ioe);
+ }
+ if (enableAconfigdFromMainline()) {
+ returns = sendAconfigdRequests("aconfigd_mainline", requests);
+ try {
+ parseAndLogAconfigdReturn(returns);
+ } catch (IOException ioe) {
+ logErr("failed to parse aconfigd return", ioe);
+ }
+ }
+ }
+
+ /**
+ * apply flag local override in aconfig new storage
+ * @param socketName: the socket to send to
+ * @param requests: request proto output stream
+ * @return aconfigd socket return as proto input stream
+ */
+ static ProtoInputStream sendAconfigdRequests(String socketName, ProtoOutputStream requests) {
// connect to aconfigd socket
LocalSocket client = new LocalSocket();
- String socketName = "aconfigd_system";
try {
client.connect(new LocalSocketAddress(
socketName, LocalSocketAddress.Namespace.RESERVED));
- Slog.d(TAG, "connected to aconfigd socket");
+ Slog.d(TAG, "connected to " + socketName + " socket");
} catch (IOException ioe) {
- logErr("failed to connect to aconfigd socket", ioe);
+ logErr("failed to connect to " + socketName + " socket", ioe);
return null;
}
@@ -416,9 +439,9 @@
byte[] requests_bytes = requests.getBytes();
outputStream.writeInt(requests_bytes.length);
outputStream.write(requests_bytes, 0, requests_bytes.length);
- Slog.d(TAG, "flag override requests sent to aconfigd");
+ Slog.d(TAG, "flag override requests sent to " + socketName);
} catch (IOException ioe) {
- logErr("failed to send requests to aconfigd", ioe);
+ logErr("failed to send requests to " + socketName, ioe);
return null;
}
@@ -426,10 +449,10 @@
try {
int num_bytes = inputStream.readInt();
ProtoInputStream returns = new ProtoInputStream(inputStream);
- Slog.d(TAG, "received " + num_bytes + " bytes back from aconfigd");
+ Slog.d(TAG, "received " + num_bytes + " bytes back from " + socketName);
return returns;
} catch (IOException ioe) {
- logErr("failed to read requests return from aconfigd", ioe);
+ logErr("failed to read requests return from " + socketName, ioe);
return null;
}
}
@@ -524,15 +547,8 @@
return;
}
- // send requests to aconfigd and obtain the return byte buffer
- ProtoInputStream returns = sendAconfigdRequests(requests);
-
- // deserialize back using proto input stream
- try {
- parseAndLogAconfigdReturn(returns);
- } catch (IOException ioe) {
- logErr("failed to parse aconfigd return", ioe);
- }
+ // send requests to aconfigd
+ sendAconfigdRequests(requests);
}
public static SettingsToPropertiesMapper start(ContentResolver contentResolver) {
@@ -642,15 +658,8 @@
return;
}
- // send requests to aconfigd and obtain the return
- ProtoInputStream returns = sendAconfigdRequests(requests);
-
- // deserialize back using proto input stream
- try {
- parseAndLogAconfigdReturn(returns);
- } catch (IOException ioe) {
- logErr("failed to parse aconfigd return", ioe);
- }
+ // send requests to aconfigd
+ sendAconfigdRequests(requests);
}
/**
diff --git a/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java b/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java
index 1208b6ef..08ceb61 100644
--- a/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java
+++ b/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java
@@ -142,6 +142,8 @@
/** Used by {@link ActivityRecord#dump}. */
@Override
public String toString() {
- return String.valueOf(mConnections);
+ synchronized (mActivity) {
+ return String.valueOf(mConnections);
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index aaa7f12..b278274 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8010,42 +8010,45 @@
@Override
public void waitForAllWindowsDrawn(Message message, long timeout, int displayId) {
Objects.requireNonNull(message.getTarget());
- final WindowContainer<?> container = displayId == INVALID_DISPLAY
- ? mRoot : mRoot.getDisplayContent(displayId);
- if (container == null) {
- // The waiting container doesn't exist, no need to wait to run the callback. Run and
- // return;
- message.sendToTarget();
- return;
- }
boolean allWindowsDrawn = false;
synchronized (mGlobalLock) {
- if (mRoot.getDefaultDisplay().mDisplayUpdater.waitForTransition(message)) {
- // Use the ready-to-play of transition as the signal.
- return;
- }
- container.waitForAllWindowsDrawn();
- mWindowPlacerLocked.requestTraversal();
- mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, container);
- if (container.mWaitingForDrawn.isEmpty()) {
- allWindowsDrawn = true;
- } else {
- if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
- for (int i = 0; i < container.mWaitingForDrawn.size(); i++) {
- traceStartWaitingForWindowDrawn(container.mWaitingForDrawn.get(i));
- }
- }
-
- mWaitingForDrawnCallbacks.put(container, message);
- mH.sendNewMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, container, timeout);
- checkDrawnWindowsLocked();
- }
+ allWindowsDrawn = waitForAllWindowsDrawnLocked(message, timeout, displayId);
}
if (allWindowsDrawn) {
message.sendToTarget();
}
}
+ /** Return {@code true} if all windows have been drawn. */
+ private boolean waitForAllWindowsDrawnLocked(Message message, long timeout, int displayId) {
+ final WindowContainer<?> container = displayId == INVALID_DISPLAY
+ ? mRoot : mRoot.getDisplayContent(displayId);
+ if (container == null) {
+ // The waiting container doesn't exist, no need to wait. Treat as drawn.
+ return true;
+ }
+ if (mRoot.getDefaultDisplay().mDisplayUpdater.waitForTransition(message)) {
+ // Use the ready-to-play of transition as the signal.
+ return false;
+ }
+ container.waitForAllWindowsDrawn();
+ mWindowPlacerLocked.requestTraversal();
+ mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, container);
+ if (container.mWaitingForDrawn.isEmpty()) {
+ return true;
+ }
+ if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
+ for (int i = 0; i < container.mWaitingForDrawn.size(); i++) {
+ traceStartWaitingForWindowDrawn(container.mWaitingForDrawn.get(i));
+ }
+ }
+
+ mWaitingForDrawnCallbacks.put(container, message);
+ mH.sendNewMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, container, timeout);
+ checkDrawnWindowsLocked();
+ return false;
+ }
+
@Override
public void setForcedDisplaySize(int displayId, int width, int height) {
WindowManagerService.this.setForcedDisplaySize(displayId, width, height);
diff --git a/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesMetadataProcessor.kt b/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesMetadataProcessor.kt
index 100d869..4a6d4b1 100644
--- a/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesMetadataProcessor.kt
+++ b/tools/systemfeatures/src/com/android/systemfeatures/SystemFeaturesMetadataProcessor.kt
@@ -17,8 +17,10 @@
package com.android.systemfeatures
import android.annotation.SdkConstant
+import com.squareup.javapoet.ClassName
import com.squareup.javapoet.FieldSpec
import com.squareup.javapoet.JavaFile
+import com.squareup.javapoet.MethodSpec
import com.squareup.javapoet.TypeSpec
import java.io.IOException
import javax.annotation.processing.AbstractProcessor
@@ -27,6 +29,7 @@
import javax.lang.model.SourceVersion
import javax.lang.model.element.Modifier
import javax.lang.model.element.TypeElement
+import javax.lang.model.element.VariableElement
import javax.tools.Diagnostic
/*
@@ -35,7 +38,16 @@
* <p>The output is a single class file, `com.android.internal.pm.SystemFeaturesMetadata`, with
* properties computed from feature constant definitions in the PackageManager class. This
* class is only produced if the processed environment includes PackageManager; all other
- * invocations are ignored.
+ * invocations are ignored. The generated API is as follows:
+ *
+ * <pre>
+ * package android.content.pm;
+ * public final class SystemFeaturesMetadata {
+ * public static final int SDK_FEATURE_COUNT;
+ * // @return [0, SDK_FEATURE_COUNT) if an SDK-defined system feature, -1 otherwise.
+ * public static int maybeGetSdkFeatureIndex(String featureName);
+ * }
+ * </pre>
*/
class SystemFeaturesMetadataProcessor : AbstractProcessor() {
@@ -56,19 +68,31 @@
return false
}
- // We're only interested in feature constants defined in PackageManager.
- var featureCount = 0
- roundEnv.getElementsAnnotatedWith(SdkConstant::class.java).forEach {
- if (
- it.enclosingElement == packageManagerType &&
- it.getAnnotation(SdkConstant::class.java).value ==
- SdkConstant.SdkConstantType.FEATURE
- ) {
- featureCount++
- }
- }
+ // Collect all FEATURE-annotated fields from PackageManager, and
+ // 1) Use the field values to de-duplicate, as there can be multiple FEATURE_* fields that
+ // map to the same feature string name value.
+ // 2) Ensure they're sorted to ensure consistency and determinism between builds.
+ val featureVarNames =
+ roundEnv
+ .getElementsAnnotatedWith(SdkConstant::class.java)
+ .asSequence()
+ .filter {
+ it.enclosingElement == packageManagerType &&
+ it.getAnnotation(SdkConstant::class.java).value ==
+ SdkConstant.SdkConstantType.FEATURE
+ }
+ .mapNotNull { element ->
+ (element as? VariableElement)?.let { varElement ->
+ varElement.getConstantValue()?.toString() to
+ varElement.simpleName.toString()
+ }
+ }
+ .toMap()
+ .values
+ .sorted()
+ .toList()
- if (featureCount == 0) {
+ if (featureVarNames.isEmpty()) {
// This is fine, and happens for any environment that doesn't include PackageManager.
return false
}
@@ -77,16 +101,8 @@
TypeSpec.classBuilder("SystemFeaturesMetadata")
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addJavadoc("@hide")
- .addField(
- FieldSpec.builder(Int::class.java, "SDK_FEATURE_COUNT")
- .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
- .addJavadoc(
- "The number of `@SdkConstant` features defined in PackageManager."
- )
- .addJavadoc("@hide")
- .initializer("\$L", featureCount)
- .build()
- )
+ .addField(buildFeatureCount(featureVarNames))
+ .addMethod(buildFeatureIndexLookup(featureVarNames))
.build()
try {
@@ -104,7 +120,41 @@
return true
}
+ private fun buildFeatureCount(featureVarNames: Collection<String>): FieldSpec {
+ return FieldSpec.builder(Int::class.java, "SDK_FEATURE_COUNT")
+ .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
+ .addJavadoc(
+ "# of {@link android.annotation.SdkConstant}` features defined in PackageManager."
+ )
+ .addJavadoc("\n\n@hide")
+ .initializer("\$L", featureVarNames.size)
+ .build()
+ }
+
+ private fun buildFeatureIndexLookup(featureVarNames: Collection<String>): MethodSpec {
+ val methodBuilder =
+ MethodSpec.methodBuilder("maybeGetSdkFeatureIndex")
+ .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
+ .addJavadoc("@return an index in [0, SDK_FEATURE_COUNT) for features defined ")
+ .addJavadoc("in PackageManager, else -1.")
+ .addJavadoc("\n\n@hide")
+ .returns(Int::class.java)
+ .addParameter(String::class.java, "featureName")
+ methodBuilder.beginControlFlow("switch (featureName)")
+ featureVarNames.forEachIndexed { index, featureVarName ->
+ methodBuilder
+ .addCode("case \$T.\$N: ", PACKAGEMANAGER_CLASS, featureVarName)
+ .addStatement("return \$L", index)
+ }
+ methodBuilder
+ .addCode("default: ")
+ .addStatement("return -1")
+ .endControlFlow()
+ return methodBuilder.build()
+ }
+
companion object {
private val SDK_CONSTANT_ANNOTATION_NAME = SdkConstant::class.qualifiedName
+ private val PACKAGEMANAGER_CLASS = ClassName.get("android.content.pm", "PackageManager")
}
}
diff --git a/tools/systemfeatures/tests/src/SystemFeaturesMetadataProcessorTest.java b/tools/systemfeatures/tests/src/SystemFeaturesMetadataProcessorTest.java
index 4ffb5b9..74ce6da 100644
--- a/tools/systemfeatures/tests/src/SystemFeaturesMetadataProcessorTest.java
+++ b/tools/systemfeatures/tests/src/SystemFeaturesMetadataProcessorTest.java
@@ -16,10 +16,16 @@
package com.android.systemfeatures;
+import static com.android.internal.pm.SystemFeaturesMetadata.maybeGetSdkFeatureIndex;
+
import static com.google.common.truth.Truth.assertThat;
+import android.content.pm.PackageManager;
+
import com.android.internal.pm.SystemFeaturesMetadata;
+import com.google.common.collect.Range;
+
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -33,4 +39,17 @@
// It defines 5 annotated features, and any/all other constants should be ignored.
assertThat(SystemFeaturesMetadata.SDK_FEATURE_COUNT).isEqualTo(5);
}
+
+ @Test
+ public void testSdkFeatureIndex() {
+ // Only SDK-defined features return valid indices.
+ final Range validIndexRange = Range.closedOpen(0, SystemFeaturesMetadata.SDK_FEATURE_COUNT);
+ assertThat(maybeGetSdkFeatureIndex(PackageManager.FEATURE_PC)).isIn(validIndexRange);
+ assertThat(maybeGetSdkFeatureIndex(PackageManager.FEATURE_VULKAN)).isIn(validIndexRange);
+ assertThat(maybeGetSdkFeatureIndex(PackageManager.FEATURE_NOT_ANNOTATED)).isEqualTo(-1);
+ assertThat(maybeGetSdkFeatureIndex(PackageManager.NOT_FEATURE)).isEqualTo(-1);
+ assertThat(maybeGetSdkFeatureIndex("foo")).isEqualTo(-1);
+ assertThat(maybeGetSdkFeatureIndex("0")).isEqualTo(-1);
+ assertThat(maybeGetSdkFeatureIndex("")).isEqualTo(-1);
+ }
}