Merge "Improve am --help wording" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 45f6570..fdd0505 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -121,6 +121,18 @@
     srcs: ["core/java/android/nfc/*.aconfig"],
 }
 
+cc_aconfig_library {
+    name: "android_nfc_flags_aconfig_c_lib",
+    vendor_available: true,
+    aconfig_declarations: "android.nfc.flags-aconfig",
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.nfcservices",
+        "nfc_nci.st21nfc.default",
+    ],
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
+
 java_aconfig_library {
     name: "android.nfc.flags-aconfig-java",
     aconfig_declarations: "android.nfc.flags-aconfig",
@@ -149,7 +161,7 @@
     name: "android.security.flags-aconfig-java-host",
     aconfig_declarations: "android.security.flags-aconfig",
     host_supported: true,
-    test: true,
+    mode: "test",
     defaults: ["framework-minus-apex-aconfig-java-defaults"],
 }
 
diff --git a/INPUT_OWNERS b/INPUT_OWNERS
index e02ba77..44b2f38 100644
--- a/INPUT_OWNERS
+++ b/INPUT_OWNERS
@@ -5,3 +5,5 @@
 prabirmsp@google.com
 svv@google.com
 vdevmurari@google.com
+
+per-file Virtual*=file:/services/companion/java/com/android/server/companion/virtual/OWNERS
diff --git a/api/Android.bp b/api/Android.bp
index 15b10a6..bd2b11a 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -83,7 +83,6 @@
         "framework-configinfrastructure",
         "framework-connectivity",
         "framework-connectivity-t",
-        "framework-crashrecovery",
         "framework-devicelock",
         "framework-graphics",
         "framework-healthfitness",
@@ -106,7 +105,6 @@
     system_server_classpath: [
         "service-art",
         "service-configinfrastructure",
-        "service-crashrecovery",
         "service-healthfitness",
         "service-media-s",
         "service-permission",
diff --git a/boot/Android.bp b/boot/Android.bp
index b33fab6..8a3d35e 100644
--- a/boot/Android.bp
+++ b/boot/Android.bp
@@ -84,10 +84,6 @@
             module: "com.android.conscrypt-bootclasspath-fragment",
         },
         {
-            apex: "com.android.crashrecovery",
-            module: "com.android.crashrecovery-bootclasspath-fragment",
-        },
-        {
             apex: "com.android.devicelock",
             module: "com.android.devicelock-bootclasspath-fragment",
         },
diff --git a/core/api/current.txt b/core/api/current.txt
index c9cba00..e392bd3 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -29105,14 +29105,17 @@
   }
 
   public final class NfcAdapter {
+    method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean allowTransaction();
     method public void disableForegroundDispatch(android.app.Activity);
     method public void disableReaderMode(android.app.Activity);
+    method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean disallowTransaction();
     method public void enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], String[][]);
     method public void enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle);
     method public static android.nfc.NfcAdapter getDefaultAdapter(android.content.Context);
     method @Nullable public android.nfc.NfcAntennaInfo getNfcAntennaInfo();
     method public boolean ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler);
     method public boolean isEnabled();
+    method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean isObserveModeSupported();
     method @FlaggedApi("android.nfc.enable_nfc_reader_option") public boolean isReaderOptionEnabled();
     method @FlaggedApi("android.nfc.enable_nfc_reader_option") public boolean isReaderOptionSupported();
     method public boolean isSecureNfcEnabled();
@@ -29220,6 +29223,7 @@
     method public boolean removeAidsForService(android.content.ComponentName, String);
     method @NonNull @RequiresPermission(android.Manifest.permission.NFC) public boolean setOffHostForService(@NonNull android.content.ComponentName, @NonNull String);
     method public boolean setPreferredService(android.app.Activity, android.content.ComponentName);
+    method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean setServiceObserveModeDefault(@NonNull android.content.ComponentName, boolean);
     method public boolean supportsAidPrefixRegistration();
     method @NonNull @RequiresPermission(android.Manifest.permission.NFC) public boolean unsetOffHostForService(@NonNull android.content.ComponentName);
     method public boolean unsetPreferredService(android.app.Activity);
@@ -29239,9 +29243,20 @@
     method public final android.os.IBinder onBind(android.content.Intent);
     method public abstract void onDeactivated(int);
     method public abstract byte[] processCommandApdu(byte[], android.os.Bundle);
+    method @FlaggedApi("android.nfc.nfc_read_polling_loop") public void processPollingFrames(@NonNull java.util.List<android.os.Bundle>);
     method public final void sendResponseApdu(byte[]);
     field public static final int DEACTIVATION_DESELECTED = 1; // 0x1
     field public static final int DEACTIVATION_LINK_LOSS = 0; // 0x0
+    field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final String POLLING_LOOP_DATA_KEY = "android.nfc.cardemulation.DATA";
+    field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final String POLLING_LOOP_GAIN_KEY = "android.nfc.cardemulation.GAIN";
+    field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final String POLLING_LOOP_TIMESTAMP_KEY = "android.nfc.cardemulation.TIMESTAMP";
+    field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_A = 65; // 0x0041 'A'
+    field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_B = 66; // 0x0042 'B'
+    field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_F = 70; // 0x0046 'F'
+    field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final String POLLING_LOOP_TYPE_KEY = "android.nfc.cardemulation.TYPE";
+    field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_OFF = 88; // 0x0058 'X'
+    field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_ON = 79; // 0x004f 'O'
+    field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final char POLLING_LOOP_TYPE_UNKNOWN = 85; // 0x0055 'U'
     field public static final String SERVICE_INTERFACE = "android.nfc.cardemulation.action.HOST_APDU_SERVICE";
     field public static final String SERVICE_META_DATA = "android.nfc.cardemulation.host_apdu_service";
   }
