summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/hid/Android.bp2
-rw-r--r--cmds/uinput/Android.bp2
-rw-r--r--core/api/current.txt6
-rw-r--r--core/java/android/app/ActivityThread.java2
-rw-r--r--core/java/android/app/AppOpsManager.java11
-rw-r--r--core/java/android/app/admin/SecurityLog.java17
-rw-r--r--core/java/android/app/admin/SecurityLogTags.logtags4
-rw-r--r--core/java/android/app/admin/flags/flags.aconfig2
-rw-r--r--core/java/android/app/appfunctions/OWNERS1
-rw-r--r--core/java/android/hardware/OWNERS3
-rw-r--r--core/java/android/net/vcn/VcnTransportInfo.java43
-rw-r--r--core/java/android/net/vcn/VcnUtils.java97
-rw-r--r--core/java/android/os/BinderProxy.java5
-rw-r--r--core/java/android/security/flags.aconfig7
-rw-r--r--core/jni/OWNERS1
-rw-r--r--core/jni/android_media_AudioFormat.h5
-rw-r--r--core/res/res/values/config.xml5
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java4
-rw-r--r--keystore/OWNERS3
-rw-r--r--libs/hwui/AutoBackendTextureRelease.cpp7
-rw-r--r--media/java/android/media/AudioFormat.java23
-rw-r--r--media/java/android/media/AudioSystem.java2
-rw-r--r--media/java/android/media/session/PlaybackState.java44
-rw-r--r--nfc/Android.bp4
-rw-r--r--nfc/api/current.txt1
-rw-r--r--nfc/api/system-current.txt14
-rw-r--r--nfc/java/android/nfc/INfcCardEmulation.aidl4
-rw-r--r--nfc/java/android/nfc/INfcOemExtensionCallback.aidl9
-rw-r--r--nfc/java/android/nfc/NfcOemExtension.java232
-rw-r--r--nfc/java/android/nfc/RoutingStatus.java79
-rw-r--r--nfc/java/android/nfc/cardemulation/CardEmulation.java114
-rw-r--r--nfc/java/android/nfc/flags.aconfig8
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/Utils.java14
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java6
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java40
-rw-r--r--ravenwood/TEST_MAPPING3
-rw-r--r--ravenwood/runtime-common-src/com/android/ravenwood/common/RavenwoodCommonUtils.java5
-rw-r--r--ravenwood/runtime-helper-src/libcore-fake/libcore/util/NativeAllocationRegistry.java11
-rw-r--r--ravenwood/tests/coretest/test/com/android/ravenwoodtest/coretest/RavenwoodMockitoTest.java15
-rw-r--r--ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt2
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiEarcController.java20
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java98
-rw-r--r--services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java16
-rw-r--r--services/core/java/com/android/server/pm/ApexManager.java14
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java8
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java15
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/OWNERS1
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java44
-rw-r--r--tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/OWNERS (renamed from tests/FlickerTests/ActivityEmbedding/OWNERS)0
-rw-r--r--tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/OWNERS1
-rw-r--r--tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/OWNERS1
-rw-r--r--tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OWNERS1
-rw-r--r--tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/OWNERS1
-rw-r--r--tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/OWNERS1
-rw-r--r--tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rtl/OWNERS1
-rw-r--r--tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/OWNERS1
-rw-r--r--tests/Internal/src/com/android/internal/os/OWNERS2
-rw-r--r--tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java23
-rw-r--r--tests/vcn/java/android/net/vcn/VcnUtilsTest.java136
63 files changed, 1088 insertions, 184 deletions
diff --git a/cmds/hid/Android.bp b/cmds/hid/Android.bp
index a6e27698e36c..b93227a60d99 100644
--- a/cmds/hid/Android.bp
+++ b/cmds/hid/Android.bp
@@ -22,5 +22,5 @@ java_binary {
name: "hid",
wrapper: "hid.sh",
srcs: ["**/*.java"],
- required: ["libhidcommand_jni"],
+ jni_libs: ["libhidcommand_jni"],
}
diff --git a/cmds/uinput/Android.bp b/cmds/uinput/Android.bp
index da497dcf908e..cec8a0d88b99 100644
--- a/cmds/uinput/Android.bp
+++ b/cmds/uinput/Android.bp
@@ -25,7 +25,7 @@ java_binary {
"src/**/*.java",
":uinputcommand_aidl",
],
- required: ["libuinputcommand_jni"],
+ jni_libs: ["libuinputcommand_jni"],
}
filegroup {
diff --git a/core/api/current.txt b/core/api/current.txt
index 9881a90ff003..ce373d0cde38 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -8596,7 +8596,7 @@ package android.app.admin {
field public static final int TAG_ADB_SHELL_CMD = 210002; // 0x33452
field public static final int TAG_ADB_SHELL_INTERACTIVE = 210001; // 0x33451
field public static final int TAG_APP_PROCESS_START = 210005; // 0x33455
- field @FlaggedApi("android.app.admin.flags.backup_service_security_log_event_enabled") public static final int TAG_BACKUP_SERVICE_TOGGLED = 210044; // 0x3347c
+ field public static final int TAG_BACKUP_SERVICE_TOGGLED = 210044; // 0x3347c
field public static final int TAG_BLUETOOTH_CONNECTION = 210039; // 0x33477
field public static final int TAG_BLUETOOTH_DISCONNECTION = 210040; // 0x33478
field public static final int TAG_CAMERA_POLICY_SET = 210034; // 0x33472
@@ -8619,6 +8619,8 @@ package android.app.admin {
field public static final int TAG_MAX_SCREEN_LOCK_TIMEOUT_SET = 210019; // 0x33463
field public static final int TAG_MEDIA_MOUNT = 210013; // 0x3345d
field public static final int TAG_MEDIA_UNMOUNT = 210014; // 0x3345e
+ field @FlaggedApi("android.nfc.nfc_state_change_security_log_event_enabled") public static final int TAG_NFC_DISABLED = 210046; // 0x3347e
+ field @FlaggedApi("android.nfc.nfc_state_change_security_log_event_enabled") public static final int TAG_NFC_ENABLED = 210045; // 0x3347d
field public static final int TAG_OS_SHUTDOWN = 210010; // 0x3345a
field public static final int TAG_OS_STARTUP = 210009; // 0x33459
field public static final int TAG_PACKAGE_INSTALLED = 210041; // 0x33479
@@ -21308,6 +21310,7 @@ package android.media {
field public static final int ENCODING_AAC_XHE = 16; // 0x10
field public static final int ENCODING_AC3 = 5; // 0x5
field public static final int ENCODING_AC4 = 17; // 0x11
+ field @FlaggedApi("android.media.audio.dolby_ac4_level4_encoding_api") public static final int ENCODING_AC4_L4 = 32; // 0x20
field public static final int ENCODING_DEFAULT = 1; // 0x1
field public static final int ENCODING_DOLBY_MAT = 19; // 0x13
field public static final int ENCODING_DOLBY_TRUEHD = 14; // 0xe
@@ -26811,7 +26814,6 @@ package android.media.session {
field public static final int STATE_FAST_FORWARDING = 4; // 0x4
field public static final int STATE_NONE = 0; // 0x0
field public static final int STATE_PAUSED = 2; // 0x2
- field @FlaggedApi("com.android.media.flags.enable_notifying_activity_manager_with_media_session_status_change") public static final int STATE_PLAYBACK_SUPPRESSED = 12; // 0xc
field public static final int STATE_PLAYING = 3; // 0x3
field public static final int STATE_REWINDING = 5; // 0x5
field public static final int STATE_SKIPPING_TO_NEXT = 10; // 0xa
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index b384326201fc..eb742faa5835 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -6188,7 +6188,7 @@ public final class ActivityThread extends ClientTransactionHandler
}
r.activity.mConfigChangeFlags |= configChanges;
- r.mPreserveWindow = tmp.mPreserveWindow;
+ r.mPreserveWindow = r.activity.mWindowAdded && tmp.mPreserveWindow;
r.activity.mChangingConfigurations = true;
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 5214d2c9c02a..091d5ab8534d 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -10193,6 +10193,9 @@ public class AppOpsManager {
}
p.writeInt(Parcel.EX_HAS_NOTED_APPOPS_REPLY_HEADER);
+ final int sizePosition = p.dataPosition();
+ // Write size placeholder. With this size we can easily skip it in native.
+ p.writeInt(0);
int numAttributionWithNotesAppOps = notedAppOps.size();
p.writeInt(numAttributionWithNotesAppOps);
@@ -10209,6 +10212,12 @@ public class AppOpsManager {
}
}
}
+
+ final int payloadPosition = p.dataPosition();
+ p.setDataPosition(sizePosition);
+ // Total header size including 4 bytes size itself.
+ p.writeInt(payloadPosition - sizePosition);
+ p.setDataPosition(payloadPosition);
}
/**
@@ -10222,6 +10231,8 @@ public class AppOpsManager {
* @hide
*/
public static void readAndLogNotedAppops(@NonNull Parcel p) {
+ // Skip size.
+ p.readInt();
int numAttributionsWithNotedAppOps = p.readInt();
for (int i = 0; i < numAttributionsWithNotedAppOps; i++) {
diff --git a/core/java/android/app/admin/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java
index 477f2e007b33..eb0ea1e6ef4f 100644
--- a/core/java/android/app/admin/SecurityLog.java
+++ b/core/java/android/app/admin/SecurityLog.java
@@ -16,7 +16,7 @@
package android.app.admin;
-import static android.app.admin.flags.Flags.FLAG_BACKUP_SERVICE_SECURITY_LOG_EVENT_ENABLED;
+import static android.nfc.Flags.FLAG_NFC_STATE_CHANGE_SECURITY_LOG_EVENT_ENABLED;
import android.Manifest;
import android.annotation.FlaggedApi;
@@ -103,6 +103,8 @@ public class SecurityLog {
TAG_PACKAGE_UPDATED,
TAG_PACKAGE_UNINSTALLED,
TAG_BACKUP_SERVICE_TOGGLED,
+ TAG_NFC_ENABLED,
+ TAG_NFC_DISABLED,
})
public @interface SecurityLogTag {}
@@ -611,9 +613,20 @@ public class SecurityLog {
* <li> [2] backup service state ({@code Integer}, 1 for enabled, 0 for disabled)
* @see DevicePolicyManager#setBackupServiceEnabled(ComponentName, boolean)
*/
- @FlaggedApi(FLAG_BACKUP_SERVICE_SECURITY_LOG_EVENT_ENABLED)
public static final int TAG_BACKUP_SERVICE_TOGGLED =
SecurityLogTags.SECURITY_BACKUP_SERVICE_TOGGLED;
+
+ /**
+ * Indicates that NFC service is enabled. There is no extra payload in the log event.
+ */
+ @FlaggedApi(FLAG_NFC_STATE_CHANGE_SECURITY_LOG_EVENT_ENABLED)
+ public static final int TAG_NFC_ENABLED = SecurityLogTags.SECURITY_NFC_ENABLED;
+
+ /**
+ * Indicates that NFC service is disabled. There is no extra payload in the log event.
+ */
+ @FlaggedApi(FLAG_NFC_STATE_CHANGE_SECURITY_LOG_EVENT_ENABLED)
+ public static final int TAG_NFC_DISABLED = SecurityLogTags.SECURITY_NFC_DISABLED;
/**
* Event severity level indicating that the event corresponds to normal workflow.
*/
diff --git a/core/java/android/app/admin/SecurityLogTags.logtags b/core/java/android/app/admin/SecurityLogTags.logtags
index 7b3aa7b589b7..8f22c761d535 100644
--- a/core/java/android/app/admin/SecurityLogTags.logtags
+++ b/core/java/android/app/admin/SecurityLogTags.logtags
@@ -48,4 +48,6 @@ option java_package android.app.admin
210041 security_package_installed (package_name|3),(version_code|1),(user_id|1)
210042 security_package_updated (package_name|3),(version_code|1),(user_id|1)
210043 security_package_uninstalled (package_name|3),(version_code|1),(user_id|1)
-210044 security_backup_service_toggled (package|3),(admin_user|1),(enabled|1) \ No newline at end of file
+210044 security_backup_service_toggled (package|3),(admin_user|1),(enabled|1)
+210045 security_nfc_enabled
+210046 security_nfc_disabled \ No newline at end of file
diff --git a/core/java/android/app/admin/flags/flags.aconfig b/core/java/android/app/admin/flags/flags.aconfig
index ff66e0fbc76d..7a615b27686a 100644
--- a/core/java/android/app/admin/flags/flags.aconfig
+++ b/core/java/android/app/admin/flags/flags.aconfig
@@ -146,6 +146,7 @@ flag {
bug: "293441361"
}
+# Fully rolled out and must not be used.
flag {
name: "assist_content_user_restriction_enabled"
is_exported: true
@@ -164,6 +165,7 @@ flag {
}
}
+# Fully rolled out and must not be used.
flag {
name: "backup_service_security_log_event_enabled"
is_exported: true
diff --git a/core/java/android/app/appfunctions/OWNERS b/core/java/android/app/appfunctions/OWNERS
index c6827cc93222..6a69e15d00dd 100644
--- a/core/java/android/app/appfunctions/OWNERS
+++ b/core/java/android/app/appfunctions/OWNERS
@@ -4,3 +4,4 @@ toki@google.com
tonymak@google.com
mingweiliao@google.com
anothermark@google.com
+utkarshnigam@google.com
diff --git a/core/java/android/hardware/OWNERS b/core/java/android/hardware/OWNERS
index 43d3f5466ccf..f11625ed9d61 100644
--- a/core/java/android/hardware/OWNERS
+++ b/core/java/android/hardware/OWNERS
@@ -19,3 +19,6 @@ per-file DataSpace* = file:/graphics/java/android/graphics/OWNERS
# OverlayProperties
per-file OverlayProperties* = file:/graphics/java/android/graphics/OWNERS
+
+# Lut related files
+per-file *Lut* = file:/graphics/java/android/graphics/OWNERS \ No newline at end of file
diff --git a/core/java/android/net/vcn/VcnTransportInfo.java b/core/java/android/net/vcn/VcnTransportInfo.java
index f5469104be7f..1fc91eea3138 100644
--- a/core/java/android/net/vcn/VcnTransportInfo.java
+++ b/core/java/android/net/vcn/VcnTransportInfo.java
@@ -17,9 +17,11 @@
package android.net.vcn;
import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
+import static android.net.vcn.VcnGatewayConnectionConfig.MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS;
import static android.net.vcn.VcnGatewayConnectionConfig.MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.NetworkCapabilities;
@@ -29,6 +31,8 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.SubscriptionManager;
+import com.android.internal.util.Preconditions;
+
import java.util.Objects;
/**
@@ -47,6 +51,7 @@ import java.util.Objects;
*
* @hide
*/
+// TODO: Do not store WifiInfo and subscription ID in VcnTransportInfo anymore
public class VcnTransportInfo implements TransportInfo, Parcelable {
@Nullable private final WifiInfo mWifiInfo;
private final int mSubId;
@@ -195,4 +200,42 @@ public class VcnTransportInfo implements TransportInfo, Parcelable {
return new VcnTransportInfo[size];
}
};
+
+ /** This class can be used to construct a {@link VcnTransportInfo}. */
+ public static final class Builder {
+ private int mMinUdpPort4500NatTimeoutSeconds = MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET;
+
+ /** Construct Builder */
+ public Builder() {}
+
+ /**
+ * Sets the maximum supported IKEv2/IPsec NATT keepalive timeout.
+ *
+ * <p>This is used as a power-optimization hint for other IKEv2/IPsec use cases (e.g. VPNs,
+ * or IWLAN) to reduce the necessary keepalive frequency, thus conserving power and data.
+ *
+ * @param minUdpPort4500NatTimeoutSeconds the maximum keepalive timeout supported by the VCN
+ * Gateway Connection, generally the minimum duration a NAT mapping is cached on the VCN
+ * Gateway.
+ * @return this {@link Builder} instance, for chaining
+ */
+ @NonNull
+ public Builder setMinUdpPort4500NatTimeoutSeconds(
+ @IntRange(from = MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS)
+ int minUdpPort4500NatTimeoutSeconds) {
+ Preconditions.checkArgument(
+ minUdpPort4500NatTimeoutSeconds >= MIN_UDP_PORT_4500_NAT_TIMEOUT_SECONDS,
+ "Timeout must be at least 120s");
+
+ mMinUdpPort4500NatTimeoutSeconds = minUdpPort4500NatTimeoutSeconds;
+ return Builder.this;
+ }
+
+ /** Build a VcnTransportInfo instance */
+ @NonNull
+ public VcnTransportInfo build() {
+ return new VcnTransportInfo(
+ null /* wifiInfo */, INVALID_SUBSCRIPTION_ID, mMinUdpPort4500NatTimeoutSeconds);
+ }
+ }
}
diff --git a/core/java/android/net/vcn/VcnUtils.java b/core/java/android/net/vcn/VcnUtils.java
new file mode 100644
index 000000000000..6dc518097737
--- /dev/null
+++ b/core/java/android/net/vcn/VcnUtils.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.net.vcn;
+
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkSpecifier;
+import android.net.TelephonyNetworkSpecifier;
+import android.net.TransportInfo;
+import android.net.wifi.WifiInfo;
+
+import java.util.List;
+
+/**
+ * Utility class for VCN callers get information from VCN network
+ *
+ * @hide
+ */
+public class VcnUtils {
+ /** Get the WifiInfo of the VCN's underlying WiFi network */
+ @Nullable
+ public static WifiInfo getWifiInfoFromVcnCaps(
+ @NonNull ConnectivityManager connectivityMgr,
+ @NonNull NetworkCapabilities networkCapabilities) {
+ final NetworkCapabilities underlyingCaps =
+ getVcnUnderlyingCaps(connectivityMgr, networkCapabilities);
+
+ if (underlyingCaps == null) {
+ return null;
+ }
+
+ final TransportInfo underlyingTransportInfo = underlyingCaps.getTransportInfo();
+ if (!(underlyingTransportInfo instanceof WifiInfo)) {
+ return null;
+ }
+
+ return (WifiInfo) underlyingTransportInfo;
+ }
+
+ /** Get the subscription ID of the VCN's underlying Cell network */
+ public static int getSubIdFromVcnCaps(
+ @NonNull ConnectivityManager connectivityMgr,
+ @NonNull NetworkCapabilities networkCapabilities) {
+ final NetworkCapabilities underlyingCaps =
+ getVcnUnderlyingCaps(connectivityMgr, networkCapabilities);
+
+ if (underlyingCaps == null) {
+ return INVALID_SUBSCRIPTION_ID;
+ }
+
+ final NetworkSpecifier underlyingNetworkSpecifier = underlyingCaps.getNetworkSpecifier();
+ if (!(underlyingNetworkSpecifier instanceof TelephonyNetworkSpecifier)) {
+ return INVALID_SUBSCRIPTION_ID;
+ }
+
+ return ((TelephonyNetworkSpecifier) underlyingNetworkSpecifier).getSubscriptionId();
+ }
+
+ @Nullable
+ private static NetworkCapabilities getVcnUnderlyingCaps(
+ @NonNull ConnectivityManager connectivityMgr,
+ @NonNull NetworkCapabilities networkCapabilities) {
+ // Return null if it is not a VCN network
+ if (networkCapabilities.getTransportInfo() == null
+ || !(networkCapabilities.getTransportInfo() instanceof VcnTransportInfo)) {
+ return null;
+ }
+
+ // As of Android 16, VCN has one underlying network, and only one. If there are more
+ // than one networks due to future changes in the VCN mainline code, just take the first
+ // network
+ final List<Network> underlyingNws = networkCapabilities.getUnderlyingNetworks();
+ if (underlyingNws == null) {
+ return null;
+ }
+
+ return connectivityMgr.getNetworkCapabilities(underlyingNws.get(0));
+ }
+}
diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java
index 80546cd6770f..3b5a99ed089a 100644
--- a/core/java/android/os/BinderProxy.java
+++ b/core/java/android/os/BinderProxy.java
@@ -493,6 +493,11 @@ public final class BinderProxy implements IBinder {
public native boolean pingBinder();
/**
+ * Check to see if the process that the binder is in is still alive.
+ *
+ * Note, this only reflects the last known death state, if the object
+ * is linked to death or has made a transactions since the death occurs.
+ *
* @return false if the hosting process is gone
*/
public native boolean isBinderAlive();
diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig
index a86c961e6785..aedf8e097e67 100644
--- a/core/java/android/security/flags.aconfig
+++ b/core/java/android/security/flags.aconfig
@@ -106,3 +106,10 @@ flag {
description: "Clear StrongAuth on add credential"
bug: "320817991"
}
+
+flag {
+ name: "afl_api"
+ namespace: "platform_security"
+ description: "AFL feature"
+ bug: "365994454"
+}
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index af106235bd77..af393fdc5ad4 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -119,3 +119,4 @@ per-file android_tracing_Perfetto* = file:platform/development:/tools/winscope/O
# ApplicationSharedMemory
per-file *ApplicationSharedMemory* = file:/PERFORMANCE_OWNERS
+per-file *PropertyInvalidatedCache* = file:/PERFORMANCE_OWNERS
diff --git a/core/jni/android_media_AudioFormat.h b/core/jni/android_media_AudioFormat.h
index a9b19062b764..704aef3cd131 100644
--- a/core/jni/android_media_AudioFormat.h
+++ b/core/jni/android_media_AudioFormat.h
@@ -50,6 +50,7 @@
#define ENCODING_DTS_HD_MA 29
#define ENCODING_DTS_UHD_P2 30
#define ENCODING_DSD 31
+#define ENCODING_AC4_L4 32
#define ENCODING_INVALID 0
#define ENCODING_DEFAULT 1
@@ -95,6 +96,8 @@ static inline audio_format_t audioFormatToNative(int audioFormat)
return AUDIO_FORMAT_AAC_XHE;
case ENCODING_AC4:
return AUDIO_FORMAT_AC4;
+ case ENCODING_AC4_L4:
+ return AUDIO_FORMAT_AC4_L4;
case ENCODING_E_AC3_JOC:
return AUDIO_FORMAT_E_AC3_JOC;
case ENCODING_DEFAULT:
@@ -177,6 +180,8 @@ static inline int audioFormatFromNative(audio_format_t nativeFormat)
return ENCODING_AAC_XHE;
case AUDIO_FORMAT_AC4:
return ENCODING_AC4;
+ case AUDIO_FORMAT_AC4_L4:
+ return ENCODING_AC4_L4;
case AUDIO_FORMAT_E_AC3_JOC:
return ENCODING_E_AC3_JOC;
case AUDIO_FORMAT_MAT:
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 00be9fe564da..376118c8122c 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1529,6 +1529,11 @@
factory reset. -->
<bool name="config_enableCredentialFactoryResetProtection">true</bool>
+ <!-- If true, then work around broken Weaver HALs that don't work reliably before the device has
+ fully booted. Setting this to true weakens a security feature; it should be done only when
+ necessary, though it is still better than not using Weaver at all. -->
+ <bool name="config_disableWeaverOnUnsecuredUsers">false</bool>
+
<!-- Control the behavior when the user long presses the home button.
0 - Nothing
1 - Launch all apps intent
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 06a4d550b204..9ab8ad83480e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3958,6 +3958,7 @@
<java-symbol type="string" name="foreground_service_multiple_separator" />
<java-symbol type="bool" name="config_enableCredentialFactoryResetProtection" />
+ <java-symbol type="bool" name="config_disableWeaverOnUnsecuredUsers" />
<!-- ETWS primary messages -->
<java-symbol type="string" name="etws_primary_default_message_earthquake" />
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
index 9887c272e7f8..af26bd0a3404 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
@@ -130,10 +130,6 @@ public final class RequiresPermissionChecker extends BugChecker
.onDescendantOf("android.content.Context")
.withNameMatching(
Pattern.compile("^send(Ordered|Sticky)?Broadcast.*AsUser.*$")));
- private static final Matcher<ExpressionTree> SEND_PENDING_INTENT = methodInvocation(
- instanceMethod()
- .onDescendantOf("android.app.PendingIntent")
- .named("send"));
private static final Matcher<ExpressionTree> INTENT_SET_ACTION = methodInvocation(
instanceMethod().onDescendantOf("android.content.Intent").named("setAction"));
diff --git a/keystore/OWNERS b/keystore/OWNERS
index 689177715711..ea783e7f0c06 100644
--- a/keystore/OWNERS
+++ b/keystore/OWNERS
@@ -1,5 +1,6 @@
# Bug component: 189335
+ascull@google.com
drysdale@google.com
-eranm@google.com
jbires@google.com
+sethmo@google.com
swillden@google.com
diff --git a/libs/hwui/AutoBackendTextureRelease.cpp b/libs/hwui/AutoBackendTextureRelease.cpp
index 5f5ffe97e953..86fede5eb98c 100644
--- a/libs/hwui/AutoBackendTextureRelease.cpp
+++ b/libs/hwui/AutoBackendTextureRelease.cpp
@@ -140,6 +140,13 @@ void AutoBackendTextureRelease::releaseQueueOwnership(GrDirectContext* context)
return;
}
+ if (!RenderThread::isCurrent()) {
+ // releaseQueueOwnership needs to run on RenderThread to prevent multithread calling
+ // setBackendTextureState will operate skia resource cache which need single owner
+ RenderThread::getInstance().queue().post([this, context]() { releaseQueueOwnership(context); });
+ return;
+ }
+
LOG_ALWAYS_FATAL_IF(Properties::getRenderPipelineType() != RenderPipelineType::SkiaVulkan);
if (mBackendTexture.isValid()) {
// Passing in VK_IMAGE_LAYOUT_UNDEFINED means we keep the old layout.
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index c90c44152440..0da8371bc824 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -16,6 +16,9 @@
package android.media;
+import static android.media.audio.Flags.FLAG_DOLBY_AC4_LEVEL4_ENCODING_API;
+
+import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
@@ -309,7 +312,7 @@ public final class AudioFormat implements Parcelable {
public static final int ENCODING_AAC_ELD = 15;
/** Audio data format: AAC xHE compressed */
public static final int ENCODING_AAC_XHE = 16;
- /** Audio data format: AC-4 sync frame transport format */
+ /** Audio data format: AC-4 (levels 0-3) sync frame transport format */
public static final int ENCODING_AC4 = 17;
/** Audio data format: E-AC-3-JOC compressed
* E-AC-3-JOC streams can be decoded by downstream devices supporting {@link #ENCODING_E_AC3}.
@@ -375,6 +378,9 @@ public final class AudioFormat implements Parcelable {
public static final int ENCODING_DTS_UHD_P2 = 30;
/** Audio data format: Direct Stream Digital */
public static final int ENCODING_DSD = 31;
+ /** Audio data format: AC-4 level 4 sync frame transport format */
+ @FlaggedApi(FLAG_DOLBY_AC4_LEVEL4_ENCODING_API)
+ public static final int ENCODING_AC4_L4 = 32;
/** @hide */
public static String toLogFriendlyEncoding(int enc) {
@@ -413,6 +419,8 @@ public final class AudioFormat implements Parcelable {
return "ENCODING_AAC_XHE";
case ENCODING_AC4:
return "ENCODING_AC4";
+ case ENCODING_AC4_L4:
+ return "ENCODING_AC4_L4";
case ENCODING_E_AC3_JOC:
return "ENCODING_E_AC3_JOC";
case ENCODING_DOLBY_MAT:
@@ -823,6 +831,7 @@ public final class AudioFormat implements Parcelable {
case ENCODING_AAC_ELD:
case ENCODING_AAC_XHE:
case ENCODING_AC4:
+ case ENCODING_AC4_L4:
case ENCODING_E_AC3_JOC:
case ENCODING_DOLBY_MAT:
case ENCODING_OPUS:
@@ -863,6 +872,7 @@ public final class AudioFormat implements Parcelable {
case ENCODING_AAC_ELD:
case ENCODING_AAC_XHE:
case ENCODING_AC4:
+ case ENCODING_AC4_L4:
case ENCODING_E_AC3_JOC:
case ENCODING_DOLBY_MAT:
case ENCODING_OPUS:
@@ -908,6 +918,7 @@ public final class AudioFormat implements Parcelable {
case ENCODING_AAC_ELD:
case ENCODING_AAC_XHE:
case ENCODING_AC4:
+ case ENCODING_AC4_L4:
case ENCODING_E_AC3_JOC:
case ENCODING_DOLBY_MAT:
case ENCODING_OPUS:
@@ -950,6 +961,7 @@ public final class AudioFormat implements Parcelable {
case ENCODING_AAC_ELD:
case ENCODING_AAC_XHE:
case ENCODING_AC4:
+ case ENCODING_AC4_L4:
case ENCODING_E_AC3_JOC:
case ENCODING_DOLBY_MAT:
case ENCODING_OPUS:
@@ -1238,6 +1250,7 @@ public final class AudioFormat implements Parcelable {
case ENCODING_AAC_ELD:
case ENCODING_AAC_XHE:
case ENCODING_AC4:
+ case ENCODING_AC4_L4:
case ENCODING_E_AC3_JOC:
case ENCODING_DOLBY_MAT:
case ENCODING_OPUS:
@@ -1468,6 +1481,7 @@ public final class AudioFormat implements Parcelable {
ENCODING_AAC_ELD,
ENCODING_AAC_XHE,
ENCODING_AC4,
+ ENCODING_AC4_L4,
ENCODING_E_AC3_JOC,
ENCODING_DOLBY_MAT,
ENCODING_OPUS,
@@ -1506,6 +1520,7 @@ public final class AudioFormat implements Parcelable {
ENCODING_AAC_ELD,
ENCODING_AAC_XHE,
ENCODING_AC4,
+ ENCODING_AC4_L4,
ENCODING_E_AC3_JOC,
ENCODING_DOLBY_MAT,
ENCODING_OPUS,
@@ -1533,6 +1548,7 @@ public final class AudioFormat implements Parcelable {
ENCODING_AAC_LC,
ENCODING_DOLBY_TRUEHD,
ENCODING_AC4,
+ ENCODING_AC4_L4,
ENCODING_E_AC3_JOC,
ENCODING_DOLBY_MAT,
ENCODING_MPEGH_BL_L3,
@@ -1554,6 +1570,7 @@ public final class AudioFormat implements Parcelable {
ENCODING_AAC_LC,
ENCODING_DOLBY_TRUEHD,
ENCODING_AC4,
+ ENCODING_AC4_L4,
ENCODING_E_AC3_JOC,
ENCODING_DOLBY_MAT,
ENCODING_MPEGH_BL_L3,
@@ -1592,7 +1609,9 @@ public final class AudioFormat implements Parcelable {
case ENCODING_DOLBY_TRUEHD:
return "Dolby TrueHD";
case ENCODING_AC4:
- return "Dolby AC-4";
+ return "Dolby AC-4 levels 0-3";
+ case ENCODING_AC4_L4:
+ return "Dolby AC-4 level 4";
case ENCODING_E_AC3_JOC:
return "Dolby Atmos in Dolby Digital Plus";
case ENCODING_DOLBY_MAT:
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 2d0e7abbe890..7b8702fd5271 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -542,6 +542,8 @@ public class AudioSystem
return "AUDIO_FORMAT_AAC_LATM_HE_V2"; // (AAC_LATM | AAC_SUB_HE_V2)
case /* AUDIO_FORMAT_E_AC3_JOC */ 0xA000001:
return "AUDIO_FORMAT_E_AC3_JOC"; // (E_AC3 | E_AC3_SUB_JOC)
+ case /* AUDIO_FORMAT_AC4_L4 */ 0x22000001:
+ return "AUDIO_FORMAT_AC4_L4"; // (AC4 | AC4_SUB_L4)
case /* AUDIO_FORMAT_MAT_1_0 */ 0x24000001:
return "AUDIO_FORMAT_MAT_1_0"; // (MAT | MAT_SUB_1_0)
case /* AUDIO_FORMAT_MAT_2_0 */ 0x24000002:
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index 47637b82111a..290d49b31eb7 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -15,10 +15,8 @@
*/
package android.media.session;
-import static com.android.media.flags.Flags.FLAG_ENABLE_NOTIFYING_ACTIVITY_MANAGER_WITH_MEDIA_SESSION_STATUS_CHANGE;
import android.annotation.DrawableRes;
-import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.LongDef;
import android.annotation.Nullable;
@@ -187,13 +185,21 @@ public final class PlaybackState implements Parcelable {
*/
public static final long ACTION_SET_PLAYBACK_SPEED = 1 << 22;
- /**
- * @hide
- */
- @IntDef({STATE_NONE, STATE_STOPPED, STATE_PAUSED, STATE_PLAYING, STATE_FAST_FORWARDING,
- STATE_REWINDING, STATE_BUFFERING, STATE_ERROR, STATE_CONNECTING,
- STATE_SKIPPING_TO_PREVIOUS, STATE_SKIPPING_TO_NEXT, STATE_SKIPPING_TO_QUEUE_ITEM,
- STATE_PLAYBACK_SUPPRESSED})
+ /** @hide */
+ @IntDef({
+ STATE_NONE,
+ STATE_STOPPED,
+ STATE_PAUSED,
+ STATE_PLAYING,
+ STATE_FAST_FORWARDING,
+ STATE_REWINDING,
+ STATE_BUFFERING,
+ STATE_ERROR,
+ STATE_CONNECTING,
+ STATE_SKIPPING_TO_PREVIOUS,
+ STATE_SKIPPING_TO_NEXT,
+ STATE_SKIPPING_TO_QUEUE_ITEM
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface State {}
@@ -290,19 +296,6 @@ public final class PlaybackState implements Parcelable {
public static final int STATE_SKIPPING_TO_QUEUE_ITEM = 11;
/**
- * State indicating that playback is paused due to an external transient interruption, like a
- * phone call.
- *
- * <p>This state is different from {@link #STATE_PAUSED} in that it is deemed transitory,
- * possibly allowing the service associated to the session in this state to run in the
- * foreground.
- *
- * @see Builder#setState
- */
- @FlaggedApi(FLAG_ENABLE_NOTIFYING_ACTIVITY_MANAGER_WITH_MEDIA_SESSION_STATUS_CHANGE)
- public static final int STATE_PLAYBACK_SUPPRESSED = 12;
-
- /**
* Use this value for the position to indicate the position is not known.
*/
public static final long PLAYBACK_POSITION_UNKNOWN = -1;
@@ -401,7 +394,6 @@ public final class PlaybackState implements Parcelable {
* <li> {@link PlaybackState#STATE_SKIPPING_TO_PREVIOUS}</li>
* <li> {@link PlaybackState#STATE_SKIPPING_TO_NEXT}</li>
* <li> {@link PlaybackState#STATE_SKIPPING_TO_QUEUE_ITEM}</li>
- * <li> {@link PlaybackState#STATE_PLAYBACK_SUPPRESSED}</li>
* </ul>
*/
@State
@@ -525,7 +517,6 @@ public final class PlaybackState implements Parcelable {
* <li>{@link #STATE_SKIPPING_TO_NEXT}</li>
* <li>{@link #STATE_SKIPPING_TO_PREVIOUS}</li>
* <li>{@link #STATE_SKIPPING_TO_QUEUE_ITEM}</li>
- * <li>{@link #STATE_PLAYBACK_SUPPRESSED}</li>
* </ul>
*/
public boolean isActive() {
@@ -538,7 +529,6 @@ public final class PlaybackState implements Parcelable {
case PlaybackState.STATE_BUFFERING:
case PlaybackState.STATE_CONNECTING:
case PlaybackState.STATE_PLAYING:
- case PlaybackState.STATE_PLAYBACK_SUPPRESSED:
return true;
}
return false;
@@ -584,8 +574,6 @@ public final class PlaybackState implements Parcelable {
return "SKIPPING_TO_NEXT";
case STATE_SKIPPING_TO_QUEUE_ITEM:
return "SKIPPING_TO_QUEUE_ITEM";
- case STATE_PLAYBACK_SUPPRESSED:
- return "STATE_PLAYBACK_SUPPRESSED";
default:
return "UNKNOWN";
}
@@ -823,7 +811,6 @@ public final class PlaybackState implements Parcelable {
* <li> {@link PlaybackState#STATE_SKIPPING_TO_PREVIOUS}</li>
* <li> {@link PlaybackState#STATE_SKIPPING_TO_NEXT}</li>
* <li> {@link PlaybackState#STATE_SKIPPING_TO_QUEUE_ITEM}</li>
- * <li> {@link PlaybackState#STATE_PLAYBACK_SUPPRESSED}</li>
* </ul>
*
* @param state The current state of playback.
@@ -868,7 +855,6 @@ public final class PlaybackState implements Parcelable {
* <li> {@link PlaybackState#STATE_SKIPPING_TO_PREVIOUS}</li>
* <li> {@link PlaybackState#STATE_SKIPPING_TO_NEXT}</li>
* <li> {@link PlaybackState#STATE_SKIPPING_TO_QUEUE_ITEM}</li>
- * <li> {@link PlaybackState#STATE_PLAYBACK_SUPPRESSED}</li>
* </ul>
*
* @param state The current state of playback.
diff --git a/nfc/Android.bp b/nfc/Android.bp
index db3dcb0631dd..7ad8c4c8de41 100644
--- a/nfc/Android.bp
+++ b/nfc/Android.bp
@@ -41,6 +41,10 @@ java_sdk_library {
"framework-permission-s.stubs.module_lib",
"framework-permission.stubs.module_lib",
],
+ stub_only_libs: [
+ // Needed for javadoc references.
+ "framework-permission-s.stubs.module_lib",
+ ],
static_libs: [
"android.nfc.flags-aconfig-java",
"android.permission.flags-aconfig-java",
diff --git a/nfc/api/current.txt b/nfc/api/current.txt
index e7cb76c370fd..96b7c1339190 100644
--- a/nfc/api/current.txt
+++ b/nfc/api/current.txt
@@ -223,6 +223,7 @@ package android.nfc.cardemulation {
field public static final String CATEGORY_PAYMENT = "payment";
field public static final String EXTRA_CATEGORY = "category";
field public static final String EXTRA_SERVICE_COMPONENT = "component";
+ 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
field @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC = 2; // 0x2
diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt
index 94231b0facdb..4428adee818d 100644
--- a/nfc/api/system-current.txt
+++ b/nfc/api/system-current.txt
@@ -58,12 +58,16 @@ package android.nfc {
@FlaggedApi("android.nfc.nfc_oem_extension") public final class NfcOemExtension {
method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void clearPreference();
method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull public java.util.List<java.lang.String> getActiveNfceeList();
+ method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.nfc.RoutingStatus getRoutingStatus();
method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean hasUserEnabledNfc();
+ method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isAutoChangeEnabled();
method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isTagPresent();
method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void maybeTriggerFirmwareUpdate();
+ method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void overwriteRoutingTable(int, int, int);
method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void pausePolling(int);
method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcOemExtension.Callback);
method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void resumePolling();
+ method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setAutoChangeEnabled(boolean);
method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void setControllerAlwaysOnMode(int);
method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void synchronizeScreenState();
method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void triggerInitialization();
@@ -90,7 +94,11 @@ package android.nfc {
method public void onEnable(@NonNull java.util.function.Consumer<java.lang.Boolean>);
method public void onEnableFinished(int);
method public void onEnableStarted();
+ method public void onGetOemAppSearchIntent(@NonNull java.util.List<java.lang.String>, @NonNull java.util.function.Consumer<android.content.Intent>);
method public void onHceEventReceived(int);
+ method public void onLaunchHceAppChooserActivity(@NonNull String, @NonNull java.util.List<android.nfc.cardemulation.ApduServiceInfo>, @NonNull android.content.ComponentName, @NonNull String);
+ method public void onLaunchHceTapAgainDialog(@NonNull android.nfc.cardemulation.ApduServiceInfo, @NonNull String);
+ method public void onNdefMessage(@NonNull android.nfc.Tag, @NonNull android.nfc.NdefMessage, @NonNull java.util.function.Consumer<java.lang.Boolean>);
method public void onNdefRead(@NonNull java.util.function.Consumer<java.lang.Boolean>);
method public void onReaderOptionChanged(boolean);
method public void onRfDiscoveryStarted(boolean);
@@ -101,6 +109,12 @@ package android.nfc {
method public void onTagDispatch(@NonNull java.util.function.Consumer<java.lang.Boolean>);
}
+ @FlaggedApi("android.nfc.nfc_oem_extension") public class RoutingStatus {
+ method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int getDefaultIsoDepRoute();
+ method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int getDefaultOffHostRoute();
+ method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int getDefaultRoute();
+ }
+
}
package android.nfc.cardemulation {
diff --git a/nfc/java/android/nfc/INfcCardEmulation.aidl b/nfc/java/android/nfc/INfcCardEmulation.aidl
index 19b9e0f0b515..1eae3c6f30f1 100644
--- a/nfc/java/android/nfc/INfcCardEmulation.aidl
+++ b/nfc/java/android/nfc/INfcCardEmulation.aidl
@@ -51,4 +51,8 @@ interface INfcCardEmulation
void overrideRoutingTable(int userHandle, String protocol, String technology, in String pkg);
void recoverRoutingTable(int userHandle);
boolean isEuiccSupported();
+ void setAutoChangeStatus(boolean state);
+ boolean isAutoChangeEnabled();
+ List<String> getRoutingStatus();
+ void overwriteRoutingTable(int userHandle, String emptyAid, String protocol, String tech);
}
diff --git a/nfc/java/android/nfc/INfcOemExtensionCallback.aidl b/nfc/java/android/nfc/INfcOemExtensionCallback.aidl
index e49ef7e80705..48c7ee659266 100644
--- a/nfc/java/android/nfc/INfcOemExtensionCallback.aidl
+++ b/nfc/java/android/nfc/INfcOemExtensionCallback.aidl
@@ -15,9 +15,14 @@
*/
package android.nfc;
+import android.content.ComponentName;
+import android.nfc.cardemulation.ApduServiceInfo;
+import android.nfc.NdefMessage;
import android.nfc.Tag;
import android.os.ResultReceiver;
+import java.util.List;
+
/**
* @hide
*/
@@ -41,4 +46,8 @@ interface INfcOemExtensionCallback {
void onCardEmulationActivated(boolean isActivated);
void onRfFieldActivated(boolean isActivated);
void onRfDiscoveryStarted(boolean isDiscoveryStarted);
+ void onGetOemAppSearchIntent(in List<String> firstPackage, in ResultReceiver intentConsumer);
+ void onNdefMessage(in Tag tag, in NdefMessage message, in ResultReceiver hasOemExecutableContent);
+ void onLaunchHceAppChooserActivity(in String selectedAid, in List<ApduServiceInfo> services, in ComponentName failedComponent, in String category);
+ void onLaunchHceTapAgainActivity(in ApduServiceInfo service, in String category);
}
diff --git a/nfc/java/android/nfc/NfcOemExtension.java b/nfc/java/android/nfc/NfcOemExtension.java
index 6d5c069bca3a..fb63b5c03d00 100644
--- a/nfc/java/android/nfc/NfcOemExtension.java
+++ b/nfc/java/android/nfc/NfcOemExtension.java
@@ -16,6 +16,12 @@
package android.nfc;
+import static android.nfc.cardemulation.CardEmulation.PROTOCOL_AND_TECHNOLOGY_ROUTE_DH;
+import static android.nfc.cardemulation.CardEmulation.PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE;
+import static android.nfc.cardemulation.CardEmulation.PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC;
+import static android.nfc.cardemulation.CardEmulation.routeIntToString;
+
+import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
@@ -23,8 +29,14 @@ import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
+import android.nfc.cardemulation.ApduServiceInfo;
+import android.nfc.cardemulation.CardEmulation;
+import android.nfc.cardemulation.CardEmulation.ProtocolAndTechnologyRoute;
import android.os.Binder;
+import android.os.Bundle;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.util.Log;
@@ -306,6 +318,60 @@ public final class NfcOemExtension {
* @param isDiscoveryStarted true, if RF discovery started, else RF state is Idle.
*/
void onRfDiscoveryStarted(boolean isDiscoveryStarted);
+
+ /**
+ * Gets the intent to find the OEM package in the OEM App market. If the consumer returns
+ * {@code null} or a timeout occurs, the intent from the first available package will be
+ * used instead.
+ *
+ * @param packages the OEM packages name stored in the tag
+ * @param intentConsumer The {@link Consumer} to be completed.
+ * The {@link Consumer#accept(Object)} should be called with
+ * the Intent required.
+ *
+ */
+ void onGetOemAppSearchIntent(@NonNull List<String> packages,
+ @NonNull Consumer<Intent> intentConsumer);
+
+ /**
+ * Checks if the NDEF message contains any specific OEM package executable content
+ *
+ * @param tag the {@link android.nfc.Tag Tag}
+ * @param message NDEF Message to read from tag
+ * @param hasOemExecutableContent The {@link Consumer} to be completed. If there is
+ * OEM package executable content, the
+ * {@link Consumer#accept(Object)} should be called with
+ * {@link Boolean#TRUE}, otherwise call with
+ * {@link Boolean#FALSE}.
+ */
+ void onNdefMessage(@NonNull Tag tag, @NonNull NdefMessage message,
+ @NonNull Consumer<Boolean> hasOemExecutableContent);
+
+ /**
+ * Callback to indicate the app chooser activity should be launched for handling CE
+ * transaction. This is invoked for example when there are more than 1 app installed that
+ * can handle the HCE transaction. OEMs can launch the Activity based
+ * on their requirement.
+ *
+ * @param selectedAid the selected AID from APDU
+ * @param services {@link ApduServiceInfo} of the service triggering the activity
+ * @param failedComponent the component failed to be resolved
+ * @param category the category of the service
+ */
+ void onLaunchHceAppChooserActivity(@NonNull String selectedAid,
+ @NonNull List<ApduServiceInfo> services,
+ @NonNull ComponentName failedComponent,
+ @NonNull String category);
+
+ /**
+ * Callback to indicate tap again dialog should be launched for handling HCE transaction.
+ * This is invoked for example when a CE service needs the device to unlocked before
+ * handling the transaction. OEMs can launch the Activity based on their requirement.
+ *
+ * @param service {@link ApduServiceInfo} of the service triggering the dialog
+ * @param category the category of the service
+ */
+ void onLaunchHceTapAgainDialog(@NonNull ApduServiceInfo service, @NonNull String category);
}
@@ -523,6 +589,85 @@ public final class NfcOemExtension {
NfcAdapter.callService(() -> NfcAdapter.sService.resumePolling());
}
+ /**
+ * Set whether to enable auto routing change or not (enabled by default).
+ * If disabled, routing targets are limited to a single off-host destination.
+ *
+ * @param state status of auto routing change, true if enable, otherwise false
+ */
+ @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
+ @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+ public void setAutoChangeEnabled(boolean state) {
+ NfcAdapter.callService(() ->
+ NfcAdapter.sCardEmulationService.setAutoChangeStatus(state));
+ }
+
+ /**
+ * Check if auto routing change is enabled or not.
+ *
+ * @return true if enabled, otherwise false
+ */
+ @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
+ @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+ public boolean isAutoChangeEnabled() {
+ return NfcAdapter.callServiceReturn(() ->
+ NfcAdapter.sCardEmulationService.isAutoChangeEnabled(), false);
+ }
+
+ /**
+ * Get current routing status
+ *
+ * @return {@link RoutingStatus} indicating the default route, default ISO-DEP
+ * route and default off-host route.
+ */
+ @NonNull
+ @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
+ @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+ public RoutingStatus getRoutingStatus() {
+ List<String> status = NfcAdapter.callServiceReturn(() ->
+ NfcAdapter.sCardEmulationService.getRoutingStatus(), new ArrayList<>());
+ return new RoutingStatus(routeStringToInt(status.get(0)),
+ routeStringToInt(status.get(1)),
+ routeStringToInt(status.get(2)));
+ }
+
+ /**
+ * Overwrites NFC controller routing table, which includes Protocol Route, Technology Route,
+ * and Empty AID Route.
+ *
+ * The parameter set to
+ * {@link ProtocolAndTechnologyRoute#PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET}
+ * can be used to keep current values for that entry. At least one route should be overridden
+ * when calling this API, otherwise throw {@link IllegalArgumentException}.
+ *
+ * @param protocol ISO-DEP route destination, where the possible inputs are defined in
+ * {@link ProtocolAndTechnologyRoute}.
+ * @param technology Tech-A, Tech-B and Tech-F route destination, where the possible inputs
+ * are defined in
+ * {@link ProtocolAndTechnologyRoute}
+ * @param emptyAid Zero-length AID route destination, where the possible inputs are defined in
+ * {@link ProtocolAndTechnologyRoute}
+ */
+ @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+ @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
+ public void overwriteRoutingTable(
+ @CardEmulation.ProtocolAndTechnologyRoute int protocol,
+ @CardEmulation.ProtocolAndTechnologyRoute int technology,
+ @CardEmulation.ProtocolAndTechnologyRoute int emptyAid) {
+
+ String protocolRoute = routeIntToString(protocol);
+ String technologyRoute = routeIntToString(technology);
+ String emptyAidRoute = routeIntToString(emptyAid);
+
+ NfcAdapter.callService(() ->
+ NfcAdapter.sCardEmulationService.overwriteRoutingTable(
+ mContext.getUser().getIdentifier(),
+ emptyAidRoute,
+ protocolRoute,
+ technologyRoute
+ ));
+ }
+
private final class NfcOemExtensionCallback extends INfcOemExtensionCallback.Stub {
@Override
@@ -562,25 +707,25 @@ public final class NfcOemExtension {
public void onApplyRouting(ResultReceiver isSkipped) throws RemoteException {
mCallbackMap.forEach((cb, ex) ->
handleVoidCallback(
- new ReceiverWrapper(isSkipped), cb::onApplyRouting, ex));
+ new ReceiverWrapper<>(isSkipped), cb::onApplyRouting, ex));
}
@Override
public void onNdefRead(ResultReceiver isSkipped) throws RemoteException {
mCallbackMap.forEach((cb, ex) ->
handleVoidCallback(
- new ReceiverWrapper(isSkipped), cb::onNdefRead, ex));
+ new ReceiverWrapper<>(isSkipped), cb::onNdefRead, ex));
}
@Override
public void onEnable(ResultReceiver isAllowed) throws RemoteException {
mCallbackMap.forEach((cb, ex) ->
handleVoidCallback(
- new ReceiverWrapper(isAllowed), cb::onEnable, ex));
+ new ReceiverWrapper<>(isAllowed), cb::onEnable, ex));
}
@Override
public void onDisable(ResultReceiver isAllowed) throws RemoteException {
mCallbackMap.forEach((cb, ex) ->
handleVoidCallback(
- new ReceiverWrapper(isAllowed), cb::onDisable, ex));
+ new ReceiverWrapper<>(isAllowed), cb::onDisable, ex));
}
@Override
public void onBootStarted() throws RemoteException {
@@ -616,7 +761,7 @@ public final class NfcOemExtension {
public void onTagDispatch(ResultReceiver isSkipped) throws RemoteException {
mCallbackMap.forEach((cb, ex) ->
handleVoidCallback(
- new ReceiverWrapper(isSkipped), cb::onTagDispatch, ex));
+ new ReceiverWrapper<>(isSkipped), cb::onTagDispatch, ex));
}
@Override
public void onRoutingChanged() throws RemoteException {
@@ -635,6 +780,59 @@ public final class NfcOemExtension {
handleVoidCallback(enabled, cb::onReaderOptionChanged, ex));
}
+ @Override
+ public void onGetOemAppSearchIntent(List<String> packages, ResultReceiver intentConsumer)
+ throws RemoteException {
+ mCallbackMap.forEach((cb, ex) ->
+ handleVoid2ArgCallback(packages, new ReceiverWrapper<>(intentConsumer),
+ cb::onGetOemAppSearchIntent, ex));
+ }
+
+ @Override
+ public void onNdefMessage(Tag tag, NdefMessage message,
+ ResultReceiver hasOemExecutableContent) throws RemoteException {
+ mCallbackMap.forEach((cb, ex) -> {
+ synchronized (mLock) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ ex.execute(() -> cb.onNdefMessage(
+ tag, message, new ReceiverWrapper<>(hasOemExecutableContent)));
+ } catch (RuntimeException exception) {
+ throw exception;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onLaunchHceAppChooserActivity(String selectedAid,
+ List<ApduServiceInfo> services,
+ ComponentName failedComponent, String category)
+ throws RemoteException {
+ mCallbackMap.forEach((cb, ex) -> {
+ synchronized (mLock) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ ex.execute(() -> cb.onLaunchHceAppChooserActivity(
+ selectedAid, services, failedComponent, category));
+ } catch (RuntimeException exception) {
+ throw exception;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onLaunchHceTapAgainActivity(ApduServiceInfo service, String category)
+ throws RemoteException {
+ mCallbackMap.forEach((cb, ex) ->
+ handleVoid2ArgCallback(service, category, cb::onLaunchHceTapAgainDialog, ex));
+ }
+
private <T> void handleVoidCallback(
T input, Consumer<T> callbackMethod, Executor executor) {
synchronized (mLock) {
@@ -718,7 +916,16 @@ public final class NfcOemExtension {
}
}
- private class ReceiverWrapper implements Consumer<Boolean> {
+ private @CardEmulation.ProtocolAndTechnologyRoute int routeStringToInt(String route) {
+ return switch (route) {
+ case "DH" -> PROTOCOL_AND_TECHNOLOGY_ROUTE_DH;
+ case "eSE" -> PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE;
+ case "SIM" -> PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC;
+ default -> throw new IllegalStateException("Unexpected value: " + route);
+ };
+ }
+
+ private class ReceiverWrapper<T> implements Consumer<T> {
private final ResultReceiver mResultReceiver;
ReceiverWrapper(ResultReceiver resultReceiver) {
@@ -726,12 +933,19 @@ public final class NfcOemExtension {
}
@Override
- public void accept(Boolean result) {
- mResultReceiver.send(result ? 1 : 0, null);
+ public void accept(T result) {
+ if (result instanceof Boolean) {
+ mResultReceiver.send((Boolean) result ? 1 : 0, null);
+ } else if (result instanceof Intent) {
+ Bundle bundle = new Bundle();
+ bundle.putParcelable("intent", (Intent) result);
+ mResultReceiver.send(0, bundle);
+ }
+
}
@Override
- public Consumer<Boolean> andThen(Consumer<? super Boolean> after) {
+ public Consumer<T> andThen(Consumer<? super T> after) {
return Consumer.super.andThen(after);
}
}
diff --git a/nfc/java/android/nfc/RoutingStatus.java b/nfc/java/android/nfc/RoutingStatus.java
new file mode 100644
index 000000000000..4a1b1f3cecbc
--- /dev/null
+++ b/nfc/java/android/nfc/RoutingStatus.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.nfc;
+
+import android.annotation.FlaggedApi;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.nfc.cardemulation.CardEmulation;
+
+/**
+ * A class indicating default route, ISO-DEP route and off-host route.
+ *
+ * @hide
+ */
+@SystemApi
+@FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
+public class RoutingStatus {
+ private final @CardEmulation.ProtocolAndTechnologyRoute int mDefaultRoute;
+ private final @CardEmulation.ProtocolAndTechnologyRoute int mDefaultIsoDepRoute;
+ private final @CardEmulation.ProtocolAndTechnologyRoute int mDefaultOffHostRoute;
+
+ RoutingStatus(@CardEmulation.ProtocolAndTechnologyRoute int mDefaultRoute,
+ @CardEmulation.ProtocolAndTechnologyRoute int mDefaultIsoDepRoute,
+ @CardEmulation.ProtocolAndTechnologyRoute int mDefaultOffHostRoute) {
+ this.mDefaultRoute = mDefaultRoute;
+ this.mDefaultIsoDepRoute = mDefaultIsoDepRoute;
+ this.mDefaultOffHostRoute = mDefaultOffHostRoute;
+ }
+
+ /**
+ * Getter of the default route.
+ * @return an integer defined in
+ * {@link android.nfc.cardemulation.CardEmulation.ProtocolAndTechnologyRoute}
+ */
+ @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ @CardEmulation.ProtocolAndTechnologyRoute
+ public int getDefaultRoute() {
+ return mDefaultRoute;
+ }
+
+ /**
+ * Getter of the default ISO-DEP route.
+ * @return an integer defined in
+ * {@link android.nfc.cardemulation.CardEmulation.ProtocolAndTechnologyRoute}
+ */
+ @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ @CardEmulation.ProtocolAndTechnologyRoute
+ public int getDefaultIsoDepRoute() {
+ return mDefaultIsoDepRoute;
+ }
+
+ /**
+ * Getter of the default off-host route.
+ * @return an integer defined in
+ * {@link android.nfc.cardemulation.CardEmulation.ProtocolAndTechnologyRoute}
+ */
+ @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION)
+ @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ @CardEmulation.ProtocolAndTechnologyRoute
+ public int getDefaultOffHostRoute() {
+ return mDefaultOffHostRoute;
+ }
+
+}
diff --git a/nfc/java/android/nfc/cardemulation/CardEmulation.java b/nfc/java/android/nfc/cardemulation/CardEmulation.java
index 4be082ccc02f..d8f04c50b695 100644
--- a/nfc/java/android/nfc/cardemulation/CardEmulation.java
+++ b/nfc/java/android/nfc/cardemulation/CardEmulation.java
@@ -168,6 +168,12 @@ public final class CardEmulation {
public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC = 2;
/**
+ * Route to the default value in config file.
+ */
+ @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE)
+ public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_DEFAULT = 3;
+
+ /**
* Route unset.
*/
@FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE)
@@ -895,45 +901,47 @@ public final class CardEmulation {
PROTOCOL_AND_TECHNOLOGY_ROUTE_DH,
PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE,
PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC,
- PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET
+ PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET,
+ PROTOCOL_AND_TECHNOLOGY_ROUTE_DEFAULT
})
@Retention(RetentionPolicy.SOURCE)
public @interface ProtocolAndTechnologyRoute {}
- /**
- * Setting NFC controller routing table, which includes Protocol Route and Technology Route,
- * while this Activity is in the foreground.
- *
- * The parameter set to {@link #PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET}
- * can be used to keep current values for that entry. Either
- * Protocol Route or Technology Route should be override when calling this API, otherwise
- * throw {@link IllegalArgumentException}.
- * <p>
- * Example usage in an Activity that requires to set proto route to "ESE" and keep tech route:
- * <pre>
- * protected void onResume() {
- * mNfcAdapter.overrideRoutingTable(
- * this, {@link #PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE}, null);
- * }</pre>
- * </p>
- * Also activities must call {@link #recoverRoutingTable(Activity)}
- * when it goes to the background. Only the package of the
- * currently preferred service (the service set as preferred by the current foreground
- * application via {@link CardEmulation#setPreferredService(Activity, ComponentName)} or the
- * current Default Wallet Role Holder {@link RoleManager#ROLE_WALLET}),
- * otherwise a call to this method will fail and throw {@link SecurityException}.
- * @param activity The Activity that requests NFC controller routing table to be changed.
- * @param protocol ISO-DEP route destination, where the possible inputs are defined
- * in {@link ProtocolAndTechnologyRoute}.
- * @param technology Tech-A, Tech-B and Tech-F route destination, where the possible inputs
- * are defined in {@link ProtocolAndTechnologyRoute}
- * @throws SecurityException if the caller is not the preferred NFC service
- * @throws IllegalArgumentException if the activity is not resumed or the caller is not in the
- * foreground.
- * <p>
- * This is a high risk API and only included to support mainline effort
- * @hide
- */
+ /**
+ * Setting NFC controller routing table, which includes Protocol Route and Technology Route,
+ * while this Activity is in the foreground.
+ *
+ * The parameter set to {@link #PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET}
+ * can be used to keep current values for that entry. Either
+ * Protocol Route or Technology Route should be override when calling this API, otherwise
+ * throw {@link IllegalArgumentException}.
+ * <p>
+ * Example usage in an Activity that requires to set proto route to "ESE" and keep tech route:
+ * <pre>
+ * protected void onResume() {
+ * mNfcAdapter.overrideRoutingTable(
+ * this, {@link #PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE},
+ * {@link #PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET});
+ * }</pre>
+ * </p>
+ * Also activities must call {@link #recoverRoutingTable(Activity)}
+ * when it goes to the background. Only the package of the
+ * currently preferred service (the service set as preferred by the current foreground
+ * application via {@link CardEmulation#setPreferredService(Activity, ComponentName)} or the
+ * current Default Wallet Role Holder {@link RoleManager#ROLE_WALLET}),
+ * otherwise a call to this method will fail and throw {@link SecurityException}.
+ * @param activity The Activity that requests NFC controller routing table to be changed.
+ * @param protocol ISO-DEP route destination, where the possible inputs are defined
+ * in {@link ProtocolAndTechnologyRoute}.
+ * @param technology Tech-A, Tech-B and Tech-F route destination, where the possible inputs
+ * are defined in {@link ProtocolAndTechnologyRoute}
+ * @throws SecurityException if the caller is not the preferred NFC service
+ * @throws IllegalArgumentException if the activity is not resumed or the caller is not in the
+ * foreground.
+ * <p>
+ * This is a high risk API and only included to support mainline effort
+ * @hide
+ */
@SystemApi
@FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE)
public void overrideRoutingTable(
@@ -942,26 +950,14 @@ public final class CardEmulation {
if (!activity.isResumed()) {
throw new IllegalArgumentException("Activity must be resumed.");
}
- String protocolRoute = switch (protocol) {
- case PROTOCOL_AND_TECHNOLOGY_ROUTE_DH -> "DH";
- case PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE -> "ESE";
- case PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC -> "UICC";
- case PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET -> null;
- default -> throw new IllegalStateException("Unexpected value: " + protocol);
- };
- String technologyRoute = switch (technology) {
- case PROTOCOL_AND_TECHNOLOGY_ROUTE_DH -> "DH";
- case PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE -> "ESE";
- case PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC -> "UICC";
- case PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET -> null;
- default -> throw new IllegalStateException("Unexpected value: " + protocol);
- };
+ String protocolRoute = routeIntToString(protocol);
+ String technologyRoute = routeIntToString(technology);
callService(() ->
sService.overrideRoutingTable(
- mContext.getUser().getIdentifier(),
- protocolRoute,
- technologyRoute,
- mContext.getPackageName()));
+ mContext.getUser().getIdentifier(),
+ protocolRoute,
+ technologyRoute,
+ mContext.getPackageName()));
}
/**
@@ -1068,4 +1064,16 @@ public final class CardEmulation {
}
return defaultReturn;
}
+
+ /** @hide */
+ public static String routeIntToString(@ProtocolAndTechnologyRoute int route) {
+ return switch (route) {
+ case PROTOCOL_AND_TECHNOLOGY_ROUTE_DH -> "DH";
+ case PROTOCOL_AND_TECHNOLOGY_ROUTE_ESE -> "eSE";
+ case PROTOCOL_AND_TECHNOLOGY_ROUTE_UICC -> "SIM";
+ case PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET -> null;
+ case PROTOCOL_AND_TECHNOLOGY_ROUTE_DEFAULT -> "default";
+ default -> throw new IllegalStateException("Unexpected value: " + route);
+ };
+ }
}
diff --git a/nfc/java/android/nfc/flags.aconfig b/nfc/java/android/nfc/flags.aconfig
index cc9a97cd52c9..6a7e6939e773 100644
--- a/nfc/java/android/nfc/flags.aconfig
+++ b/nfc/java/android/nfc/flags.aconfig
@@ -157,3 +157,11 @@ flag {
description: "Enable EUICC card emulation"
bug: "321314635"
}
+
+flag {
+ name: "nfc_state_change_security_log_event_enabled"
+ is_exported: true
+ namespace: "nfc"
+ description: "Enabling security log for nfc state change"
+ bug: "319934052"
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index c2506d353d14..307e5875affb 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -30,9 +30,10 @@ import android.hardware.usb.flags.Flags;
import android.icu.text.NumberFormat;
import android.location.LocationManager;
import android.media.AudioManager;
+import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.net.TetheringManager;
-import android.net.vcn.VcnTransportInfo;
+import android.net.vcn.VcnUtils;
import android.net.wifi.WifiInfo;
import android.os.BatteryManager;
import android.os.Build;
@@ -739,14 +740,9 @@ public class Utils {
* @param networkCapabilities NetworkCapabilities of the network.
*/
@Nullable
- public static WifiInfo tryGetWifiInfoForVcn(NetworkCapabilities networkCapabilities) {
- if (networkCapabilities.getTransportInfo() == null
- || !(networkCapabilities.getTransportInfo() instanceof VcnTransportInfo)) {
- return null;
- }
- VcnTransportInfo vcnTransportInfo =
- (VcnTransportInfo) networkCapabilities.getTransportInfo();
- return vcnTransportInfo.getWifiInfo();
+ public static WifiInfo tryGetWifiInfoForVcn(
+ ConnectivityManager connectivityMgr, NetworkCapabilities networkCapabilities) {
+ return VcnUtils.getWifiInfoFromVcnCaps(connectivityMgr, networkCapabilities);
}
/** Whether there is any incompatible chargers in the current UsbPort? */
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 015356e013b7..cea3d17f116d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -30,6 +30,7 @@ import android.net.NetworkScoreManager;
import android.net.ScoredNetwork;
import android.net.TransportInfo;
import android.net.vcn.VcnTransportInfo;
+import android.net.vcn.VcnUtils;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiNetworkScoreCache;
@@ -394,10 +395,7 @@ public class WifiStatusTracker {
TransportInfo transportInfo = networkCapabilities.getTransportInfo();
if (transportInfo instanceof VcnTransportInfo) {
- // This VcnTransportInfo logic is copied from
- // [com.android.settingslib.Utils.tryGetWifiInfoForVcn]. It's copied instead of
- // re-used because it makes the logic here clearer.
- return ((VcnTransportInfo) transportInfo).getWifiInfo();
+ return VcnUtils.getWifiInfoFromVcnCaps(mConnectivityManager, networkCapabilities);
} else if (transportInfo instanceof WifiInfo) {
return (WifiInfo) transportInfo;
} else {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index d3d30dfcea3a..fc7802c9f9da 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -586,7 +586,7 @@ final class SettingsState {
flag.getPackageName(),
flag.getFlagName(),
flag.getServerFlagValue(),
- false);
+ StorageRequestMessage.SERVER_ON_REBOOT);
}
if (flag.getHasLocalOverride()) {
@@ -595,7 +595,7 @@ final class SettingsState {
flag.getPackageName(),
flag.getFlagName(),
flag.getLocalFlagValue(),
- true);
+ StorageRequestMessage.LOCAL_ON_REBOOT);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
index e3c47a43aad4..321593b6ada4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
@@ -596,7 +596,8 @@ public class NetworkControllerImpl extends BroadcastReceiver
// NetworkCapabilities, but we need to convert it into TRANSPORT_WIFI in order to
// distinguish it from VCN over Cellular.
if (transportTypes[i] == NetworkCapabilities.TRANSPORT_CELLULAR
- && Utils.tryGetWifiInfoForVcn(networkCapabilities) != null) {
+ && Utils.tryGetWifiInfoForVcn(mConnectivityManager, networkCapabilities)
+ != null) {
transportTypes[i] = NetworkCapabilities.TRANSPORT_WIFI;
break;
}
@@ -1112,7 +1113,9 @@ public class NetworkControllerImpl extends BroadcastReceiver
continue;
}
if (transportType == NetworkCapabilities.TRANSPORT_CELLULAR
- && Utils.tryGetWifiInfoForVcn(mLastDefaultNetworkCapabilities) != null) {
+ && Utils.tryGetWifiInfoForVcn(
+ mConnectivityManager, mLastDefaultNetworkCapabilities)
+ != null) {
mConnectedTransports.set(NetworkCapabilities.TRANSPORT_WIFI);
if (mLastDefaultNetworkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) {
mValidatedTransports.set(NetworkCapabilities.TRANSPORT_WIFI);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
index 98315d0ca3c9..83dbfa0682ad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
@@ -95,6 +95,7 @@ import org.mockito.MockitoSession;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
public class NetworkControllerBaseTest extends SysuiTestCase {
@@ -332,10 +333,15 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
}
public void setConnectivityViaCallbackInNetworkControllerForVcn(
- int networkType, boolean validated, boolean isConnected, VcnTransportInfo info) {
+ int networkType,
+ boolean validated,
+ boolean isConnected,
+ VcnTransportInfo info,
+ Network underlyingNetwork) {
final NetworkCapabilities.Builder builder =
new NetworkCapabilities.Builder(mNetCapabilities);
- builder.setTransportInfo(info);
+ builder.setTransportInfo(info)
+ .setUnderlyingNetworks(Collections.singletonList(underlyingNetwork));
setConnectivityCommon(builder, networkType, validated, isConnected);
mDefaultCallbackInNetworkController.onCapabilitiesChanged(
mock(Network.class), builder.build());
@@ -385,10 +391,15 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
}
public void setConnectivityViaCallbackInWifiTrackerForVcn(
- int networkType, boolean validated, boolean isConnected, VcnTransportInfo info) {
+ int networkType,
+ boolean validated,
+ boolean isConnected,
+ VcnTransportInfo info,
+ Network underlyingNetwork) {
final NetworkCapabilities.Builder builder =
new NetworkCapabilities.Builder(mNetCapabilities);
- builder.setTransportInfo(info);
+ builder.setTransportInfo(info)
+ .setUnderlyingNetworks(Collections.singletonList(underlyingNetwork));
setConnectivityCommon(builder, networkType, validated, isConnected);
if (networkType == NetworkCapabilities.TRANSPORT_CELLULAR) {
if (isConnected) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java
index 6c80a97625a7..6febb91db992 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerWifiTest.java
@@ -18,6 +18,7 @@ package com.android.systemui.statusbar.connectivity;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static junit.framework.Assert.assertEquals;
@@ -250,6 +251,17 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest {
assertEquals(testSsid, mNetworkController.mWifiSignalController.mCurrentState.ssid);
}
+ private Network newWifiNetwork(WifiInfo wifiInfo) {
+ final Network network = mock(Network.class);
+ final NetworkCapabilities wifiCaps =
+ new NetworkCapabilities.Builder()
+ .addTransportType(TRANSPORT_WIFI)
+ .setTransportInfo(wifiInfo)
+ .build();
+ when(mMockCm.getNetworkCapabilities(network)).thenReturn(wifiCaps);
+ return network;
+ }
+
@Test
public void testVcnWithUnderlyingWifi() {
String testSsid = "Test VCN SSID";
@@ -266,11 +278,19 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest {
setWifiLevelForVcn(testLevel);
setConnectivityViaCallbackInNetworkControllerForVcn(
- NetworkCapabilities.TRANSPORT_CELLULAR, true, true, mVcnTransportInfo);
+ NetworkCapabilities.TRANSPORT_CELLULAR,
+ true,
+ true,
+ mVcnTransportInfo,
+ newWifiNetwork(mWifiInfo));
verifyLastMobileDataIndicatorsForVcn(true, testLevel, TelephonyIcons.ICON_CWF, true);
setConnectivityViaCallbackInNetworkControllerForVcn(
- NetworkCapabilities.TRANSPORT_CELLULAR, false, true, mVcnTransportInfo);
+ NetworkCapabilities.TRANSPORT_CELLULAR,
+ false,
+ true,
+ mVcnTransportInfo,
+ newWifiNetwork(mWifiInfo));
verifyLastMobileDataIndicatorsForVcn(true, testLevel, TelephonyIcons.ICON_CWF, false);
}
}
@@ -391,13 +411,15 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest {
}
protected void setWifiLevelForVcn(int level) {
- when(mVcnTransportInfo.getWifiInfo()).thenReturn(mWifiInfo);
- when(mVcnTransportInfo.makeCopy(anyLong())).thenReturn(mVcnTransportInfo);
when(mWifiInfo.getRssi()).thenReturn(calculateRssiForLevel(level));
when(mWifiInfo.isCarrierMerged()).thenReturn(true);
when(mWifiInfo.getSubscriptionId()).thenReturn(1);
setConnectivityViaCallbackInWifiTrackerForVcn(
- NetworkCapabilities.TRANSPORT_CELLULAR, false, true, mVcnTransportInfo);
+ NetworkCapabilities.TRANSPORT_CELLULAR,
+ false,
+ true,
+ mVcnTransportInfo,
+ newWifiNetwork(mWifiInfo));
}
private int calculateRssiForLevel(int level) {
@@ -409,13 +431,15 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest {
}
protected void setWifiStateForVcn(boolean connected, String ssid) {
- when(mVcnTransportInfo.getWifiInfo()).thenReturn(mWifiInfo);
- when(mVcnTransportInfo.makeCopy(anyLong())).thenReturn(mVcnTransportInfo);
when(mWifiInfo.getSSID()).thenReturn(ssid);
when(mWifiInfo.isCarrierMerged()).thenReturn(true);
when(mWifiInfo.getSubscriptionId()).thenReturn(1);
setConnectivityViaCallbackInWifiTrackerForVcn(
- NetworkCapabilities.TRANSPORT_CELLULAR, false, connected, mVcnTransportInfo);
+ NetworkCapabilities.TRANSPORT_CELLULAR,
+ false,
+ connected,
+ mVcnTransportInfo,
+ newWifiNetwork(mWifiInfo));
}
protected void verifyLastQsDataDirection(boolean in, boolean out) {
diff --git a/ravenwood/TEST_MAPPING b/ravenwood/TEST_MAPPING
index 86246e2dcc2a..72f62c5c29ee 100644
--- a/ravenwood/TEST_MAPPING
+++ b/ravenwood/TEST_MAPPING
@@ -5,7 +5,8 @@
{ "name": "hoststubgen-test-tiny-test" },
{ "name": "hoststubgen-invoke-test" },
{ "name": "RavenwoodMockitoTest_device" },
- { "name": "RavenwoodBivalentTest_device" },
+ // TODO(b/371215487): Re-enable when the test is fixed.
+ // { "name": "RavenwoodBivalentTest_device" },
{ "name": "RavenwoodBivalentInstTest_nonself_inst" },
{ "name": "RavenwoodBivalentInstTest_self_inst_device" },
diff --git a/ravenwood/runtime-common-src/com/android/ravenwood/common/RavenwoodCommonUtils.java b/ravenwood/runtime-common-src/com/android/ravenwood/common/RavenwoodCommonUtils.java
index ef795c63880e..520f050f0655 100644
--- a/ravenwood/runtime-common-src/com/android/ravenwood/common/RavenwoodCommonUtils.java
+++ b/ravenwood/runtime-common-src/com/android/ravenwood/common/RavenwoodCommonUtils.java
@@ -37,8 +37,6 @@ public class RavenwoodCommonUtils {
private RavenwoodCommonUtils() {
}
- private static final Object sLock = new Object();
-
/**
* If set to "1", we enable the verbose logging.
*
@@ -68,9 +66,6 @@ public class RavenwoodCommonUtils {
public static final String RAVENWOOD_VERSION_JAVA_SYSPROP = "android.ravenwood.version";
- // @GuardedBy("sLock")
- private static boolean sIntegrityChecked = false;
-
/**
* @return if we're running on Ravenwood.
*/
diff --git a/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NativeAllocationRegistry.java b/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NativeAllocationRegistry.java
index 4e7dc5d6264f..ad86135de32e 100644
--- a/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NativeAllocationRegistry.java
+++ b/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NativeAllocationRegistry.java
@@ -32,25 +32,20 @@ public class NativeAllocationRegistry {
public static NativeAllocationRegistry createNonmalloced(
ClassLoader classLoader, long freeFunction, long size) {
- return new NativeAllocationRegistry(classLoader, freeFunction, size, false);
+ return new NativeAllocationRegistry(classLoader, freeFunction, size);
}
public static NativeAllocationRegistry createMalloced(
ClassLoader classLoader, long freeFunction, long size) {
- return new NativeAllocationRegistry(classLoader, freeFunction, size, true);
+ return new NativeAllocationRegistry(classLoader, freeFunction, size);
}
public static NativeAllocationRegistry createMalloced(
ClassLoader classLoader, long freeFunction) {
- return new NativeAllocationRegistry(classLoader, freeFunction, 0, true);
+ return new NativeAllocationRegistry(classLoader, freeFunction, 0);
}
public NativeAllocationRegistry(ClassLoader classLoader, long freeFunction, long size) {
- this(classLoader, freeFunction, size, size == 0);
- }
-
- private NativeAllocationRegistry(ClassLoader classLoader, long freeFunction, long size,
- boolean mallocAllocation) {
if (size < 0) {
throw new IllegalArgumentException("Invalid native allocation size: " + size);
}
diff --git a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/coretest/RavenwoodMockitoTest.java b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/coretest/RavenwoodMockitoTest.java
index dd6d259d5a34..31884b6bfc57 100644
--- a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/coretest/RavenwoodMockitoTest.java
+++ b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/coretest/RavenwoodMockitoTest.java
@@ -16,11 +16,19 @@
package com.android.ravenwoodtest.coretest;
import static org.junit.Assert.assertThrows;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
import org.junit.Test;
public class RavenwoodMockitoTest {
+ private static class MockClass {
+ void foo() {
+ throw new RuntimeException("Unsupported!!");
+ }
+ }
+
@Test
public void checkMockitoClasses() {
// DexMaker should not exist
@@ -32,4 +40,11 @@ public class RavenwoodMockitoTest {
ClassNotFoundException.class,
() -> Class.forName("org.mockito.Matchers"));
}
+
+ @Test
+ public void checkMockitoActuallyWorks() {
+ var mock = mock(MockClass.class);
+ doNothing().when(mock).foo();
+ mock.foo();
+ }
}
diff --git a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt
index 49f0b599762f..e67c730df069 100644
--- a/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt
+++ b/ravenwood/tools/ravenizer/src/com/android/platform/test/ravenwood/ravenizer/Ravenizer.kt
@@ -127,7 +127,7 @@ class Ravenizer {
}
}
if (includeUnsupportedMockito(allClasses)) {
- log.w("Unsupported Mockito detected in $inJar}!")
+ log.w("Unsupported Mockito detected in $inJar!")
}
stats.totalProcessTime = log.vTime("$executableName processing $inJar") {
diff --git a/services/core/java/com/android/server/hdmi/HdmiEarcController.java b/services/core/java/com/android/server/hdmi/HdmiEarcController.java
index 46a8f039584b..1c947e9d626d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiEarcController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiEarcController.java
@@ -87,8 +87,8 @@ final class HdmiEarcController {
} catch (ServiceSpecificException sse) {
HdmiLogger.error(
"Could not set eARC enabled to " + enabled + ". Error: ", sse.errorCode);
- } catch (RemoteException re) {
- HdmiLogger.error("Could not set eARC enabled to " + enabled + ":. Exception: ", re);
+ } catch (RemoteException | NullPointerException e) {
+ HdmiLogger.error("Could not set eARC enabled to " + enabled + ":. Exception: ", e);
}
}
@@ -96,8 +96,8 @@ final class HdmiEarcController {
public boolean nativeIsEarcEnabled() {
try {
return mEarc.isEArcEnabled();
- } catch (RemoteException re) {
- HdmiLogger.error("Could not read if eARC is enabled. Exception: ", re);
+ } catch (RemoteException | NullPointerException e) {
+ HdmiLogger.error("Could not read if eARC is enabled. Exception: ", e);
return false;
}
}
@@ -107,8 +107,8 @@ final class HdmiEarcController {
mEarcCallback = callback;
try {
mEarc.setCallback(callback);
- } catch (RemoteException re) {
- HdmiLogger.error("Could not set callback. Exception: ", re);
+ } catch (RemoteException | NullPointerException e) {
+ HdmiLogger.error("Could not set callback. Exception: ", e);
}
}
@@ -116,8 +116,8 @@ final class HdmiEarcController {
public byte nativeGetState(int portId) {
try {
return mEarc.getState(portId);
- } catch (RemoteException re) {
- HdmiLogger.error("Could not get eARC state. Exception: ", re);
+ } catch (RemoteException | NullPointerException e) {
+ HdmiLogger.error("Could not get eARC state. Exception: ", e);
return -1;
}
}
@@ -126,9 +126,9 @@ final class HdmiEarcController {
public byte[] nativeGetLastReportedAudioCapabilities(int portId) {
try {
return mEarc.getLastReportedAudioCapabilities(portId);
- } catch (RemoteException re) {
+ } catch (RemoteException | NullPointerException e) {
HdmiLogger.error(
- "Could not read last reported audio capabilities. Exception: ", re);
+ "Could not read last reported audio capabilities. Exception: ", e);
return null;
}
}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 3780fbd61e79..bbdac5636fa4 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -99,6 +99,7 @@ import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.ShellCallback;
+import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
@@ -126,6 +127,7 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.LongSparseArray;
+import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
@@ -253,6 +255,8 @@ public class LockSettingsService extends ILockSettings.Stub {
private static final String MIGRATED_KEYSTORE_NS = "migrated_keystore_namespace";
private static final String MIGRATED_SP_CE_ONLY = "migrated_all_users_to_sp_and_bound_ce";
private static final String MIGRATED_SP_FULL = "migrated_all_users_to_sp_and_bound_keys";
+ private static final String MIGRATED_WEAVER_DISABLED_ON_UNSECURED_USERS =
+ "migrated_weaver_disabled_on_unsecured_users";
// Duration that LockSettingsService will store the gatekeeper password for. This allows
// multiple biometric enrollments without prompting the user to enter their password via
@@ -309,6 +313,10 @@ public class LockSettingsService extends ILockSettings.Stub {
@GuardedBy("mUserCreationAndRemovalLock")
private boolean mThirdPartyAppsStarted;
+ // This list contains the (protectorId, userId) of any protectors that were by replaced by a
+ // migration and should be destroyed once rollback to the old build is no longer possible.
+ private ArrayList<Pair<Long, Integer>> mProtectorsToDestroyOnBootCompleted = new ArrayList<>();
+
// Current password metrics for all secured users on the device. Updated when user unlocks the
// device or changes password. Removed if user is stopped with its CE key evicted.
@GuardedBy("this")
@@ -363,6 +371,10 @@ public class LockSettingsService extends ILockSettings.Stub {
mLockSettingsService.migrateOldDataAfterSystemReady();
mLockSettingsService.deleteRepairModePersistentDataIfNeeded();
} else if (phase == PHASE_BOOT_COMPLETED) {
+ // In the case of an upgrade, PHASE_BOOT_COMPLETED means that a rollback to the old
+ // build can no longer occur. This is the time to destroy any migrated protectors.
+ mLockSettingsService.destroyMigratedProtectors();
+
mLockSettingsService.loadEscrowData();
}
}
@@ -1076,6 +1088,11 @@ public class LockSettingsService extends ILockSettings.Stub {
mStorage.deleteRepairModePersistentData();
}
+ private boolean isWeaverDisabledOnUnsecuredUsers() {
+ return mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_disableWeaverOnUnsecuredUsers);
+ }
+
// This is called when Weaver is guaranteed to be available (if the device supports Weaver).
// It does any synthetic password related work that was delayed from earlier in the boot.
private void onThirdPartyAppsStarted() {
@@ -1114,13 +1131,20 @@ public class LockSettingsService extends ILockSettings.Stub {
//
// - Upgrading from Android 14, where unsecured users didn't have Keystore super keys.
//
+ // - Upgrading from a build with config_disableWeaverOnUnsecuredUsers=false to one with
+ // config_disableWeaverOnUnsecuredUsers=true. (We don't bother to proactively add
+ // Weaver for the reverse update to false, as it's too late to help in that case.)
+ //
// The end result is that all users, regardless of whether they are secured or not, have
- // a synthetic password with all keys initialized and protected by it.
+ // a synthetic password with all keys initialized and protected by it, and honoring
+ // config_disableWeaverOnUnsecuredUsers=true when applicable.
//
// Note: if this migration gets interrupted (e.g. by the device powering off), there
// shouldn't be a problem since this will run again on the next boot, and
// setCeStorageProtection() and initKeystoreSuperKeys(..., true) are idempotent.
- if (!getBoolean(MIGRATED_SP_FULL, false, 0)) {
+ if (!getBoolean(MIGRATED_SP_FULL, false, 0)
+ || (isWeaverDisabledOnUnsecuredUsers()
+ && !getBoolean(MIGRATED_WEAVER_DISABLED_ON_UNSECURED_USERS, false, 0))) {
for (UserInfo user : mUserManager.getAliveUsers()) {
removeStateForReusedUserIdIfNecessary(user.id, user.serialNumber);
synchronized (mSpManager) {
@@ -1128,6 +1152,9 @@ public class LockSettingsService extends ILockSettings.Stub {
}
}
setBoolean(MIGRATED_SP_FULL, true, 0);
+ if (isWeaverDisabledOnUnsecuredUsers()) {
+ setBoolean(MIGRATED_WEAVER_DISABLED_ON_UNSECURED_USERS, true, 0);
+ }
}
mThirdPartyAppsStarted = true;
@@ -1151,13 +1178,61 @@ public class LockSettingsService extends ILockSettings.Stub {
getGateKeeperService(), protectorId, LockscreenCredential.createNone(), userId,
null);
SyntheticPassword sp = result.syntheticPassword;
- if (sp == null) {
+ if (isWeaverDisabledOnUnsecuredUsers()) {
+ Slog.i(TAG, "config_disableWeaverOnUnsecuredUsers=true");
+
+ // If config_disableWeaverOnUnsecuredUsers=true, then the Weaver HAL may be buggy and
+ // need multiple retries before it works here to unwrap the SP, if the SP was already
+ // protected by Weaver. Note that the problematic HAL can also deadlock if called with
+ // the ActivityManagerService lock held, but that should not be a problem here since
+ // that lock isn't held here, unlike unlockUserKeyIfUnsecured() where it is.
+ for (int i = 0; i < 12 && sp == null; i++) {
+ Slog.e(TAG, "Failed to unwrap synthetic password. Waiting 5 seconds to retry.");
+ SystemClock.sleep(5000);
+ result = mSpManager.unlockLskfBasedProtector(getGateKeeperService(), protectorId,
+ LockscreenCredential.createNone(), userId, null);
+ sp = result.syntheticPassword;
+ }
+ if (sp == null) {
+ throw new IllegalStateException(
+ "Failed to unwrap synthetic password for unsecured user");
+ }
+ // If the SP is protected by Weaver, then remove the Weaver protection in order to make
+ // config_disableWeaverOnUnsecuredUsers=true take effect.
+ if (result.usedWeaver) {
+ Slog.i(TAG, "Removing Weaver protection from the synthetic password");
+ // Create a new protector, which will not use Weaver.
+ long newProtectorId = mSpManager.createLskfBasedProtector(
+ getGateKeeperService(), LockscreenCredential.createNone(), sp, userId);
+
+ // Out of paranoia, make sure the new protector really works.
+ result = mSpManager.unlockLskfBasedProtector(getGateKeeperService(),
+ newProtectorId, LockscreenCredential.createNone(), userId, null);
+ sp = result.syntheticPassword;
+ if (sp == null) {
+ throw new IllegalStateException("New SP protector does not work");
+ }
+
+ // Replace the protector. Wait until PHASE_BOOT_COMPLETED to destroy the old
+ // protector, since the Weaver slot erasure and freeing cannot be rolled back.
+ setCurrentLskfBasedProtectorId(newProtectorId, userId);
+ mProtectorsToDestroyOnBootCompleted.add(new Pair(protectorId, userId));
+ } else {
+ Slog.i(TAG, "Synthetic password is already not protected by Weaver");
+ }
+ } else if (sp == null) {
Slogf.wtf(TAG, "Failed to unwrap synthetic password for unsecured user %d", userId);
return;
}
- // While setCeStorageProtection() is idempotent, it does log some error messages when called
- // again. Skip it if we know it was already handled by an earlier upgrade to Android 14.
- if (getString(MIGRATED_SP_CE_ONLY, null, 0) == null) {
+
+ // Call setCeStorageProtection(), to re-encrypt the CE key with the SP if it's currently
+ // encrypted by an empty secret. Skip this if it was definitely already done as part of the
+ // upgrade to Android 14, since while setCeStorageProtection() is idempotent it does log
+ // some error messages when called again. Do not skip this if
+ // config_disableWeaverOnUnsecuredUsers=true, since in that case we'd like to recover from
+ // the case where an earlier upgrade to Android 14 incorrectly skipped this step.
+ if (getString(MIGRATED_SP_CE_ONLY, null, 0) == null
+ || isWeaverDisabledOnUnsecuredUsers()) {
Slogf.i(TAG, "Encrypting CE key of user %d with synthetic password", userId);
setCeStorageProtection(userId, sp);
}
@@ -1165,6 +1240,17 @@ public class LockSettingsService extends ILockSettings.Stub {
initKeystoreSuperKeys(userId, sp, /* allowExisting= */ true);
}
+ private void destroyMigratedProtectors() {
+ if (!mProtectorsToDestroyOnBootCompleted.isEmpty()) {
+ synchronized (mSpManager) {
+ for (Pair<Long, Integer> pair : mProtectorsToDestroyOnBootCompleted) {
+ mSpManager.destroyLskfBasedProtector(pair.first, pair.second);
+ }
+ }
+ }
+ mProtectorsToDestroyOnBootCompleted = null; // The list is no longer needed.
+ }
+
/**
* Returns the lowest password quality that still presents the same UI for entering it.
*
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index 3a429b041b3c..47788f2e7d2f 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -195,6 +195,8 @@ class SyntheticPasswordManager {
// ERROR: password / token fails verification
// RETRY: password / token verification is throttled at the moment.
@Nullable public VerifyCredentialResponse gkResponse;
+ // For unlockLskfBasedProtector() this is set to true if the protector uses Weaver.
+ public boolean usedWeaver;
}
/**
@@ -532,6 +534,11 @@ class SyntheticPasswordManager {
Settings.Global.DEVICE_PROVISIONED, 0) != 0;
}
+ private boolean isWeaverDisabledOnUnsecuredUsers() {
+ return mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_disableWeaverOnUnsecuredUsers);
+ }
+
@VisibleForTesting
protected android.hardware.weaver.V1_0.IWeaver getWeaverHidlService() throws RemoteException {
try {
@@ -1011,7 +1018,13 @@ class SyntheticPasswordManager {
Slogf.i(TAG, "Creating LSKF-based protector %016x for user %d", protectorId, userId);
- final IWeaver weaver = getWeaverService();
+ final IWeaver weaver;
+ if (credential.isNone() && isWeaverDisabledOnUnsecuredUsers()) {
+ weaver = null;
+ Slog.w(TAG, "Not using Weaver for unsecured user (disabled by config)");
+ } else {
+ weaver = getWeaverService();
+ }
if (weaver != null) {
// Weaver is available, so make the protector use it to verify the LSKF. Do this even
// if the LSKF is empty, as that gives us support for securely deleting the protector.
@@ -1404,6 +1417,7 @@ class SyntheticPasswordManager {
int weaverSlot = loadWeaverSlot(protectorId, userId);
if (weaverSlot != INVALID_WEAVER_SLOT) {
// Protector uses Weaver to verify the LSKF
+ result.usedWeaver = true;
final IWeaver weaver = getWeaverService();
if (weaver == null) {
Slog.e(TAG, "Protector uses Weaver, but Weaver is unavailable");
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 5d71439e8f46..458b46dab54c 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -592,7 +592,7 @@ public abstract class ApexManager {
return apexSessionInfo;
} catch (RemoteException re) {
Slog.e(TAG, "Unable to contact apexservice", re);
- throw new RuntimeException(re);
+ return null;
}
}
@@ -607,7 +607,7 @@ public abstract class ApexManager {
return result;
} catch (RemoteException re) {
Slog.e(TAG, "Unable to contact apexservice", re);
- throw new RuntimeException(re);
+ return new SparseArray<>(0);
}
}
@@ -619,7 +619,9 @@ public abstract class ApexManager {
return apexInfoList;
} catch (RemoteException re) {
Slog.e(TAG, "Unable to contact apexservice", re);
- throw new RuntimeException(re);
+ throw new PackageManagerException(
+ PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
+ "apexd verification failed : " + re.getMessage());
} catch (Exception e) {
throw new PackageManagerException(
PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
@@ -633,7 +635,7 @@ public abstract class ApexManager {
return waitForApexService().getStagedApexInfos(params);
} catch (RemoteException re) {
Slog.w(TAG, "Unable to contact apexservice" + re.getMessage());
- throw new RuntimeException(re);
+ return new ApexInfo[0];
} catch (Exception e) {
Slog.w(TAG, "Failed to collect staged apex infos" + e.getMessage());
return new ApexInfo[0];
@@ -646,7 +648,9 @@ public abstract class ApexManager {
waitForApexService().markStagedSessionReady(sessionId);
} catch (RemoteException re) {
Slog.e(TAG, "Unable to contact apexservice", re);
- throw new RuntimeException(re);
+ throw new PackageManagerException(
+ PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
+ "Failed to mark apexd session as ready : " + re.getMessage());
} catch (Exception e) {
throw new PackageManagerException(
PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index f1d858fa1f6c..cc780132e0f5 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -18578,11 +18578,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
toggleBackupServiceActive(caller.getUserId(), enabled);
- if (Flags.backupServiceSecurityLogEventEnabled()) {
- if (SecurityLog.isLoggingEnabled()) {
- SecurityLog.writeEvent(SecurityLog.TAG_BACKUP_SERVICE_TOGGLED,
- caller.getPackageName(), caller.getUserId(), enabled ? 1 : 0);
- }
+ if (SecurityLog.isLoggingEnabled()) {
+ SecurityLog.writeEvent(SecurityLog.TAG_BACKUP_SERVICE_TOGGLED,
+ caller.getPackageName(), caller.getUserId(), enabled ? 1 : 0);
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java
index d08cdc718a82..769f071e3ddc 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java
@@ -265,19 +265,19 @@ public class ApexManagerTest {
}
@Test
- public void testSubmitStagedSession_throwRunTimeException() throws RemoteException {
+ public void testSubmitStagedSession_throwPackageManagerExceptionOnRemoteException()
+ throws RemoteException {
doThrow(RemoteException.class).when(mApexService).submitStagedSession(any(), any());
- assertThrows(RuntimeException.class,
+ assertThrows(PackageManagerException.class,
() -> mApexManager.submitStagedSession(testParamsWithChildren()));
}
@Test
- public void testGetStagedApexInfos_throwRunTimeException() throws RemoteException {
+ public void testGetStagedApexInfos_returnsEmptyOnRemoteException() throws RemoteException {
doThrow(RemoteException.class).when(mApexService).getStagedApexInfos(any());
- assertThrows(RuntimeException.class,
- () -> mApexManager.getStagedApexInfos(testParamsWithChildren()));
+ assertThat(mApexManager.getStagedApexInfos(testParamsWithChildren())).hasLength(0);
}
@Test
@@ -298,10 +298,11 @@ public class ApexManagerTest {
}
@Test
- public void testMarkStagedSessionReady_throwRunTimeException() throws RemoteException {
+ public void testMarkStagedSessionReady_throwPackageManagerExceptionOnRemoteException()
+ throws RemoteException {
doThrow(RemoteException.class).when(mApexService).markStagedSessionReady(anyInt());
- assertThrows(RuntimeException.class,
+ assertThrows(PackageManagerException.class,
() -> mApexManager.markStagedSessionReady(TEST_SESSION_ID));
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS b/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS
index 5181af14ff65..aa22790022c5 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS
@@ -2,3 +2,4 @@ include /services/core/java/com/android/server/pm/OWNERS
per-file BackgroundDexOptServiceUnitTest.java = file:/services/core/java/com/android/server/pm/dex/OWNERS
per-file StagingManagerTest.java = dariofreni@google.com, ioffe@google.com, olilan@google.com
+per-file ApexManagerTest.java = dariofreni@google.com, ioffe@google.com, olilan@google.com
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java
index 50f3a88cc3a2..5bcddc41eb87 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/WeaverBasedSyntheticPasswordTests.java
@@ -1,6 +1,10 @@
package com.android.server.locksettings;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
import android.platform.test.annotations.Presubmit;
@@ -56,4 +60,44 @@ public class WeaverBasedSyntheticPasswordTests extends SyntheticPasswordTests {
mService.initializeSyntheticPassword(userId); // This should allocate a Weaver slot.
assertEquals(Sets.newHashSet(0), mPasswordSlotManager.getUsedSlots());
}
+
+ private int getNumUsedWeaverSlots() {
+ return mPasswordSlotManager.getUsedSlots().size();
+ }
+
+ @Test
+ public void testDisableWeaverOnUnsecuredUsers_false() {
+ final int userId = PRIMARY_USER_ID;
+ when(mResources.getBoolean(eq(
+ com.android.internal.R.bool.config_disableWeaverOnUnsecuredUsers)))
+ .thenReturn(false);
+ assertEquals(0, getNumUsedWeaverSlots());
+ mService.initializeSyntheticPassword(userId);
+ assertEquals(1, getNumUsedWeaverSlots());
+ assertTrue(mService.setLockCredential(newPassword("password"), nonePassword(), userId));
+ assertEquals(1, getNumUsedWeaverSlots());
+ assertTrue(mService.setLockCredential(nonePassword(), newPassword("password"), userId));
+ assertEquals(1, getNumUsedWeaverSlots());
+ }
+
+ @Test
+ public void testDisableWeaverOnUnsecuredUsers_true() {
+ final int userId = PRIMARY_USER_ID;
+ when(mResources.getBoolean(eq(
+ com.android.internal.R.bool.config_disableWeaverOnUnsecuredUsers)))
+ .thenReturn(true);
+ assertEquals(0, getNumUsedWeaverSlots());
+ mService.initializeSyntheticPassword(userId);
+ assertEquals(0, getNumUsedWeaverSlots());
+ assertTrue(mService.setLockCredential(newPassword("password"), nonePassword(), userId));
+ assertEquals(1, getNumUsedWeaverSlots());
+ assertTrue(mService.setLockCredential(nonePassword(), newPassword("password"), userId));
+ assertEquals(0, getNumUsedWeaverSlots());
+ }
+
+ @Test
+ public void testDisableWeaverOnUnsecuredUsers_defaultsToFalse() {
+ assertFalse(mResources.getBoolean(
+ com.android.internal.R.bool.config_disableWeaverOnUnsecuredUsers));
+ }
}
diff --git a/tests/FlickerTests/ActivityEmbedding/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/OWNERS
index 981b3168cdbb..981b3168cdbb 100644
--- a/tests/FlickerTests/ActivityEmbedding/OWNERS
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/OWNERS
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/OWNERS
new file mode 100644
index 000000000000..981b3168cdbb
--- /dev/null
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/close/OWNERS
@@ -0,0 +1 @@
+# Bug component: 1168918
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/OWNERS
new file mode 100644
index 000000000000..981b3168cdbb
--- /dev/null
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/layoutchange/OWNERS
@@ -0,0 +1 @@
+# Bug component: 1168918
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OWNERS
new file mode 100644
index 000000000000..981b3168cdbb
--- /dev/null
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/open/OWNERS
@@ -0,0 +1 @@
+# Bug component: 1168918
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/OWNERS
new file mode 100644
index 000000000000..981b3168cdbb
--- /dev/null
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/pip/OWNERS
@@ -0,0 +1 @@
+# Bug component: 1168918
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/OWNERS
new file mode 100644
index 000000000000..981b3168cdbb
--- /dev/null
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rotation/OWNERS
@@ -0,0 +1 @@
+# Bug component: 1168918
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rtl/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rtl/OWNERS
new file mode 100644
index 000000000000..981b3168cdbb
--- /dev/null
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/rtl/OWNERS
@@ -0,0 +1 @@
+# Bug component: 1168918
diff --git a/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/OWNERS b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/OWNERS
new file mode 100644
index 000000000000..981b3168cdbb
--- /dev/null
+++ b/tests/FlickerTests/ActivityEmbedding/src/com/android/server/wm/flicker/activityembedding/splitscreen/OWNERS
@@ -0,0 +1 @@
+# Bug component: 1168918
diff --git a/tests/Internal/src/com/android/internal/os/OWNERS b/tests/Internal/src/com/android/internal/os/OWNERS
new file mode 100644
index 000000000000..64ffa463bac1
--- /dev/null
+++ b/tests/Internal/src/com/android/internal/os/OWNERS
@@ -0,0 +1,2 @@
+# ApplicationSharedMemory
+per-file *ApplicationSharedMemory* = file:/PERFORMANCE_OWNERS
diff --git a/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java b/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java
index 81814b67f5ee..7bc9970629a6 100644
--- a/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java
@@ -25,6 +25,7 @@ import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
import android.net.NetworkCapabilities;
import android.net.wifi.WifiConfiguration;
@@ -39,6 +40,7 @@ public class VcnTransportInfoTest {
private static final int SUB_ID = 1;
private static final int NETWORK_ID = 5;
private static final int MIN_UDP_PORT_4500_NAT_TIMEOUT = 120;
+ private static final int MIN_UDP_PORT_4500_NAT_TIMEOUT_INVALID = 119;
private static final WifiInfo WIFI_INFO =
new WifiInfo.Builder().setNetworkId(NETWORK_ID).build();
@@ -48,6 +50,27 @@ public class VcnTransportInfoTest {
new VcnTransportInfo(WIFI_INFO, MIN_UDP_PORT_4500_NAT_TIMEOUT);
@Test
+ public void testBuilder() {
+ final VcnTransportInfo transportInfo =
+ new VcnTransportInfo.Builder()
+ .setMinUdpPort4500NatTimeoutSeconds(MIN_UDP_PORT_4500_NAT_TIMEOUT)
+ .build();
+
+ assertEquals(
+ MIN_UDP_PORT_4500_NAT_TIMEOUT, transportInfo.getMinUdpPort4500NatTimeoutSeconds());
+ }
+
+ @Test
+ public void testBuilder_withInvalidNatTimeout() {
+ try {
+ new VcnTransportInfo.Builder()
+ .setMinUdpPort4500NatTimeoutSeconds(MIN_UDP_PORT_4500_NAT_TIMEOUT_INVALID);
+ fail("Expected to fail due to invalid NAT timeout");
+ } catch (Exception expected) {
+ }
+ }
+
+ @Test
public void testGetWifiInfo() {
assertEquals(WIFI_INFO, WIFI_UNDERLYING_INFO.getWifiInfo());
diff --git a/tests/vcn/java/android/net/vcn/VcnUtilsTest.java b/tests/vcn/java/android/net/vcn/VcnUtilsTest.java
new file mode 100644
index 000000000000..3ce6c8f9386d
--- /dev/null
+++ b/tests/vcn/java/android/net/vcn/VcnUtilsTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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 android.net.vcn;
+
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.TelephonyNetworkSpecifier;
+import android.net.wifi.WifiInfo;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+public class VcnUtilsTest {
+ private static final int SUB_ID = 1;
+
+ private static final WifiInfo WIFI_INFO = new WifiInfo.Builder().build();
+ private static final TelephonyNetworkSpecifier TEL_NETWORK_SPECIFIER =
+ new TelephonyNetworkSpecifier.Builder().setSubscriptionId(SUB_ID).build();
+ private static final VcnTransportInfo VCN_TRANSPORT_INFO =
+ new VcnTransportInfo.Builder().build();
+
+ private ConnectivityManager mMockConnectivityManager;
+ private Network mMockWifiNetwork;
+ private Network mMockCellNetwork;
+
+ private NetworkCapabilities mVcnCapsWithUnderlyingWifi;
+ private NetworkCapabilities mVcnCapsWithUnderlyingCell;
+
+ @Before
+ public void setUp() {
+ mMockConnectivityManager = mock(ConnectivityManager.class);
+
+ mMockWifiNetwork = mock(Network.class);
+ mVcnCapsWithUnderlyingWifi = newVcnCaps(VCN_TRANSPORT_INFO, mMockWifiNetwork);
+ final NetworkCapabilities wifiCaps =
+ new NetworkCapabilities.Builder()
+ .addTransportType(TRANSPORT_WIFI)
+ .setTransportInfo(WIFI_INFO)
+ .build();
+ when(mMockConnectivityManager.getNetworkCapabilities(mMockWifiNetwork))
+ .thenReturn(wifiCaps);
+
+ mMockCellNetwork = mock(Network.class);
+ mVcnCapsWithUnderlyingCell = newVcnCaps(VCN_TRANSPORT_INFO, mMockCellNetwork);
+ final NetworkCapabilities cellCaps =
+ new NetworkCapabilities.Builder()
+ .addTransportType(TRANSPORT_CELLULAR)
+ .setNetworkSpecifier(TEL_NETWORK_SPECIFIER)
+ .build();
+ when(mMockConnectivityManager.getNetworkCapabilities(mMockCellNetwork))
+ .thenReturn(cellCaps);
+ }
+
+ private static NetworkCapabilities newVcnCaps(
+ VcnTransportInfo vcnTransportInfo, Network underlyingNetwork) {
+ return new NetworkCapabilities.Builder()
+ .setTransportInfo(vcnTransportInfo)
+ .setUnderlyingNetworks(Collections.singletonList(underlyingNetwork))
+ .build();
+ }
+
+ @Test
+ public void getWifiInfoFromVcnCaps() {
+ assertEquals(
+ WIFI_INFO,
+ VcnUtils.getWifiInfoFromVcnCaps(
+ mMockConnectivityManager, mVcnCapsWithUnderlyingWifi));
+ }
+
+ @Test
+ public void getWifiInfoFromVcnCaps_onVcnWithUnderlyingCell() {
+ assertNull(
+ VcnUtils.getWifiInfoFromVcnCaps(
+ mMockConnectivityManager, mVcnCapsWithUnderlyingCell));
+ }
+
+ @Test
+ public void getSubIdFromVcnCaps() {
+ assertEquals(
+ SUB_ID,
+ VcnUtils.getSubIdFromVcnCaps(mMockConnectivityManager, mVcnCapsWithUnderlyingCell));
+ }
+
+ @Test
+ public void getSubIdFromVcnCaps_onVcnWithUnderlyingWifi() {
+ assertEquals(
+ INVALID_SUBSCRIPTION_ID,
+ VcnUtils.getSubIdFromVcnCaps(mMockConnectivityManager, mVcnCapsWithUnderlyingWifi));
+ }
+
+ @Test
+ public void getSubIdFromVcnCaps_onNonVcnNetwork() {
+ assertEquals(
+ INVALID_SUBSCRIPTION_ID,
+ VcnUtils.getSubIdFromVcnCaps(
+ mMockConnectivityManager, new NetworkCapabilities.Builder().build()));
+ }
+
+ @Test
+ public void getSubIdFromVcnCaps_withMultipleUnderlyingNetworks() {
+ final NetworkCapabilities vcnCaps =
+ new NetworkCapabilities.Builder(mVcnCapsWithUnderlyingCell)
+ .setUnderlyingNetworks(
+ Arrays.asList(
+ new Network[] {mMockCellNetwork, mock(Network.class)}))
+ .build();
+ assertEquals(SUB_ID, VcnUtils.getSubIdFromVcnCaps(mMockConnectivityManager, vcnCaps));
+ }
+}