Merge "Moving tests in multivalent locations to remove the need to copy files around and confuse developers." into main
diff --git a/core/api/current.txt b/core/api/current.txt
index 09abe2b..e8894a81 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -10601,6 +10601,7 @@
     field public static final String RESTRICTIONS_SERVICE = "restrictions";
     field public static final String ROLE_SERVICE = "role";
     field public static final String SEARCH_SERVICE = "search";
+    field @FlaggedApi("android.os.security_state_service") public static final String SECURITY_STATE_SERVICE = "security_state";
     field public static final String SENSOR_SERVICE = "sensor";
     field public static final String SHORTCUT_SERVICE = "shortcut";
     field public static final String STATUS_BAR_SERVICE = "statusbar";
@@ -10613,6 +10614,7 @@
     field public static final String TELEPHONY_SUBSCRIPTION_SERVICE = "telephony_subscription_service";
     field public static final String TEXT_CLASSIFICATION_SERVICE = "textclassification";
     field public static final String TEXT_SERVICES_MANAGER_SERVICE = "textservices";
+    field @FlaggedApi("android.media.tv.flags.enable_ad_service_fw") public static final String TV_AD_SERVICE = "tv_ad";
     field public static final String TV_INPUT_SERVICE = "tv_input";
     field public static final String TV_INTERACTIVE_APP_SERVICE = "tv_interactive_app";
     field public static final String UI_MODE_SERVICE = "uimode";
@@ -27302,6 +27304,13 @@
 
 }
 
+package android.media.tv.ad {
+
+  @FlaggedApi("android.media.tv.flags.enable_ad_service_fw") public class TvAdManager {
+  }
+
+}
+
 package android.media.tv.interactive {
 
   public final class AppLinkInfo implements android.os.Parcelable {
@@ -33379,6 +33388,13 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.os.ResultReceiver> CREATOR;
   }
 
+  @FlaggedApi("android.os.security_state_service") public class SecurityStateManager {
+    method @FlaggedApi("android.os.security_state_service") @NonNull public android.os.Bundle getGlobalSecurityState();
+    field public static final String KEY_KERNEL_VERSION = "kernel_version";
+    field public static final String KEY_SYSTEM_SPL = "system_spl";
+    field public static final String KEY_VENDOR_SPL = "vendor_spl";
+  }
+
   public final class SharedMemory implements java.io.Closeable android.os.Parcelable {
     method public void close();
     method @NonNull public static android.os.SharedMemory create(@Nullable String, int) throws android.system.ErrnoException;
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 79a5879..9cf732a 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -137,6 +137,8 @@
 import android.media.soundtrigger.SoundTriggerManager;
 import android.media.tv.ITvInputManager;
 import android.media.tv.TvInputManager;
+import android.media.tv.ad.ITvAdManager;
+import android.media.tv.ad.TvAdManager;
 import android.media.tv.interactive.ITvInteractiveAppManager;
 import android.media.tv.interactive.TvInteractiveAppManager;
 import android.media.tv.tunerresourcemanager.ITunerResourceManager;
@@ -174,6 +176,7 @@
 import android.os.IPowerManager;
 import android.os.IPowerStatsService;
 import android.os.IRecoverySystem;
+import android.os.ISecurityStateManager;
 import android.os.ISystemUpdateManager;
 import android.os.IThermalService;
 import android.os.IUserManager;
@@ -182,6 +185,7 @@
 import android.os.PermissionEnforcer;
 import android.os.PowerManager;
 import android.os.RecoverySystem;
+import android.os.SecurityStateManager;
 import android.os.ServiceManager;
 import android.os.ServiceManager.ServiceNotFoundException;
 import android.os.StatsFrameworkInitializer;
@@ -628,6 +632,17 @@
                         ctx.mMainThread.getHandler());
             }});
 