diff --git a/core/java/android/net/INetworkManagementEventObserver.aidl b/core/java/android/net/INetworkManagementEventObserver.aidl
index 0a6be20..eda80c8 100644
--- a/core/java/android/net/INetworkManagementEventObserver.aidl
+++ b/core/java/android/net/INetworkManagementEventObserver.aidl
@@ -85,14 +85,14 @@
     /**
      * Interface data activity status is changed.
      *
-     * @param transportType The transport type of the data activity change.
+     * @param label label of the data activity change.
      * @param active  True if the interface is actively transmitting data, false if it is idle.
      * @param tsNanos Elapsed realtime in nanos when the state of the network interface changed.
      * @param uid Uid of this event. It represents the uid that was responsible for waking the
      *            radio. For those events that are reported by system itself, not from specific uid,
      *            use -1 for the events which means no uid.
      */
-    void interfaceClassDataActivityChanged(int transportType, boolean active, long tsNanos, int uid);
+    void interfaceClassDataActivityChanged(int label, boolean active, long tsNanos, int uid);
 
     /**
      * Information about available DNS servers has been received.
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index 0c95c2e..f6beec1 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -84,4 +84,6 @@
     boolean isReaderOptionSupported();
     @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)")
     boolean enableReaderOption(boolean enable);
+    boolean isObserveModeSupported();
+    boolean setObserveMode(boolean enabled);
 }
diff --git a/core/java/android/nfc/INfcCardEmulation.aidl b/core/java/android/nfc/INfcCardEmulation.aidl
index c7b3b2c..191385a 100644
--- a/core/java/android/nfc/INfcCardEmulation.aidl
+++ b/core/java/android/nfc/INfcCardEmulation.aidl
@@ -30,6 +30,7 @@
     boolean isDefaultServiceForAid(int userHandle, in ComponentName service, String aid);
     boolean setDefaultServiceForCategory(int userHandle, in ComponentName service, String category);
     boolean setDefaultForNextTap(int userHandle, in ComponentName service);
+    boolean setServiceObserveModeDefault(int userId, in android.content.ComponentName service, boolean enable);
     boolean registerAidGroupForService(int userHandle, in ComponentName service, in AidGroup aidGroup);
     boolean setOffHostForService(int userHandle, in ComponentName service, in String offHostSecureElement);
     boolean unsetOffHostForService(int userHandle, in ComponentName service);
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index c897595..98a980f 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -1081,6 +1081,61 @@
         }
     }
 
+
+    /**
+     * Returns whether the device supports observer mode or not. When observe
+     * mode is enabled, the NFC hardware will listen for NFC readers, but not
+     * respond to them. When observe mode is disabled, the NFC hardware will
+     * resoond to the reader and proceed with the transaction.
+     * @return true if the mode is supported, false otherwise.
+     */
+    @FlaggedApi(Flags.FLAG_NFC_OBSERVE_MODE)
+    public boolean isObserveModeSupported() {
+        try {
+            return sService.isObserveModeSupported();
+        } catch (RemoteException e) {
+            attemptDeadServiceRecovery(e);
+            return false;
+        }
+    }
+
+   /**
+    * Disables observe mode to allow the transaction to proceed. See
+    * {@link #isObserveModeSupported()} for a description of observe mode and
+    * use {@link #disallowTransaction()} to enable observe mode and block
+    * transactions again.
+    *
+    * @return boolean indicating success or failure.
+    */
+    @FlaggedApi(Flags.FLAG_NFC_OBSERVE_MODE)
+    public boolean allowTransaction() {
+        try {
+            return sService.setObserveMode(false);
+        } catch (RemoteException e) {
+            attemptDeadServiceRecovery(e);
+            return false;
+        }
+    }
+
+    /**
+    * Signals that the transaction has completed and observe mode may be
+    * reenabled. See {@link #isObserveModeSupported()} for a description of
+    * observe mode and use {@link #allowTransaction()} to disable observe
+    * mode and allow transactions to proceed.
+    *
+    * @return boolean indicating success or failure.
+    */
+
+    @FlaggedApi(Flags.FLAG_NFC_OBSERVE_MODE)
+    public boolean disallowTransaction() {
+        try {
+            return sService.setObserveMode(true);
+        } catch (RemoteException e) {
+            attemptDeadServiceRecovery(e);
+            return false;
+        }
+    }
+
     /**
      * Resumes default polling for the current device state if polling is paused. Calling
      * this while polling is not paused is a no-op.
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index d048b59..58b6179 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -328,6 +328,24 @@
             return SELECTION_MODE_ASK_IF_CONFLICT;
         }
     }
+    /**
+     * Sets whether the system should default to observe mode or not when
+     * the service is in the foreground or the default payment service.
+     *
+     * @param service The component name of the service
+     * @param enable Whether the servic should default to observe mode or not
+     * @return whether the change was successful.
+     */
+    @FlaggedApi(Flags.FLAG_NFC_OBSERVE_MODE)
+    public boolean setServiceObserveModeDefault(@NonNull ComponentName service, boolean enable) {
+        try {
+            return sService.setServiceObserveModeDefault(mContext.getUser().getIdentifier(),
+                    service, enable);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to reach CardEmulationService.");
+        }
+        return  false;
+    }
 
     /**
      * Registers a list of AIDs for a specific category for the
diff --git a/core/java/android/nfc/cardemulation/HostApduService.java b/core/java/android/nfc/cardemulation/HostApduService.java
index 55d0e73..7cd2533 100644
--- a/core/java/android/nfc/cardemulation/HostApduService.java
+++ b/core/java/android/nfc/cardemulation/HostApduService.java
@@ -16,11 +16,14 @@
 
 package android.nfc.cardemulation;
 
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.app.Service;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.nfc.NfcAdapter;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -29,6 +32,9 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * <p>HostApduService is a convenience {@link Service} class that can be
  * extended to emulate an NFC card inside an Android
@@ -230,9 +236,99 @@
     /**
      * @hide
      */
