diff options
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)); + } +} |