+        registerService(Context.SECURITY_STATE_SERVICE, SecurityStateManager.class,
+                new CachedServiceFetcher<SecurityStateManager>() {
+                    @Override
+                    public SecurityStateManager createService(ContextImpl ctx)
+                            throws ServiceNotFoundException {
+                        IBinder b = ServiceManager.getServiceOrThrow(
+                                Context.SECURITY_STATE_SERVICE);
+                        ISecurityStateManager service = ISecurityStateManager.Stub.asInterface(b);
+                        return new SecurityStateManager(service);
+                    }});
+
         registerService(Context.SENSOR_SERVICE, SensorManager.class,
                 new CachedServiceFetcher<SensorManager>() {
             @Override
@@ -960,6 +975,18 @@
                 return new TvInteractiveAppManager(service, ctx.getUserId());
             }});
 
+        registerService(Context.TV_AD_SERVICE, TvAdManager.class,
+                new CachedServiceFetcher<TvAdManager>() {
+                    @Override
+                    public TvAdManager createService(ContextImpl ctx)
+                            throws ServiceNotFoundException {
+                        IBinder iBinder =
+                                ServiceManager.getServiceOrThrow(Context.TV_AD_SERVICE);
+                        ITvAdManager service =
+                                ITvAdManager.Stub.asInterface(iBinder);
+                        return new TvAdManager(service, ctx.getUserId());
+                    }});
+
         registerService(Context.TV_INPUT_SERVICE, TvInputManager.class,
                 new CachedServiceFetcher<TvInputManager>() {
             @Override
diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java
index 0ae00cd..9eb73b3 100644
--- a/core/java/android/app/usage/UsageEvents.java
+++ b/core/java/android/app/usage/UsageEvents.java
@@ -837,6 +837,7 @@
         if (mEventCount != mEventsToWrite.size()) {
             Log.w(TAG, "Partial usage event list received: " + mEventCount + " != "
                     + mEventsToWrite.size());
+            mEventCount = mEventsToWrite.size();
         }
     }
 
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 1c6c7b5..b75c64d 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -72,6 +72,7 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Environment;
+import android.os.Flags;
 import android.os.Handler;
 import android.os.HandlerExecutor;
 import android.os.IBinder;
@@ -4214,6 +4215,7 @@
             DEVICE_LOCK_SERVICE,
             VIRTUALIZATION_SERVICE,
             GRAMMATICAL_INFLECTION_SERVICE,
+            SECURITY_STATE_SERVICE,
 
     })
     @Retention(RetentionPolicy.SOURCE)
@@ -5818,6 +5820,17 @@
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve a
+     * {@link android.media.tv.ad.TvAdManager} for interacting with TV client-side advertisement
+     * services on the device.
+     *
+     * @see #getSystemService(String)
+     * @see android.media.tv.ad.TvAdManager
+     */
+    @FlaggedApi(android.media.tv.flags.Flags.FLAG_ENABLE_AD_SERVICE_FW)
+    public static final String TV_AD_SERVICE = "tv_ad";
+
+    /**
+     * Use with {@link #getSystemService(String)} to retrieve a
      * {@link android.media.tv.TunerResourceManager} for interacting with TV
      * tuner resources on the device.
      *
@@ -6478,6 +6491,16 @@
     public static final String SHARED_CONNECTIVITY_SERVICE = "shared_connectivity";
 
     /**
+     * Use with {@link #getSystemService(String)} to retrieve a
+     * {@link android.os.SecurityStateManager} for accessing the security state manager service.
+     *
+     * @see #getSystemService(String)
+     * @see android.os.SecurityStateManager
+     */
+    @FlaggedApi(Flags.FLAG_SECURITY_STATE_SERVICE)
+    public static final String SECURITY_STATE_SERVICE = "security_state";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java
index ed31002..eabe13b 100644
--- a/core/java/android/os/BatteryUsageStats.java
+++ b/core/java/android/os/BatteryUsageStats.java
@@ -123,6 +123,12 @@
 
     private static final int STATSD_PULL_ATOM_MAX_BYTES = 45000;
 
+    private static final int[] UID_USAGE_TIME_PROCESS_STATES = {
+            BatteryConsumer.PROCESS_STATE_FOREGROUND,
+            BatteryConsumer.PROCESS_STATE_BACKGROUND,
+            BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE
+    };
+
     private final int mDischargePercentage;
     private final double mBatteryCapacityMah;
     private final long mStatsStartTimestampMs;