+    public static final int MSG_POLLING_LOOP = 4;
+
+    /**
+     * @hide
+     */
     public static final String KEY_DATA = "data";
 
     /**
+     * POLLING_LOOP_TYPE_KEY is the Bundle key for the type of
+     * polling loop frame in the Bundle passed to {@link #processPollingFrames(List)}
+     */
+    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+    public static final String POLLING_LOOP_TYPE_KEY = "android.nfc.cardemulation.TYPE";
+
+    /**
+     * POLLING_LOOP_TYPE_A is the value associated with the key
+     * POLLING_LOOP_TYPE  in the Bundle passed to {@link #processPollingFrames(List)}
+     * when the polling loop is for NFC-A.
+     */
+    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+    public static final char POLLING_LOOP_TYPE_A = 'A';
+
+    /**
+     * POLLING_LOOP_TYPE_B is the value associated with the key
+     * POLLING_LOOP_TYPE  in the Bundle passed to {@link #processPollingFrames(List)}
+     * when the polling loop is for NFC-B.
+     */
+    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+    public static final char POLLING_LOOP_TYPE_B = 'B';
+
+    /**
+     * POLLING_LOOP_TYPE_F is the value associated with the key
+     * POLLING_LOOP_TYPE  in the Bundle passed to {@link #processPollingFrames(List)}
+     * when the polling loop is for NFC-F.
+     */
+    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+    public static final char POLLING_LOOP_TYPE_F = 'F';
+
+    /**
+     * POLLING_LOOP_TYPE_ON is the value associated with the key
+     * POLLING_LOOP_TYPE  in the Bundle passed to {@link #processPollingFrames(List)}
+     * when the polling loop turns on.
+     */
+    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+    public static final char POLLING_LOOP_TYPE_ON = 'O';
+
+    /**
+     * POLLING_LOOP_TYPE_OFF is the value associated with the key
+     * POLLING_LOOP_TYPE  in the Bundle passed to {@link #processPollingFrames(List)}
+     * when the polling loop turns off.
+     */
+    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+    public static final char POLLING_LOOP_TYPE_OFF = 'X';
+
+    /**
+     * POLLING_LOOP_TYPE_UNKNOWN is the value associated with the key
+     * POLLING_LOOP_TYPE  in the Bundle passed to {@link #processPollingFrames(List)}
+     * when the polling loop frame isn't recognized.
+     */
+    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+    public static final char POLLING_LOOP_TYPE_UNKNOWN = 'U';
+
+    /**
+     * POLLING_LOOP_DATA is the Bundle key for the raw data of captured from
+     * the polling loop frame in the Bundle passed to {@link #processPollingFrames(List)}
+     * when the frame type isn't recognized.
+     */
+    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+    public static final String POLLING_LOOP_DATA_KEY = "android.nfc.cardemulation.DATA";
+
+    /**
+     * POLLING_LOOP_GAIN_KEY is the Bundle key for the field strength of
+     * the polling loop frame in the Bundle passed to {@link #processPollingFrames(List)}
+     * when the frame type isn't recognized.
+     */
+    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+    public static final String POLLING_LOOP_GAIN_KEY = "android.nfc.cardemulation.GAIN";
+
+    /**
+     * POLLING_LOOP_TIMESTAMP_KEY is the Bundle key for the timestamp of
+     * the polling loop frame in the Bundle passed to {@link #processPollingFrames(List)}
+     * when the frame type isn't recognized.
+     */
+    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+    public static final String POLLING_LOOP_TIMESTAMP_KEY = "android.nfc.cardemulation.TIMESTAMP";
+
+    /**
+     * @hide
+     */
+    public static final String POLLING_LOOP_FRAMES_BUNDLE_KEY =
+            "android.nfc.cardemulation.POLLING_FRAMES";
+
+    /**
      * Messenger interface to NfcService for sending responses.
      * Only accessed on main thread by the message handler.
      *
@@ -255,6 +351,7 @@
 
                 byte[] apdu = dataBundle.getByteArray(KEY_DATA);
                 if (apdu != null) {
+                        HostApduService has = HostApduService.this;
                     byte[] responseApdu = processCommandApdu(apdu, null);
                     if (responseApdu != null) {
                         if (mNfcService == null) {
@@ -306,6 +403,12 @@
                     Log.e(TAG, "RemoteException calling into NfcService.");
                 }
                 break;
+                case MSG_POLLING_LOOP:
+                    ArrayList<Bundle> frames =
+                            msg.getData().getParcelableArrayList(POLLING_LOOP_FRAMES_BUNDLE_KEY,
+                            Bundle.class);
+                    processPollingFrames(frames);
+                    break;
             default:
                 super.handleMessage(msg);
             }
@@ -366,6 +469,21 @@
         }
     }
 
+    /**
+     * This method is called when a polling frame has been received from a
+     * remote device. If the device is in observe mode, the service should
+     * call {@link NfcAdapter#allowTransaction()} once it is ready to proceed
+     * with the transaction. If the device is not in observe mode, the service
+     * can use this polling frame information to determine how to proceed if it
+     * subsequently has {@link #processCommandApdu(byte[], Bundle)} called. The
+     * service must override this method inorder to receive polling frames,
+     * otherwise the base implementation drops the frame.
+     *
+     * @param frame A description of the polling frame.
+     */
+    @FlaggedApi(android.nfc.Flags.FLAG_NFC_READ_POLLING_LOOP)
+    public void processPollingFrames(@NonNull List<Bundle> frame) {
+    }
 
     /**
      * <p>This method will be called when a command APDU has been received
diff --git a/core/java/android/nfc/flags.aconfig b/core/java/android/nfc/flags.aconfig
index cd50ace..17e0427 100644
--- a/core/java/android/nfc/flags.aconfig
+++ b/core/java/android/nfc/flags.aconfig
@@ -20,3 +20,31 @@
     description: "Flag for NFC user restriction"
     bug: "291187960"
 }
+
+flag {
+    name: "nfc_observe_mode"
+    namespace: "nfc"
+    description: "Enable NFC Observe Mode"
+    bug: "294217286"
+}
+
+flag {
+    name: "nfc_read_polling_loop"
+    namespace: "nfc"
+    description: "Enable NFC Polling Loop Notifications"
+    bug: "294217286"
+}
+
+flag {
+    name: "nfc_observe_mode_st_shim"
+    namespace: "nfc"
+    description: "Enable NFC Observe Mode ST shim"
+    bug: "294217286"
+}
+
+flag {
+    name: "nfc_read_polling_loop_st_shim"
+    namespace: "nfc"
+    description: "Enable NFC Polling Loop Notifications ST shim"
+    bug: "294217286"
+}
diff --git a/core/java/android/os/DeadObjectException.java b/core/java/android/os/DeadObjectException.java
index e06b0f9..65ed618 100644
--- a/core/java/android/os/DeadObjectException.java
+++ b/core/java/android/os/DeadObjectException.java
@@ -19,7 +19,8 @@
 
 /**
  * The object you are calling has died, because its hosting process
- * no longer exists.
+ * no longer exists. This is also thrown for low-level binder
+ * errors.
  */
 public class DeadObjectException extends RemoteException {
     public DeadObjectException() {
diff --git a/core/java/android/os/DeadSystemRuntimeException.java b/core/java/android/os/DeadSystemRuntimeException.java
index 1e86924..82b1ad8 100644
--- a/core/java/android/os/DeadSystemRuntimeException.java
+++ b/core/java/android/os/DeadSystemRuntimeException.java
@@ -18,9 +18,10 @@
 
 /**
  * Exception thrown when a call into system_server resulted in a
- * DeadObjectException, meaning that the system_server has died.  There's
- * nothing apps can do at this point - the system will automatically restart -
- * so there's no point in catching this.
+ * DeadObjectException, meaning that the system_server has died or
+ * experienced a low-level binder error.  There's * nothing apps can
+ * do at this point - the system will automatically restart - so
+ * there's no point in catching this.
  *
  * @hide
  */
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index a3e0016..28fd2b4 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -1936,7 +1936,8 @@
      * If the user is not secured, ie doesn't have an LSKF, then decrypt the user's synthetic
      * password and use it to unlock various cryptographic keys associated with the user.  This
      * primarily includes unlocking the user's credential-encrypted (CE) storage.  It also includes
-     * deriving or decrypting the vendor auth secret and sending it to the AuthSecret HAL.
+     * unlocking the user's Keystore super keys, and deriving or decrypting the vendor auth secret
+     * and sending it to the AuthSecret HAL in order to unlock Secure Element firmware updates.
      * <p>
      * These tasks would normally be done when the LSKF is verified.  This method is where these
      * tasks are done when the user doesn't have an LSKF.  It's called when the user is started.
diff --git a/core/java/com/android/server/net/BaseNetworkObserver.java b/core/java/com/android/server/net/BaseNetworkObserver.java
index 139b88b..61e017d 100644
--- a/core/java/com/android/server/net/BaseNetworkObserver.java
+++ b/core/java/com/android/server/net/BaseNetworkObserver.java
@@ -64,7 +64,7 @@
     }
 
     @Override
-    public void interfaceClassDataActivityChanged(int transportType, boolean active, long tsNanos,
+    public void interfaceClassDataActivityChanged(int label, boolean active, long tsNanos,
             int uid) {
         // default no-op
     }
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index b1dab85..f9d00ed 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -212,14 +212,11 @@
             return (jint) AUDIORECORD_ERROR_SETUP_INVALIDFORMAT;
         }
 
-        size_t bytesPerSample = audio_bytes_per_sample(format);
-
         if (buffSizeInBytes == 0) {
             ALOGE("Error creating AudioRecord: frameCount is 0.");
             return (jint) AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT;
         }
-        size_t frameSize = channelCount * bytesPerSample;
-        size_t frameCount = buffSizeInBytes / frameSize;
+        size_t frameCount = buffSizeInBytes / audio_bytes_per_frame(channelCount, format);
 
         // create an uninitialized AudioRecord object
         Parcel* parcel = parcelForJavaObject(env, jAttributionSource);
@@ -574,7 +571,7 @@
     if (result != NO_ERROR) {
         return -1;
     }
-    return frameCount * channelCount * audio_bytes_per_sample(format);
+    return frameCount * audio_bytes_per_frame(channelCount, format);
 }
 
 static jboolean android_media_AudioRecord_setInputDevice(
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 6f7bc53..3413282 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4303,6 +4303,9 @@
         <!-- Whether the device must be screen on before routing data to this service.
              The default is true.-->
         <attr name="requireDeviceScreenOn" format="boolean"/>
+        <!-- Whether the device should default to observe mode when this service is
+             default or in the foreground. -->
+        <attr name="defaultToObserveMode" format="boolean"/>
     </declare-styleable>
 
     <!-- Use <code>offhost-apdu-service</code> as the root tag of the XML resource that
@@ -4327,6 +4330,9 @@
         <!-- Whether the device must be screen on before routing data to this service.
              The default is false.-->
         <attr name="requireDeviceScreenOn"/>
+        <!-- Whether the device should default to observe mode when this service is
+             default or in the foreground. -->
+        <attr name="defaultToObserveMode"/>
     </declare-styleable>
 
     <!-- Specify one or more <code>aid-group</code> elements inside a
diff --git a/keystore/java/android/security/AndroidKeyStoreMaintenance.java b/keystore/java/android/security/AndroidKeyStoreMaintenance.java
index b7ea04f..2beb434 100644
--- a/keystore/java/android/security/AndroidKeyStoreMaintenance.java
+++ b/keystore/java/android/security/AndroidKeyStoreMaintenance.java
@@ -51,7 +51,7 @@
      * @return 0 if successful or a {@code ResponseCode}
      * @hide
      */
-    public static int onUserAdded(@NonNull int userId) {
+    public static int onUserAdded(int userId) {
         StrictMode.noteDiskWrite();
         try {
             getService().onUserAdded(userId);
@@ -66,6 +66,30 @@
     }
 
     /**
+     * Tells Keystore to create a user's super keys and store them encrypted by the given secret.
+     *
+     * @param userId - Android user id of the user
+     * @param password - a secret derived from the user's synthetic password
+     * @param allowExisting - true if the keys already existing should not be considered an error
+     * @return 0 if successful or a {@code ResponseCode}
+     * @hide
+     */
+    public static int initUserSuperKeys(int userId, @NonNull byte[] password,
+            boolean allowExisting) {
+        StrictMode.noteDiskWrite();
+        try {
+            getService().initUserSuperKeys(userId, password, allowExisting);
+            return 0;
+        } catch (ServiceSpecificException e) {
+            Log.e(TAG, "initUserSuperKeys failed", e);
+            return e.errorCode;
+        } catch (Exception e) {
+            Log.e(TAG, "Can not connect to keystore", e);
+            return SYSTEM_ERROR;
+        }
+    }
+
+    /**
      * Informs Keystore 2.0 about removing a user
      *
      * @param userId - Android user id of the user being removed
@@ -110,6 +134,28 @@
     }
 
     /**
+     * Tells Keystore that a user's LSKF is being removed, ie the user's lock screen is changing to
+     * Swipe or None.  Keystore uses this notification to delete the user's auth-bound keys.
+     *
+     * @param userId - Android user id of the user
+     * @return 0 if successful or a {@code ResponseCode}
+     * @hide
+     */
+    public static int onUserLskfRemoved(int userId) {
+        StrictMode.noteDiskWrite();
+        try {
+            getService().onUserLskfRemoved(userId);
+            return 0;
+        } catch (ServiceSpecificException e) {
+            Log.e(TAG, "onUserLskfRemoved failed", e);
+            return e.errorCode;
+        } catch (Exception e) {
+            Log.e(TAG, "Can not connect to keystore", e);
+            return SYSTEM_ERROR;
+        }
+    }
+
+    /**
      * Informs Keystore 2.0 that an app was uninstalled and the corresponding namespace is to
      * be cleared.
      */
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 7faa13c..447d3bb 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -1176,6 +1176,7 @@
             case AudioFormat.ENCODING_PCM_FLOAT:
             case AudioFormat.ENCODING_PCM_16BIT:
             case AudioFormat.ENCODING_PCM_8BIT:
+            case AudioFormat.ENCODING_E_AC3_JOC:
                 mAudioFormat = audioFormat;
                 break;
             default:
@@ -1188,20 +1189,12 @@
 
 
     // Convenience method for the contructor's audio buffer size check.
-    // preconditions:
-    //    mChannelCount is valid
-    //    mAudioFormat is AudioFormat.ENCODING_PCM_8BIT, AudioFormat.ENCODING_PCM_16BIT,
-    //                 or AudioFormat.ENCODING_PCM_FLOAT
     // postcondition:
     //    mNativeBufferSizeInBytes is valid (multiple of frame size, positive)
     private void audioBuffSizeCheck(int audioBufferSize) throws IllegalArgumentException {
-        // NB: this section is only valid with PCM data.
-        // To update when supporting compressed formats
-        int frameSizeInBytes = mChannelCount
-            * (AudioFormat.getBytesPerSample(mAudioFormat));
-        if ((audioBufferSize % frameSizeInBytes != 0) || (audioBufferSize < 1)) {
+        if ((audioBufferSize % getFormat().getFrameSizeInBytes() != 0) || (audioBufferSize < 1)) {
             throw new IllegalArgumentException("Invalid audio buffer size " + audioBufferSize
-                    + " (frame size " + frameSizeInBytes + ")");
+                    + " (frame size " + getFormat().getFrameSizeInBytes() + ")");
         }
 
         mNativeBufferSizeInBytes = audioBufferSize;
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index dc6f858..7dac241 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -17,7 +17,6 @@
 package com.android.server.am;
 
 import static android.Manifest.permission.BATTERY_STATS;
-import static android.Manifest.permission.BLUETOOTH_CONNECT;
 import static android.Manifest.permission.DEVICE_POWER;
 import static android.Manifest.permission.NETWORK_STACK;
 import static android.Manifest.permission.POWER_SAVER;
@@ -103,6 +102,7 @@
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.util.ParseUtils;
 import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.modules.utils.build.SdkLevel;
 import com.android.net.module.util.NetworkCapabilitiesUtils;
 import com.android.server.LocalServices;
 import com.android.server.Watchdog;
@@ -426,7 +426,12 @@
                 ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
         final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
         try {
-            nms.registerObserver(mActivityChangeObserver);
+            if (!SdkLevel.isAtLeastV()) {
+                // On V+ devices, ConnectivityService calls BatteryStats API to update
+                // RadioPowerState change. So BatteryStatsService registers the callback only on
+                // pre V devices.
+                nms.registerObserver(mActivityChangeObserver);
+            }
             cm.registerDefaultNetworkCallback(mNetworkCallback);
         } catch (RemoteException e) {
             Slog.e(TAG, "Could not register INetworkManagement event observer " + e);
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index fa95a34..ec7f561 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -243,6 +243,10 @@
     private static final String MIGRATED_FRP2 = "migrated_frp2";
     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 boolean FIX_UNLOCKED_DEVICE_REQUIRED_KEYS =
+            android.security.Flags.fixUnlockedDeviceRequiredKeys();
 
     // Duration that LockSettingsService will store the gatekeeper password for. This allows
     // multiple biometric enrollments without prompting the user to enter their password via
@@ -853,9 +857,11 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             if (Intent.ACTION_USER_ADDED.equals(intent.getAction())) {
-                // Notify keystore that a new user was added.
-                final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
-                AndroidKeyStoreMaintenance.onUserAdded(userHandle);
+                if (!FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) {
+                    // Notify keystore that a new user was added.
+                    final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+                    AndroidKeyStoreMaintenance.onUserAdded(userHandle);
+                }
             } else if (Intent.ACTION_USER_STARTING.equals(intent.getAction())) {
                 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
                 mStorage.prefetchUser(userHandle);
@@ -1019,24 +1025,53 @@
             }
             mEarlyCreatedUsers = null; // no longer needed
 
-            // Also do a one-time migration of all users to SP-based credentials with the CE key
-            // encrypted by the SP.  This is needed for the system user on the first boot of a
-            // device, as the system user is special and never goes through the user creation flow
-            // that other users do.  It is also needed for existing users on a device upgraded from
-            // Android 13 or earlier, where users with no LSKF didn't necessarily have an SP, and if
-            // they did have an SP then their CE key wasn't encrypted by it.
+            // Do a one-time migration for any unsecured users: create the user's synthetic password
+            // if not already done, encrypt the user's CE key with the synthetic password if not
+            // already done, and create the user's Keystore super keys if not already done.
             //
-            // If this 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() is
-            // okay with the CE key being already protected by the given secret.
-            if (getString(MIGRATED_SP_CE_ONLY, null, 0) == null) {
-                for (UserInfo user : mUserManager.getAliveUsers()) {
-                    removeStateForReusedUserIdIfNecessary(user.id, user.serialNumber);
-                    synchronized (mSpManager) {
-                        migrateUserToSpWithBoundCeKeyLocked(user.id);
+            // This is needed for the following cases:
+            //
+            // - Finalizing the creation of the system user on the first boot of a device, as the
+            //   system user is special and doesn't go through the normal user creation flow.
+            //
+            // - Upgrading from Android 13 or earlier, where unsecured users didn't necessarily have
+            //   a synthetic password, and if they did have a synthetic password their CE key wasn't
+            //   encrypted by it.  Also, unsecured users didn't have Keystore super keys.
+            //
+            // - Upgrading from Android 14, where unsecured users didn't have Keystore super keys.
+            //
+            // 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.
+            //
+            // 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 (FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) {
+                if (!getBoolean(MIGRATED_SP_FULL, false, 0)) {
+                    for (UserInfo user : mUserManager.getAliveUsers()) {
+                        removeStateForReusedUserIdIfNecessary(user.id, user.serialNumber);
+                        synchronized (mSpManager) {
+                            migrateUserToSpWithBoundKeysLocked(user.id);
+                        }
                     }
+                    setBoolean(MIGRATED_SP_FULL, true, 0);
                 }
-                setString(MIGRATED_SP_CE_ONLY, "true", 0);
+            } else {
+                if (getString(MIGRATED_SP_CE_ONLY, null, 0) == null) {
+                    for (UserInfo user : mUserManager.getAliveUsers()) {
+                        removeStateForReusedUserIdIfNecessary(user.id, user.serialNumber);
+                        synchronized (mSpManager) {
+                            migrateUserToSpWithBoundCeKeyLocked(user.id);
+                        }
+                    }
+                    setString(MIGRATED_SP_CE_ONLY, "true", 0);
+                }
+
+                if (getBoolean(MIGRATED_SP_FULL, false, 0)) {
+                    // The FIX_UNLOCKED_DEVICE_REQUIRED_KEYS flag was enabled but then got disabled.
+                    // Ensure the full migration runs again the next time the flag is enabled...
+                    setBoolean(MIGRATED_SP_FULL, false, 0);
+                }
             }
 
             mThirdPartyAppsStarted = true;
@@ -1067,6 +1102,37 @@
         }
     }
 
+    @GuardedBy("mSpManager")
+    private void migrateUserToSpWithBoundKeysLocked(@UserIdInt int userId) {
+        if (isUserSecure(userId)) {
+            Slogf.d(TAG, "User %d is secured; no migration needed", userId);
+            return;
+        }
+        long protectorId = getCurrentLskfBasedProtectorId(userId);
+        if (protectorId == SyntheticPasswordManager.NULL_PROTECTOR_ID) {
+            Slogf.i(TAG, "Migrating unsecured user %d to SP-based credential", userId);
+            initializeSyntheticPassword(userId);
+            return;
+        }
+        Slogf.i(TAG, "Existing unsecured user %d has a synthetic password", userId);
+        AuthenticationResult result = mSpManager.unlockLskfBasedProtector(
+                getGateKeeperService(), protectorId, LockscreenCredential.createNone(), userId,
+                null);
+        SyntheticPassword sp = result.syntheticPassword;
+        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) {
+            Slogf.i(TAG, "Encrypting CE key of user %d with synthetic password", userId);
+            setCeStorageProtection(userId, sp);
+        }
+        Slogf.i(TAG, "Initializing Keystore super keys for user %d", userId);
+        initKeystoreSuperKeys(userId, sp, /* allowExisting= */ true);
+    }
+
     /**
      * Returns the lowest password quality that still presents the same UI for entering it.
      *
@@ -1348,6 +1414,20 @@
         AndroidKeyStoreMaintenance.onUserPasswordChanged(userHandle, password);
     }
 
+    @VisibleForTesting /** Note: this method is overridden in unit tests */
+    void initKeystoreSuperKeys(@UserIdInt int userId, SyntheticPassword sp, boolean allowExisting) {
+        final byte[] password = sp.deriveKeyStorePassword();
+        try {
+            int res = AndroidKeyStoreMaintenance.initUserSuperKeys(userId, password, allowExisting);
+            if (res != 0) {
+                throw new IllegalStateException("Failed to initialize Keystore super keys for user "
+                        + userId);
+            }
+        } finally {
+            Arrays.fill(password, (byte) 0);
+        }
+    }
+
     private void unlockKeystore(int userId, SyntheticPassword sp) {
         Authorization.onLockScreenEvent(false, userId, sp.deriveKeyStorePassword(), null);
     }
@@ -2071,6 +2151,9 @@
                 return;
             }
             onSyntheticPasswordUnlocked(userId, result.syntheticPassword);
+            if (FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) {
+                unlockKeystore(userId, result.syntheticPassword);
+            }
             unlockCeStorage(userId, result.syntheticPassword);
         }
     }
@@ -2350,6 +2433,16 @@
     }
 
     private void createNewUser(@UserIdInt int userId, int userSerialNumber) {
+
+        // Delete all Keystore keys for userId, just in case any were left around from a removed
+        // user with the same userId.  This should be unnecessary, but we've been doing this for a
+        // long time, so for now we keep doing it just in case it's ever important.  Don't wait
+        // until initKeystoreSuperKeys() to do this; that can be delayed if the user is being
+        // created during early boot, and maybe something will use Keystore before then.
+        if (FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) {
+            AndroidKeyStoreMaintenance.onUserAdded(userId);
+        }
+
         synchronized (mUserCreationAndRemovalLock) {
             // During early boot, don't actually create the synthetic password yet, but rather
             // automatically delay it to later.  We do this because protecting the synthetic
@@ -2756,7 +2849,7 @@
 
     /**
      * Creates the synthetic password (SP) for the given user, protects it with an empty LSKF, and
-     * protects the user's CE key with a key derived from the SP.
+     * protects the user's CE storage key and Keystore super keys with keys derived from the SP.
      *
      * <p>This is called just once in the lifetime of the user: at user creation time (possibly
      * delayed until the time when Weaver is guaranteed to be available), or when upgrading from
@@ -2775,6 +2868,9 @@
                     LockscreenCredential.createNone(), sp, userId);
             setCurrentLskfBasedProtectorId(protectorId, userId);
             setCeStorageProtection(userId, sp);
+            if (FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) {
+                initKeystoreSuperKeys(userId, sp, /* allowExisting= */ false);
+            }
             onSyntheticPasswordCreated(userId, sp);
             Slogf.i(TAG, "Successfully initialized synthetic password for user %d", userId);
             return sp;
@@ -2867,11 +2963,10 @@
     /**
      * Changes the user's LSKF by creating an LSKF-based protector that uses the new LSKF (which may
      * be empty) and replacing the old LSKF-based protector with it.  The SP itself is not changed.
-     *
-     * Also maintains the invariants described in {@link SyntheticPasswordManager} by
-     * setting/clearing the protection (by the SP) on the user's auth-bound Keystore keys when the
-     * LSKF is added/removed, respectively.  If an LSKF is being added, then the Gatekeeper auth
-     * token is also refreshed.
+     * <p>
+     * Also maintains the invariants described in {@link SyntheticPasswordManager} by enrolling /
+     * deleting the synthetic password into Gatekeeper as the LSKF is set / cleared, and asking
+     * Keystore to delete the user's auth-bound keys when the LSKF is cleared.
      */
     @GuardedBy("mSpManager")
     private long setLockCredentialWithSpLocked(LockscreenCredential credential,
@@ -2890,7 +2985,9 @@
             if (!mSpManager.hasSidForUser(userId)) {
                 mSpManager.newSidForUser(getGateKeeperService(), sp, userId);
                 mSpManager.verifyChallenge(getGateKeeperService(), sp, 0L, userId);
-                setKeystorePassword(sp.deriveKeyStorePassword(), userId);
+                if (!FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) {
+                    setKeystorePassword(sp.deriveKeyStorePassword(), userId);
+                }
             }
         } else {
             // Cache all profile password if they use unified work challenge. This will later be
@@ -2901,7 +2998,11 @@
             gateKeeperClearSecureUserId(userId);
             unlockCeStorage(userId, sp);
             unlockKeystore(userId, sp);
-            setKeystorePassword(null, userId);
+            if (FIX_UNLOCKED_DEVICE_REQUIRED_KEYS) {
+                AndroidKeyStoreMaintenance.onUserLskfRemoved(userId);
+            } else {
+                setKeystorePassword(null, userId);
+            }
             removeBiometricsForUser(userId);
         }
         setCurrentLskfBasedProtectorId(newProtectorId, userId);
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index 8e9c21f..cc205d4 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -90,10 +90,15 @@
  *
  *  - The user's credential-encrypted storage is always protected by the SP.
  *