@@ -516,6 +522,22 @@
             proto.write(
                     BatteryUsageStatsAtomsProto.UidBatteryConsumer.TIME_IN_BACKGROUND_MILLIS,
                     bgMs);
+            for (int processState : UID_USAGE_TIME_PROCESS_STATES) {
+                final long timeInStateMillis = consumer.getTimeInProcessStateMs(processState);
+                if (timeInStateMillis <= 0) {
+                    continue;
+                }
+                final long timeInStateToken = proto.start(
+                        BatteryUsageStatsAtomsProto.UidBatteryConsumer.TIME_IN_STATE);
+                proto.write(
+                        BatteryUsageStatsAtomsProto.UidBatteryConsumer.TimeInState.PROCESS_STATE,
+                        processState);
+                proto.write(
+                        BatteryUsageStatsAtomsProto.UidBatteryConsumer.TimeInState
+                                .TIME_IN_STATE_MILLIS,
+                        timeInStateMillis);
+                proto.end(timeInStateToken);
+            }
             proto.end(token);
 
             if (proto.getRawSize() >= maxRawSize) {
diff --git a/core/java/android/os/ISecurityStateManager.aidl b/core/java/android/os/ISecurityStateManager.aidl
new file mode 100644
index 0000000..8ae624d
--- /dev/null
+++ b/core/java/android/os/ISecurityStateManager.aidl
@@ -0,0 +1,26 @@
+/* //device/java/android/android/os/ISecurityStateManager.aidl
+**
+** Copyright 2023, 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.os;
+
+import android.os.Bundle;
+import android.os.PersistableBundle;
+
+/** @hide */
+interface ISecurityStateManager {
+    Bundle getGlobalSecurityState();
+}
diff --git a/core/java/android/os/SecurityStateManager.java b/core/java/android/os/SecurityStateManager.java
new file mode 100644
index 0000000..4fa61e0
--- /dev/null
+++ b/core/java/android/os/SecurityStateManager.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2023 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.os;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.annotation.SystemService;
+import android.content.Context;
+
+/**
+ * SecurityStateManager provides the functionality to query the security status of the system and
+ * platform components. For example, this includes the system and vendor security patch level.
+ */
+@FlaggedApi(Flags.FLAG_SECURITY_STATE_SERVICE)
+@SystemService(Context.SECURITY_STATE_SERVICE)
+public class SecurityStateManager {
+
+    /**
+     * The system SPL key returned as part of the {@code Bundle} from
+     * {@code getGlobalSecurityState}.
+     */
+    public static final String KEY_SYSTEM_SPL = "system_spl";
+
+    /**
+     * The vendor SPL key returned as part of the {@code Bundle} from
+     * {@code getGlobalSecurityState}.
+     */
+    public static final String KEY_VENDOR_SPL = "vendor_spl";
+
+    /**
+     * The kernel version key returned as part of the {@code Bundle} from
+     * {@code getGlobalSecurityState}.
+     */
+    public static final String KEY_KERNEL_VERSION = "kernel_version";
+
+    private final ISecurityStateManager mService;
+
+    /**
+     * @hide
+     */
+    public SecurityStateManager(ISecurityStateManager service) {
+        mService = requireNonNull(service, "missing ISecurityStateManager");
+    }
+
+    /**
+     * Returns the current global security state. Each key-value pair is a mapping of a component
+     * of the global security state to its current version/SPL (security patch level). For example,
+     * the {@code KEY_SYSTEM_SPL} key will map to the SPL of the system as defined in
+     * {@link android.os.Build.VERSION}. The bundle will also include mappings from WebView packages
+     * and packages listed under config {@code config_securityStatePackages} to their respective
+     * versions as defined in {@link android.content.pm.PackageInfo#versionName}.
+     *
+     * @return A {@code Bundle} that contains the global security state information as
+     * string-to-string key-value pairs.
+     */
+    @FlaggedApi(Flags.FLAG_SECURITY_STATE_SERVICE)
+    @NonNull
+    public Bundle getGlobalSecurityState() {
+        try {
+            return mService.getGlobalSecurityState();
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+}
diff --git a/core/java/android/os/flags.aconfig b/core/java/android/os/flags.aconfig
index a78f221..c085f33 100644
--- a/core/java/android/os/flags.aconfig
+++ b/core/java/android/os/flags.aconfig
@@ -57,6 +57,13 @@
 }
 
 flag {
+    name: "security_state_service"
+    namespace: "dynamic_spl"
+    description: "Guards the Security State API."
+    bug: "302189431"
+}
+
+flag {
     name: "battery_saver_supported_check_api"
     namespace: "backstage_power"
     description: "Guards a new API in PowerManager to check if battery saver is supported or not."
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 6853892..78a12f7 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1738,23 +1738,6 @@
         return RoSystemProperties.CRYPTO_FILE_ENCRYPTED;
     }
 
-    /** {@hide}
-     * @deprecated Use {@link #isFileEncrypted} instead, since emulated FBE is no longer supported.
-     */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
-    @Deprecated
-    public static boolean isFileEncryptedNativeOnly() {
-        return isFileEncrypted();
-    }
-
-    /** {@hide}
-     * @deprecated Use {@link #isFileEncrypted} instead, since emulated FBE is no longer supported.
-     */
-    @Deprecated
-    public static boolean isFileEncryptedNativeOrEmulated() {
-        return isFileEncrypted();
-    }
-
     /** {@hide} */
     public static boolean hasAdoptable() {
         switch (SystemProperties.get(PROP_ADOPTABLE)) {
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 8bbc809..1d4e01a 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4993,6 +4993,11 @@
     <!-- Component name for the default module metadata provider on this device -->
     <string name="config_defaultModuleMetadataProvider" translatable="false">com.android.modulemetadata</string>
 
+    <!-- Packages that contain a security state.
+         {@link SecurityStateManager#getGlobalSecurityState} will read and report the state/version
+          of these packages. -->
+    <string-array name="config_securityStatePackages" translatable="false" />
+
     <!-- Package name for the default Health Connect app.
          OEMs can set this with their own health app package name to define a default app with high
          priority for the app to store the health data. If set the app always has priority of 1
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 3d43004..4b0fa4b 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1274,6 +1274,7 @@
   <java-symbol type="array" name="policy_exempt_apps" />
   <java-symbol type="array" name="vendor_policy_exempt_apps" />
   <java-symbol type="array" name="cloneable_apps" />
+  <java-symbol type="array" name="config_securityStatePackages" />
 
   <java-symbol type="drawable" name="default_wallpaper" />
   <java-symbol type="drawable" name="default_lock_wallpaper" />
diff --git a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java
index b92d9db..ac1f7d0 100644
--- a/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java
+++ b/core/tests/batterystatstests/BatteryUsageStatsProtoTests/src/com/android/internal/os/BatteryUsageStatsPulledTest.java
@@ -48,6 +48,11 @@
     private static final int UID_1 = 2000;
     private static final int UID_2 = 3000;
     private static final int UID_3 = 4000;
+    private static final int[] UID_USAGE_TIME_PROCESS_STATES = {
+            BatteryConsumer.PROCESS_STATE_FOREGROUND,
+            BatteryConsumer.PROCESS_STATE_BACKGROUND,
+            BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE
+    };
 
     @Test
     public void testGetStatsProto() {
@@ -195,6 +200,20 @@
         assertEquals("For uid " + uid,
                 uidConsumer.getTimeInStateMs(android.os.UidBatteryConsumer.STATE_BACKGROUND),
                 uidConsumerProto.timeInBackgroundMillis);
+        for (int processState : UID_USAGE_TIME_PROCESS_STATES) {
+            final long timeInStateMillis = uidConsumer.getTimeInProcessStateMs(processState);
+            if (timeInStateMillis <= 0) {
+                continue;
+            }
+            assertEquals("For uid " + uid + ", process state " + processState,
+                    timeInStateMillis,
+                    Arrays.stream(uidConsumerProto.timeInState)
+                            .filter(timeInState -> timeInState.processState == processState)
+                            .findFirst()
+                            .orElseThrow()
+                            .timeInStateMillis);
+        }
+
         if (expectNullBatteryConsumerData) {
             assertNull("For uid " + uid, uidConsumerProto.batteryConsumerData);
         } else {
diff --git a/media/java/android/media/tv/ad/TvAdManager.java b/media/java/android/media/tv/ad/TvAdManager.java
index aa5a290..2b52c4b 100644
--- a/media/java/android/media/tv/ad/TvAdManager.java
+++ b/media/java/android/media/tv/ad/TvAdManager.java
@@ -16,6 +16,10 @@
 
 package android.media.tv.ad;
 
+import android.annotation.FlaggedApi;
+import android.annotation.SystemService;
+import android.content.Context;
+import android.media.tv.flags.Flags;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Log;
@@ -23,14 +27,17 @@
 /**
  * Central system API to the overall client-side TV AD architecture, which arbitrates interaction
  * between applications and AD services.
- * @hide
  */
+@FlaggedApi(Flags.FLAG_ENABLE_AD_SERVICE_FW)
+@SystemService(Context.TV_AD_SERVICE)
 public class TvAdManager {
+    // TODO: implement more methods and unhide APIs.
     private static final String TAG = "TvAdManager";
 
     private final ITvAdManager mService;
     private final int mUserId;
 
+    /** @hide */
     public TvAdManager(ITvAdManager service, int userId) {
         mService = service;
         mUserId = userId;
@@ -38,6 +45,7 @@
 
     /**
      * The Session provides the per-session functionality of AD service.
+     * @hide
      */
     public static final class Session {
         private final IBinder mToken;
diff --git a/media/java/android/media/tv/flags/media_tv.aconfig b/media/java/android/media/tv/flags/media_tv.aconfig
index a73d1ff..018eaf6 100644
--- a/media/java/android/media/tv/flags/media_tv.aconfig
+++ b/media/java/android/media/tv/flags/media_tv.aconfig
@@ -5,4 +5,11 @@
     namespace: "media_tv"
     description: "Constants for standardizing broadcast visibility types."
     bug: "222402395"
+}
+
+flag {
+    name: "enable_ad_service_fw"
+    namespace: "media_tv"
+    description: "Enable the TV client-side AD framework."
+    bug: "303506816"
 }
\ No newline at end of file
diff --git a/services/core/java/com/android/server/SecurityStateManagerService.java b/services/core/java/com/android/server/SecurityStateManagerService.java
new file mode 100644
index 0000000..98039be
--- /dev/null
+++ b/services/core/java/com/android/server/SecurityStateManagerService.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import static android.os.SecurityStateManager.KEY_KERNEL_VERSION;
+import static android.os.SecurityStateManager.KEY_SYSTEM_SPL;
+import static android.os.SecurityStateManager.KEY_VENDOR_SPL;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.ISecurityStateManager;
+import android.os.SystemProperties;
+import android.os.VintfRuntimeInfo;
+import android.text.TextUtils;
+import android.util.Slog;
+import android.webkit.WebViewProviderInfo;
+import android.webkit.WebViewUpdateService;
+
+import com.android.internal.R;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class SecurityStateManagerService extends ISecurityStateManager.Stub {
+
+    private static final String TAG = "SecurityStateManagerService";
+
+    static final String VENDOR_SECURITY_PATCH_PROPERTY_KEY = "ro.vendor.build"
+            + ".security_patch";
+    static final Pattern KERNEL_RELEASE_PATTERN = Pattern.compile("(\\d+\\.\\d+\\.\\d+)("
+            + ".*)");
+
+    private final Context mContext;
+    private final PackageManager mPackageManager;
+
+    public SecurityStateManagerService(Context context) {
+        mContext = context;
+        mPackageManager = context.getPackageManager();
+    }
+
+    @Override
+    public Bundle getGlobalSecurityState() {
+        Bundle globalSecurityState = new Bundle();
+        globalSecurityState.putString(KEY_SYSTEM_SPL, Build.VERSION.SECURITY_PATCH);
+        globalSecurityState.putString(KEY_VENDOR_SPL,
+                SystemProperties.get(VENDOR_SECURITY_PATCH_PROPERTY_KEY, ""));
+        String moduleMetadataProviderPackageName =
+                mContext.getString(R.string.config_defaultModuleMetadataProvider);
+        if (!moduleMetadataProviderPackageName.isEmpty()) {
+            globalSecurityState.putString(moduleMetadataProviderPackageName,
+                    getSpl(moduleMetadataProviderPackageName));
+        }
+        globalSecurityState.putString(KEY_KERNEL_VERSION, getKernelVersion());
+        addWebViewPackages(globalSecurityState);
+        addSecurityStatePackages(globalSecurityState);
+        return globalSecurityState;
+    }
+
+    private String getSpl(String packageName) {
+        if (!TextUtils.isEmpty(packageName)) {
+            try {
+                return mPackageManager.getPackageInfo(packageName, 0 /* flags */).versionName;
+            } catch (PackageManager.NameNotFoundException e) {
+                Slog.e(TAG, TextUtils.formatSimple("Failed to get SPL for package %s.",
+                        packageName), e);
+            }
+        }
+        return "";
+    }
+
+    private String getKernelVersion() {
+        Matcher matcher = KERNEL_RELEASE_PATTERN.matcher(VintfRuntimeInfo.getKernelVersion());
+        if (matcher.matches()) {
+            return matcher.group(1);
+        }
+        return "";
+    }
+
+    private void addWebViewPackages(Bundle bundle) {
+        for (WebViewProviderInfo info : WebViewUpdateService.getAllWebViewPackages()) {
+            String packageName = info.packageName;
+            bundle.putString(packageName, getSpl(packageName));
+        }
+    }
+
+    private void addSecurityStatePackages(Bundle bundle) {
+        String[] packageNames;
+        packageNames = mContext.getResources().getStringArray(R.array.config_securityStatePackages);
+        for (String packageName : packageNames) {
+            bundle.putString(packageName, getSpl(packageName));
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
index e6273d3..0467d0c 100644
--- a/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
+++ b/services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java
@@ -38,6 +38,7 @@
 import android.media.tv.BroadcastInfoResponse;
 import android.media.tv.TvRecordingInfo;
 import android.media.tv.TvTrackInfo;
+import android.media.tv.ad.ITvAdManager;
 import android.media.tv.interactive.AppLinkInfo;
 import android.media.tv.interactive.ITvInteractiveAppClient;
 import android.media.tv.interactive.ITvInteractiveAppManager;
@@ -345,6 +346,7 @@
             Slogf.d(TAG, "onStart");
         }
         publishBinderService(Context.TV_INTERACTIVE_APP_SERVICE, new BinderService());
+        publishBinderService(Context.TV_AD_SERVICE, new TvAdBinderService());
     }
 
     @Override
@@ -688,6 +690,12 @@
         }
         return session;
     }
+    private final class TvAdBinderService extends ITvAdManager.Stub {
+        @Override
+        public void startAdService(IBinder sessionToken, int userId) {
+        }
+
+    }
 
     private final class BinderService extends ITvInteractiveAppManager.Stub {
 
diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
index 6e7cf12..4625b4fe 100644
--- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
+++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
@@ -60,7 +60,6 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.FrameworkStatsLog;
-import com.android.internal.util.Preconditions;
 import com.android.server.UiThread;
 import com.android.server.am.PendingIntentRecord;
 import com.android.window.flags.Flags;
@@ -237,6 +236,7 @@
         private final @ActivityManager.ProcessState int mCallingUidProcState;
         private final boolean mIsCallingUidPersistentSystemProcess;
         private final BackgroundStartPrivileges mBalAllowedByPiSender;
+        private final BackgroundStartPrivileges mBalAllowedByPiCreatorWithHardening;
         private final BackgroundStartPrivileges mBalAllowedByPiCreator;
         private final String mRealCallingPackage;
         private final int mRealCallingUid;
@@ -269,7 +269,7 @@
             mRealCallingPackage = mService.getPackageNameIfUnique(realCallingUid, realCallingPid);
             if (originatingPendingIntent == null) {
                 // grant BAL privileges unless explicitly opted out
-                mBalAllowedByPiCreator =
+                mBalAllowedByPiCreatorWithHardening = mBalAllowedByPiCreator =
                         checkedOptions.getPendingIntentCreatorBackgroundActivityStartMode()
                                 == ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED
                                 ? BackgroundStartPrivileges.NONE
@@ -281,8 +281,16 @@
                                 : BackgroundStartPrivileges.ALLOW_BAL;
             } else {
                 // for PendingIntents we restrict BAL based on target_sdk
-                mBalAllowedByPiCreator = getBackgroundStartPrivilegesAllowedByCreator(
+                mBalAllowedByPiCreatorWithHardening = getBackgroundStartPrivilegesAllowedByCreator(
                         callingUid, callingPackage, checkedOptions);
+                final BackgroundStartPrivileges mBalAllowedByPiCreatorWithoutHardening =
+                        checkedOptions.getPendingIntentCreatorBackgroundActivityStartMode()
+                                == ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED
+                                ? BackgroundStartPrivileges.NONE
+                                : BackgroundStartPrivileges.ALLOW_BAL;
+                mBalAllowedByPiCreator = balRequireOptInByPendingIntentCreator()
+                        ? mBalAllowedByPiCreatorWithHardening
+                        : mBalAllowedByPiCreatorWithoutHardening;
                 mBalAllowedByPiSender =
                         PendingIntentRecord.getBackgroundStartPrivilegesAllowedByCaller(
                                 checkedOptions, realCallingUid, mRealCallingPackage);
@@ -325,10 +333,6 @@
                     return BackgroundStartPrivileges.NONE;
                 case ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_SYSTEM_DEFINED:
                     // no explicit choice by the app - let us decide what to do
-                    if (!balRequireOptInByPendingIntentCreator()) {
-                        // if feature is disabled allow
-                        return BackgroundStartPrivileges.ALLOW_BAL;
-                    }
                     if (callingPackage != null) {
                         // determine based on the calling/creating package
                         boolean changeEnabled = CompatChanges.isChangeEnabled(
@@ -373,11 +377,6 @@
             return mOriginatingPendingIntent != null && hasRealCaller();
         }
 
-        private String dump(BalVerdict resultIfPiCreatorAllowsBal) {
-            Preconditions.checkState(!isPendingIntent());
-            return dump(resultIfPiCreatorAllowsBal, null);
-        }
-
         private boolean callerIsRealCaller() {
             return mCallingUid == mRealCallingUid;
         }
@@ -402,6 +401,8 @@
                 sb.append("; inVisibleTask: ").append(mCallerApp.hasActivityInVisibleTask());
             }
             sb.append("; balAllowedByPiCreator: ").append(mBalAllowedByPiCreator);
+            sb.append("; balAllowedByPiCreatorWithHardening: ")
+                    .append(mBalAllowedByPiCreatorWithHardening);
             sb.append("; resultIfPiCreatorAllowsBal: ").append(resultIfPiCreatorAllowsBal);
             sb.append("; hasRealCaller: ").append(hasRealCaller());
             sb.append("; isPendingIntent: ").append(isPendingIntent());
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 0a2e806..1919eb3 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -2112,6 +2112,15 @@
             networkPolicy.bindConnectivityManager();
             t.traceEnd();
 
+            t.traceBegin("StartSecurityStateManagerService");
+            try {
+                ServiceManager.addService(Context.SECURITY_STATE_SERVICE,
+                        new SecurityStateManagerService(context));
+            } catch (Throwable e) {
+                reportWtf("starting SecurityStateManagerService", e);
+            }
+            t.traceEnd();
+
             t.traceBegin("StartVpnManagerService");
             try {
                 vpnManager = VpnManagerService.create(context);
diff --git a/services/tests/servicestests/src/com/android/server/SecurityStateTest.java b/services/tests/servicestests/src/com/android/server/SecurityStateTest.java
new file mode 100644
index 0000000..fc91e47
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/SecurityStateTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import static android.os.SecurityStateManager.KEY_KERNEL_VERSION;
+import static android.os.SecurityStateManager.KEY_SYSTEM_SPL;
+import static android.os.SecurityStateManager.KEY_VENDOR_SPL;
+
+import static com.android.server.SecurityStateManagerService.KERNEL_RELEASE_PATTERN;
+import static com.android.server.SecurityStateManagerService.VENDOR_SECURITY_PATCH_PROPERTY_KEY;
+
+import static junit.framework.Assert.assertEquals;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.SystemProperties;
+import android.os.VintfRuntimeInfo;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.R;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.regex.Matcher;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class SecurityStateTest {
+    @Rule
+    public MockitoRule mockitoRule = MockitoJUnit.rule();
+
+    @Mock
+    private Context mMockContext;
+
+    @Mock
+    private PackageManager mMockPackageManager;
+
+    @Mock
+    private Resources mMockResources;
+
+    private static final String DEFAULT_MODULE_METADATA_PROVIDER = "com.android.modulemetadata";
+    private static final String DEFAULT_MODULE_METADATA_PROVIDER_VERSION = "2023-12-01";
+    private static final String DEFAULT_SECURITY_STATE_PACKAGE = "com.google.android.gms";
+    private static final String DEFAULT_SECURITY_STATE_PACKAGE_VERSION = "2023-12-05";
+    private static final String[] SECURITY_STATE_PACKAGES =
+            new String[]{DEFAULT_SECURITY_STATE_PACKAGE};
+
+    @Before
+    public void setUp() throws Exception {
+        when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+        when(mMockContext.getResources()).thenReturn(mMockResources);
+        when(mMockContext.getString(R.string.config_defaultModuleMetadataProvider))
+                .thenReturn(DEFAULT_MODULE_METADATA_PROVIDER);
+        when(mMockPackageManager.getPackageInfo(anyString(), anyInt()))
+                .thenReturn(new PackageInfo());
+        PackageInfo moduleMetadataPackageInfo = new PackageInfo();
+        moduleMetadataPackageInfo.versionName = DEFAULT_MODULE_METADATA_PROVIDER_VERSION;
+        when(mMockPackageManager.getPackageInfo(DEFAULT_MODULE_METADATA_PROVIDER, 0))
+                .thenReturn(moduleMetadataPackageInfo);
+        PackageInfo securityStatePackageInfo = new PackageInfo();
+        securityStatePackageInfo.versionName = DEFAULT_SECURITY_STATE_PACKAGE_VERSION;
+        when(mMockPackageManager.getPackageInfo(DEFAULT_SECURITY_STATE_PACKAGE, 0))
+                .thenReturn(securityStatePackageInfo);
+        when(mMockResources.getStringArray(R.array.config_securityStatePackages))
+                .thenReturn(SECURITY_STATE_PACKAGES);
+    }
+
+    @Test
+    public void testGetGlobalSecurityState_returnsBundle() {
+        SecurityStateManagerService securityState = new SecurityStateManagerService(mMockContext);
+
+        Bundle bundle = securityState.getGlobalSecurityState();
+
+        assertEquals(bundle.getString(KEY_SYSTEM_SPL), Build.VERSION.SECURITY_PATCH);
+        assertEquals(bundle.getString(KEY_VENDOR_SPL),
+                SystemProperties.get(VENDOR_SECURITY_PATCH_PROPERTY_KEY, ""));
+        Matcher matcher = KERNEL_RELEASE_PATTERN.matcher(VintfRuntimeInfo.getKernelVersion());
+        String kernelVersion = "";
+        if (matcher.matches()) {
+            kernelVersion = matcher.group(1);
+        }
+        assertEquals(bundle.getString(KEY_KERNEL_VERSION), kernelVersion);
+        assertEquals(bundle.getString(DEFAULT_MODULE_METADATA_PROVIDER),
+                DEFAULT_MODULE_METADATA_PROVIDER_VERSION);
+        assertEquals(bundle.getString(DEFAULT_SECURITY_STATE_PACKAGE),
+                DEFAULT_SECURITY_STATE_PACKAGE_VERSION);
+    }
+}