- *  - The user's auth-bound Keystore keys are protected by the SP, but only while an LSKF is set.
- *    This works by setting the user's Keystore and Gatekeeper passwords to SP-derived secrets, but
- *    only while an LSKF is set.  When the LSKF is removed, these passwords are cleared,
- *    invalidating the user's auth-bound keys.
+ *  - The user's Keystore superencryption keys are always protected by the SP.  These in turn
+ *    protect the Keystore keys that require user authentication, an unlocked device, or both.
+ *
+ *  - A secret derived from the synthetic password is enrolled in Gatekeeper for the user, but only
+ *    while the user has a (nonempty) LSKF.  This enrollment has an associated ID called the Secure
+ *    user ID or SID.  This use of Gatekeeper, which is separate from the use of GateKeeper that may
+ *    be used in the LSKF-based protector, makes it so that unlocking the synthetic password
+ *    generates a HardwareAuthToken (but only when the user has LSKF).  That HardwareAuthToken can
+ *    be provided to KeyMint to authorize the use of the user's authentication-bound Keystore keys.
  *
  * Files stored on disk for each user:
  *   For the SP itself, stored under NULL_PROTECTOR_ID:
diff --git a/services/core/java/com/android/server/net/NetworkManagementService.java b/services/core/java/com/android/server/net/NetworkManagementService.java
index 550ad5d..681d1a0 100644
--- a/services/core/java/com/android/server/net/NetworkManagementService.java
+++ b/services/core/java/com/android/server/net/NetworkManagementService.java
@@ -74,7 +74,6 @@
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.HexDump;
 import com.android.modules.utils.build.SdkLevel;
-import com.android.net.flags.Flags;
 import com.android.net.module.util.NetdUtils;
 import com.android.net.module.util.PermissionUtils;
 import com.android.server.FgThread;
@@ -328,10 +327,10 @@
     /**
      * Notify our observers of a change in the data activity state of the interface
      */
-    private void notifyInterfaceClassActivity(int type, boolean isActive, long tsNanos,
+    private void notifyInterfaceClassActivity(int label, boolean isActive, long tsNanos,
             int uid) {
         invokeForAllObservers(o -> o.interfaceClassDataActivityChanged(
-                type, isActive, tsNanos, uid));
+                label, isActive, tsNanos, uid));
     }
 
     // Sync the state of the given chain with the native daemon.
@@ -1062,7 +1061,7 @@
             }
             Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "setDataSaverModeEnabled");
             try {
-                if (Flags.setDataSaverViaCm()) {
+                if (SdkLevel.isAtLeastV()) {
                     // setDataSaverEnabled throws if it fails to set data saver.
                     mContext.getSystemService(ConnectivityManager.class)
                             .setDataSaverEnabled(enable);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
index 1c33d0d..18961c0 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
@@ -34,6 +34,7 @@
 
 import com.android.internal.widget.LockscreenCredential;
 import com.android.server.ServiceThread;
+import com.android.server.locksettings.SyntheticPasswordManager.SyntheticPassword;
 import com.android.server.locksettings.recoverablekeystore.RecoverableKeyStoreManager;
 import com.android.server.pm.UserManagerInternal;
 
@@ -203,6 +204,10 @@
     }
 
     @Override
+    void initKeystoreSuperKeys(int userId, SyntheticPassword sp, boolean allowExisting) {
+    }
+
+    @Override
     protected boolean isCredentialSharableWithParent(int userId) {
         UserInfo userInfo = mUserManager.getUserInfo(userId);
         return userInfo.isCloneProfile() || userInfo.isManagedProfile();
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkManagementServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkManagementServiceTest.java
index 2cdfbff..13dc120 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkManagementServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkManagementServiceTest.java
@@ -57,7 +57,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.app.IBatteryStats;
-import com.android.net.flags.Flags;
+import com.android.modules.utils.build.SdkLevel;
 
 import org.junit.After;
 import org.junit.Before;
@@ -264,7 +264,7 @@
         verify(mCm).addUidToMeteredNetworkDenyList(TEST_UID);
 
         mNMService.setDataSaverModeEnabled(true);
-        if (Flags.setDataSaverViaCm()) {
+        if (SdkLevel.isAtLeastV()) {
             verify(mCm).setDataSaverEnabled(true);
         } else {
             verify(mNetdService).bandwidthEnableDataSaver(true);
@@ -284,7 +284,7 @@
         mNMService.setUidOnMeteredNetworkAllowlist(TEST_UID, false);
         verify(mCm).removeUidFromMeteredNetworkAllowList(TEST_UID);
         mNMService.setDataSaverModeEnabled(false);
-        if (Flags.setDataSaverViaCm()) {
+        if (SdkLevel.isAtLeastV()) {
             verify(mCm).setDataSaverEnabled(false);
         } else {
             verify(mNetdService).bandwidthEnableDataSaver(false);