Merge "Fix lint issues in IMMS"
diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/TypefaceCreatePerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/TypefaceCreatePerfTest.java
index e83c64c..9e0cf39 100644
--- a/apct-tests/perftests/core/src/android/graphics/perftests/TypefaceCreatePerfTest.java
+++ b/apct-tests/perftests/core/src/android/graphics/perftests/TypefaceCreatePerfTest.java
@@ -16,10 +16,13 @@
 
 package android.graphics.perftests;
 
+import static org.junit.Assume.assumeNotNull;
+
 import android.content.Context;
 import android.content.res.AssetManager;
 import android.content.res.Resources;
 import android.graphics.Typeface;
+import android.graphics.fonts.FontVariationAxis;
 import android.perftests.utils.BenchmarkState;
 import android.perftests.utils.PerfStatusReporter;
 
@@ -39,6 +42,8 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.List;
 
 @LargeTest
 @RunWith(AndroidJUnit4.class)
@@ -140,4 +145,18 @@
         }
     }
 
+    @Test
+    public void testCreate_fromTypefaceWithVariation() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        final List<FontVariationAxis> axes = Arrays.asList(
+                new FontVariationAxis("wght", 100f),
+                new FontVariationAxis("wdth", 0.8f));
+
+        while (state.keepRunning()) {
+            Typeface face = Typeface.createFromTypefaceWithVariation(Typeface.SANS_SERIF, axes);
+            // Make sure that the test device has variable fonts.
+            assumeNotNull(face);
+        }
+    }
+
 }
diff --git a/core/java/android/app/timedetector/TimeDetectorHelper.java b/core/java/android/app/timedetector/TimeDetectorHelper.java
new file mode 100644
index 0000000..8752ee0
--- /dev/null
+++ b/core/java/android/app/timedetector/TimeDetectorHelper.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2022 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.app.timedetector;
+
+import android.annotation.NonNull;
+import android.os.Build;
+
+import java.time.Instant;
+
+/**
+ * A utility class for fundamental time detector-related logic that doesn't need to communicate with
+ * the time detector service, i.e. because it can use SDK APIs or hard-coded facts, and doesn't need
+ * permissions or singleton state. Putting logic here avoids the need to expose binder-based calls
+ * or to duplicate code to share related logic (since android.app.timedetector classes are visible
+ * to all processes).
+ *
+ * @hide
+ */
+// Not final for easy replacement / mocking during tests.
+public class TimeDetectorHelper {
+
+    /**
+     * See {@link #getManualDateSelectionYearMin()}. Chosen to produce Unix epoch times be greater
+     * than {@link #MANUAL_SUGGESTION_LOWER_BOUND}.
+     */
+    private static final int MANUAL_SUGGESTION_YEAR_MIN = 2008;
+
+    /**
+     * The maximum gregorian calendar year to allow for manual date selection on devices unlikely to
+     * have Y2038 issues. This serves as a sensible UI-enforced limit though the system server may
+     * support a larger upper bound. Users besides future archeologists are unlikely to need higher
+     * values, for a few years at least.
+     */
+    private static final int MANUAL_SUGGESTION_YEAR_MAX_WITHOUT_Y2038_ISSUE = 2100;
+
+    /**
+     * The maximum gregorian calendar year to allow for manual date selection on devices that may
+     * have Y2038 issues. This serves as a sensible UI-enforced limit though the system server may
+     * support a larger upper bound. That is, the signed 32-bit milliseconds value is
+     * 03:14:07 UTC on 19 January 2038, but this constant means users can only enter dates up to
+     * 2037-12-31. See {@link #MANUAL_SUGGESTION_YEAR_MAX_WITH_Y2038_ISSUE}.
+     *
+     * <p>Note: This UI limit also doesn't prevent devices reaching the Y2038 roll-over time through
+     * the natural passage of time, it just prevents users potentially causing issues in the years
+     * leading up to it accidentally via the UI.
+     */
+    private static final int MANUAL_SUGGESTION_YEAR_MAX_WITH_Y2038_ISSUE = 2037;
+
+    /**
+     * The upper bound for valid suggestions when the Y2038 issue is a risk. This is the instant
+     * when the Y2038 issue occurs.
+     */
+    private static final Instant SUGGESTION_UPPER_BOUND_WITH_Y2038_ISSUE =
+            Instant.ofEpochMilli(1000L * Integer.MAX_VALUE);
+
+    /**
+     * The upper bound for valid suggestions when the Y2038 issue is not a risk. This values means
+     * there is no practical upper bound.
+     *
+     * <p>Make sure this value remains in the value representable as a signed int64 Unix epoch
+     * millis value as in various places {@link Instant#toEpochMilli()} is called, and that throws
+     * an exception if the value is too large.
+     */
+    private static final Instant SUGGESTION_UPPER_BOUND_WIITHOUT_Y2038_ISSUE =
+            Instant.ofEpochMilli(Long.MAX_VALUE);
+
+    /** See {@link #getManualSuggestionLowerBound()}. */
+    private static final Instant MANUAL_SUGGESTION_LOWER_BOUND =
+            Instant.ofEpochMilli(1194220800000L); // Nov 5, 2007, 0:00 UTC
+
+    /**
+     * The lowest value in Unix epoch milliseconds that is considered a valid automatic suggestion.
+     * See also {@link #MANUAL_SUGGESTION_LOWER_BOUND}.
+     *
+     * <p>Note that this is a default value. The lower value enforced can be overridden to be
+     * lower in the system server with flags for testing.
+     */
+    private static final Instant AUTO_SUGGESTION_LOWER_BOUND_DEFAULT = Instant.ofEpochMilli(
+            Long.max(android.os.Environment.getRootDirectory().lastModified(), Build.TIME));
+
+    /** The singleton instance of this class. */
+    public static final TimeDetectorHelper INSTANCE = new TimeDetectorHelper();
+
+    /** Constructor present for subclassing in tests. Use {@link #INSTANCE} in production code. */
+    protected TimeDetectorHelper() {}
+
+    /**
+     * Returns the minimum gregorian calendar year to offer for manual date selection. This serves
+     * as a sensible UI-enforced lower limit, the system server may support a smaller lower bound.
+     */
+    public int getManualDateSelectionYearMin() {
+        return MANUAL_SUGGESTION_YEAR_MIN;
+    }
+
+    /**
+     * Returns the maximum gregorian calendar year to offer for manual date selection. This serves
+     * as a sensible UI-enforced lower limit, the system server may support a larger upper bound.
+     */
+    public int getManualDateSelectionYearMax() {
+        return getDeviceHasY2038Issue()
+                ? MANUAL_SUGGESTION_YEAR_MAX_WITH_Y2038_ISSUE
+                : MANUAL_SUGGESTION_YEAR_MAX_WITHOUT_Y2038_ISSUE;
+    }
+
+    /**
+     * Returns the lowest value in Unix epoch milliseconds that is considered a valid manual
+     * suggestion. For historical reasons Android has a different lower limit for manual input than
+     * automatic. This may change in the future to align with automatic suggestions, but has been
+     * kept initially to avoid breaking manual tests that are hard-coded with old dates real users
+     * will never want to use.
+     */
+    @NonNull
+    public Instant getManualSuggestionLowerBound() {
+        return MANUAL_SUGGESTION_LOWER_BOUND;
+    }
+
+    /**
+     * Returns the lowest value in Unix epoch milliseconds that is considered a valid automatic
+     * suggestion. See also {@link #MANUAL_SUGGESTION_LOWER_BOUND}.
+     *
+     * <p>Note that this is a default value. The lower value enforced can be overridden to be
+     * different in the system server with server flags.
+     */
+    @NonNull
+    public Instant getAutoSuggestionLowerBoundDefault() {
+        return AUTO_SUGGESTION_LOWER_BOUND_DEFAULT;
+    }
+
+    /** Returns the upper bound to enforce for all time suggestions (manual and automatic). */
+    @NonNull
+    public Instant getSuggestionUpperBound() {
+        return getDeviceHasY2038Issue()
+                ? SUGGESTION_UPPER_BOUND_WITH_Y2038_ISSUE
+                : SUGGESTION_UPPER_BOUND_WIITHOUT_Y2038_ISSUE;
+    }
+
+    /**
+     * Returns {@code true} if the device may be at risk of time_t overflow (because bionic
+     * defines time_t as a 32-bit signed integer for 32-bit processes).
+     */
+    private boolean getDeviceHasY2038Issue() {
+        return Build.SUPPORTED_32_BIT_ABIS.length > 0;
+    }
+}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 44dc28d..c15b3e0 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -713,6 +713,15 @@
         if (!checkUseInstalledOrHidden(flags, state, p.applicationInfo) || !p.isMatch(flags)) {
             return null;
         }
+
+        final ApplicationInfo applicationInfo;
+        if ((flags & (PackageManager.GET_ACTIVITIES | PackageManager.GET_RECEIVERS
+                | PackageManager.GET_SERVICES | PackageManager.GET_PROVIDERS)) != 0) {
+            applicationInfo = generateApplicationInfo(p, flags, state, userId);
+        } else {
+            applicationInfo = null;
+        }
+
         PackageInfo pi = new PackageInfo();
         pi.packageName = p.packageName;
         pi.splitNames = p.splitNames;
@@ -773,7 +782,7 @@
                         if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(a.className)) {
                             continue;
                         }
-                        res[num++] = generateActivityInfo(a, flags, state, userId);
+                        res[num++] = generateActivityInfo(a, flags, state, userId, applicationInfo);
                     }
                 }
                 pi.activities = ArrayUtils.trimToSize(res, num);
@@ -787,7 +796,7 @@
                 for (int i = 0; i < N; i++) {
                     final Activity a = p.receivers.get(i);
                     if (isMatch(state, a.info, flags)) {
-                        res[num++] = generateActivityInfo(a, flags, state, userId);
+                        res[num++] = generateActivityInfo(a, flags, state, userId, applicationInfo);
                     }
                 }
                 pi.receivers = ArrayUtils.trimToSize(res, num);
@@ -801,7 +810,7 @@
                 for (int i = 0; i < N; i++) {
                     final Service s = p.services.get(i);
                     if (isMatch(state, s.info, flags)) {
-                        res[num++] = generateServiceInfo(s, flags, state, userId);
+                        res[num++] = generateServiceInfo(s, flags, state, userId, applicationInfo);
                     }
                 }
                 pi.services = ArrayUtils.trimToSize(res, num);
@@ -815,7 +824,8 @@
                 for (int i = 0; i < N; i++) {
                     final Provider pr = p.providers.get(i);
                     if (isMatch(state, pr.info, flags)) {
-                        res[num++] = generateProviderInfo(pr, flags, state, userId);
+                        res[num++] = generateProviderInfo(pr, flags, state, userId,
+                                applicationInfo);
                     }
                 }
                 pi.providers = ArrayUtils.trimToSize(res, num);
@@ -8216,6 +8226,11 @@
     @UnsupportedAppUsage
     public static final ActivityInfo generateActivityInfo(Activity a, int flags,
             FrameworkPackageUserState state, int userId) {
+        return generateActivityInfo(a, flags, state, userId, null);
+    }
+
+    private static ActivityInfo generateActivityInfo(Activity a, int flags,
+            FrameworkPackageUserState state, int userId, ApplicationInfo applicationInfo) {
         if (a == null) return null;
         if (!checkUseInstalledOrHidden(flags, state, a.owner.applicationInfo)) {
             return null;
@@ -8227,7 +8242,12 @@
         // Make shallow copies so we can store the metadata safely
         ActivityInfo ai = new ActivityInfo(a.info);
         ai.metaData = a.metaData;
-        ai.applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
+
+        if (applicationInfo == null) {
+            applicationInfo = generateApplicationInfo(a.owner, flags, state, userId);
+        }
+        ai.applicationInfo = applicationInfo;
+
         return ai;
     }
 
@@ -8308,6 +8328,11 @@
     @UnsupportedAppUsage
     public static final ServiceInfo generateServiceInfo(Service s, int flags,
             FrameworkPackageUserState state, int userId) {
+        return generateServiceInfo(s, flags, state, userId, null);
+    }
+
+    private static ServiceInfo generateServiceInfo(Service s, int flags,
+            FrameworkPackageUserState state, int userId, ApplicationInfo applicationInfo) {
         if (s == null) return null;
         if (!checkUseInstalledOrHidden(flags, state, s.owner.applicationInfo)) {
             return null;
@@ -8319,7 +8344,12 @@
         // Make shallow copies so we can store the metadata safely
         ServiceInfo si = new ServiceInfo(s.info);
         si.metaData = s.metaData;
-        si.applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
+
+        if (applicationInfo == null) {
+            applicationInfo = generateApplicationInfo(s.owner, flags, state, userId);
+        }
+        si.applicationInfo = applicationInfo;
+
         return si;
     }
 
@@ -8406,13 +8436,18 @@
     @UnsupportedAppUsage
     public static final ProviderInfo generateProviderInfo(Provider p, int flags,
             FrameworkPackageUserState state, int userId) {
+        return generateProviderInfo(p, flags, state, userId, null);
+    }
+
+    private static ProviderInfo generateProviderInfo(Provider p, int flags,
+            FrameworkPackageUserState state, int userId, ApplicationInfo applicationInfo) {
         if (p == null) return null;
         if (!checkUseInstalledOrHidden(flags, state, p.owner.applicationInfo)) {
             return null;
         }
         if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
                 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
-                        || p.info.uriPermissionPatterns == null)) {
+                || p.info.uriPermissionPatterns == null)) {
             updateApplicationInfo(p.info.applicationInfo, flags, state);
             return p.info;
         }
@@ -8422,7 +8457,12 @@
         if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
             pi.uriPermissionPatterns = null;
         }
-        pi.applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
+
+        if (applicationInfo == null) {
+            applicationInfo = generateApplicationInfo(p.owner, flags, state, userId);
+        }
+        pi.applicationInfo = applicationInfo;
+
         return pi;
     }
 
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index dac55ae..8db298f 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -1325,7 +1325,8 @@
      * flashlight brightness level via
      * {@link android.hardware.camera2.CameraManager#turnOnTorchWithStrengthLevel }.
      * If this value is equal to 1, flashlight brightness control is not supported.
-     * The value for this key will be null for devices with no flash unit.</p>
+     * The value for this key will be null for devices with no flash unit.
+     * This level must be set to a safe value to prevent any burn out issues.</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
      */
     @PublicKey
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index cb8b973..fbfeac7 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -3782,6 +3782,7 @@
             }
         }
         mFirstInputStage.onWindowFocusChanged(hasWindowFocus);
+        mOnBackInvokedDispatcher.onWindowFocusChanged(hasWindowFocus);
 
         // NOTE: there's no view visibility (appeared / disapparead) events when the windows focus
         // is lost, so we don't need to to force a flush - there might be other events such as
diff --git a/core/java/android/window/ImeOnBackInvokedDispatcher.java b/core/java/android/window/ImeOnBackInvokedDispatcher.java
index 5924844..f1a052b 100644
--- a/core/java/android/window/ImeOnBackInvokedDispatcher.java
+++ b/core/java/android/window/ImeOnBackInvokedDispatcher.java
@@ -81,8 +81,10 @@
             @OnBackInvokedDispatcher.Priority int priority,
             @NonNull OnBackInvokedCallback callback) {
         final Bundle bundle = new Bundle();
+        // Always invoke back for ime without checking the window focus.
         final IOnBackInvokedCallback iCallback =
-                new WindowOnBackInvokedDispatcher.OnBackInvokedCallbackWrapper(callback);
+                new WindowOnBackInvokedDispatcher.OnBackInvokedCallbackWrapper(callback,
+                        () -> true);
         bundle.putBinder(RESULT_KEY_CALLBACK, iCallback.asBinder());
         bundle.putInt(RESULT_KEY_PRIORITY, priority);
         bundle.putInt(RESULT_KEY_ID, callback.hashCode());
diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java
index d147524d..02c5ebc 100644
--- a/core/java/android/window/WindowOnBackInvokedDispatcher.java
+++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java
@@ -32,6 +32,7 @@
 import java.util.HashMap;
 import java.util.Objects;
 import java.util.TreeMap;
+import java.util.function.Supplier;
 
 /**
  * Provides window based implementation of {@link OnBackInvokedDispatcher}.
@@ -64,6 +65,7 @@
     private final TreeMap<Integer, ArrayList<OnBackInvokedCallback>>
             mOnBackInvokedCallbacks = new TreeMap<>();
     private final Checker mChecker;
+    private boolean mHasFocus;
 
     public WindowOnBackInvokedDispatcher(boolean applicationCallBackEnabled) {
         mChecker = new Checker(applicationCallBackEnabled);
@@ -189,7 +191,7 @@
                                     .ImeOnBackInvokedCallback
                                 ? ((ImeOnBackInvokedDispatcher.ImeOnBackInvokedCallback)
                                         callback).getIOnBackInvokedCallback()
-                                : new OnBackInvokedCallbackWrapper(callback);
+                                : new OnBackInvokedCallbackWrapper(callback, this::hasFocus);
                 callbackInfo = new OnBackInvokedCallbackInfo(iCallback, priority);
             }
             mWindowSession.setOnBackInvokedCallbackInfo(mWindow, callbackInfo);
@@ -198,6 +200,17 @@
         }
     }
 
+    /**
+     * Called when window focus changed.
+     */
+    public void onWindowFocusChanged(boolean hasFocus) {
+        mHasFocus = hasFocus;
+    }
+
+    private boolean hasFocus() {
+        return mHasFocus;
+    }
+
     public OnBackInvokedCallback getTopCallback() {
         if (mAllCallbacks.isEmpty()) {
             return null;
@@ -221,9 +234,11 @@
 
     static class OnBackInvokedCallbackWrapper extends IOnBackInvokedCallback.Stub {
         private final WeakReference<OnBackInvokedCallback> mCallback;
-
-        OnBackInvokedCallbackWrapper(@NonNull OnBackInvokedCallback callback) {
+        private final Supplier<Boolean> mHasFocus;
+        OnBackInvokedCallbackWrapper(@NonNull OnBackInvokedCallback callback,
+                @NonNull Supplier<Boolean> hasFocus) {
             mCallback = new WeakReference<>(callback);
+            mHasFocus = hasFocus;
         }
 
         @Override
@@ -263,7 +278,10 @@
                 if (callback == null) {
                     return;
                 }
-
+                if (!mHasFocus.get()) {
+                    Log.w(TAG, "Skip back invoke due to current focus has lost.");
+                    return;
+                }
                 callback.onBackInvoked();
             });
         }
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index ef6fd7d..be82879 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -36,7 +36,6 @@
 #include <inttypes.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <linux/fs.h>
 
 #include <memory>
 
@@ -254,16 +253,6 @@
         return INSTALL_FAILED_CONTAINER_ERROR;
     }
 
-    // If a filesystem like f2fs supports per-file compression, set the compression bit before data
-    // writes
-    unsigned int flags;
-    if (ioctl(fd, FS_IOC_GETFLAGS, &flags) == -1) {
-        ALOGE("Failed to call FS_IOC_GETFLAGS on %s: %s\n", localTmpFileName, strerror(errno));
-    } else if ((flags & FS_COMPR_FL) == 0) {
-        flags |= FS_COMPR_FL;
-        ioctl(fd, FS_IOC_SETFLAGS, &flags);
-    }
-
     if (!zipFile->uncompressEntry(zipEntry, fd)) {
         ALOGE("Failed uncompressing %s to %s\n", fileName, localTmpFileName);
         close(fd);
diff --git a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
index f448cb3..b5194f6 100644
--- a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
+++ b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
@@ -66,6 +66,7 @@
         MockitoAnnotations.initMocks(this);
         mDispatcher = new WindowOnBackInvokedDispatcher(true /* applicationCallbackEnabled */);
         mDispatcher.attachToWindow(mWindowSession, mWindow);
+        mDispatcher.onWindowFocusChanged(true);
     }
 
     private void waitForIdle() {
@@ -152,4 +153,31 @@
         waitForIdle();
         verify(mCallback2).onBackStarted();
     }
+
+    @Test
+    public void skipBackInvokeWhenNoFocus() throws RemoteException {
+        ArgumentCaptor<OnBackInvokedCallbackInfo> captor =
+                ArgumentCaptor.forClass(OnBackInvokedCallbackInfo.class);
+
+        mDispatcher.registerOnBackInvokedCallback(
+                OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCallback1);
+
+        verify(mWindowSession, times(1)).setOnBackInvokedCallbackInfo(
+                Mockito.eq(mWindow),
+                captor.capture());
+
+        verify(mWindowSession).setOnBackInvokedCallbackInfo(Mockito.eq(mWindow), captor.capture());
+
+        // Should invoke back if it's still in focused.
+        captor.getValue().getCallback().onBackInvoked();
+        waitForIdle();
+        verify(mCallback1).onBackInvoked();
+
+        // In case the focus has lost during back gesture.
+        mDispatcher.onWindowFocusChanged(false);
+
+        captor.getValue().getCallback().onBackInvoked();
+        waitForIdle();
+        verifyZeroInteractions(mCallback1);
+    }
 }
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index 84e949a..f8c015f 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -932,7 +932,7 @@
         <font weight="700" style="normal" fallbackFor="serif">NotoSerifLao-Bold.ttf</font>
     </family>
     <family lang="und-Laoo" variant="compact">
-        <font weight="400" style="normal">NotoSansLaoUI-Regular.ttf
+        <font weight="400" style="normal" postScriptName="NotoSansLaoUI">NotoSansLaoUI-Regular.ttf
         </font>
         <font weight="700" style="normal">NotoSansLaoUI-Bold.ttf</font>
     </family>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index b69cbfa..40cf9a3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -727,31 +727,23 @@
             ActivityManager.RunningTaskInfo taskInfo1, ActivityManager.RunningTaskInfo taskInfo2) {
         if (offsetX == 0 && offsetY == 0) {
             wct.setBounds(taskInfo1.token, mBounds1);
-            wct.setAppBounds(taskInfo1.token, null);
             wct.setScreenSizeDp(taskInfo1.token,
                     SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
 
             wct.setBounds(taskInfo2.token, mBounds2);
-            wct.setAppBounds(taskInfo2.token, null);
             wct.setScreenSizeDp(taskInfo2.token,
                     SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
         } else {
-            mTempRect.set(taskInfo1.configuration.windowConfiguration.getBounds());
+            getBounds1(mTempRect);
             mTempRect.offset(offsetX, offsetY);
             wct.setBounds(taskInfo1.token, mTempRect);
-            mTempRect.set(taskInfo1.configuration.windowConfiguration.getAppBounds());
-            mTempRect.offset(offsetX, offsetY);
-            wct.setAppBounds(taskInfo1.token, mTempRect);
             wct.setScreenSizeDp(taskInfo1.token,
                     taskInfo1.configuration.screenWidthDp,
                     taskInfo1.configuration.screenHeightDp);
 
-            mTempRect.set(taskInfo2.configuration.windowConfiguration.getBounds());
+            getBounds2(mTempRect);
             mTempRect.offset(offsetX, offsetY);
             wct.setBounds(taskInfo2.token, mTempRect);
-            mTempRect.set(taskInfo2.configuration.windowConfiguration.getAppBounds());
-            mTempRect.offset(offsetX, offsetY);
-            wct.setAppBounds(taskInfo2.token, mTempRect);
             wct.setScreenSizeDp(taskInfo2.token,
                     taskInfo2.configuration.screenWidthDp,
                     taskInfo2.configuration.screenHeightDp);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
index c672476..24f02ac 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
@@ -681,9 +681,12 @@
             return;
         }
 
+        if (mState.getState() == STATE_ACTIVE) {
+            mOneHandedUiEventLogger.writeEvent(
+                    OneHandedUiEventLogger.EVENT_ONE_HANDED_TRIGGER_ROTATION_OUT);
+        }
+
         mDisplayAreaOrganizer.onRotateDisplay(mContext, toRotation, wct);
-        mOneHandedUiEventLogger.writeEvent(
-                OneHandedUiEventLogger.EVENT_ONE_HANDED_TRIGGER_ROTATION_OUT);
     }
 
     /**
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
index 7b9c1bc..42aac57 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
@@ -106,6 +106,11 @@
         super.focusChanges()
     }
 
+    /** {@inheritDoc}  */
+    @Postsubmit
+    @Test
+    override fun pipAppWindowAlwaysVisible() = super.pipAppWindowAlwaysVisible()
+
     @Presubmit
     @Test
     override fun entireScreenCovered() {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
index 90ae36c..f0c96ac 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
@@ -79,7 +79,7 @@
      */
     @Presubmit
     @Test
-    fun pipAppWindowAlwaysVisible() {
+    open fun pipAppWindowAlwaysVisible() {
         testSpec.assertWm {
             this.isAppWindowVisible(pipApp)
         }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
index a04ca09..b5a3c78 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
@@ -84,6 +84,11 @@
     @Test
     override fun entireScreenCovered() = super.entireScreenCovered()
 
+    /** {@inheritDoc}  */
+    @FlakyTest(bugId = 197726610)
+    @Test
+    override fun pipLayerExpands() = super.pipLayerExpands()
+
     companion object {
         /**
          * Creates the test configurations.
diff --git a/libs/hwui/jni/Typeface.cpp b/libs/hwui/jni/Typeface.cpp
index e79b395..30d6d00 100644
--- a/libs/hwui/jni/Typeface.cpp
+++ b/libs/hwui/jni/Typeface.cpp
@@ -111,15 +111,15 @@
     std::vector<std::shared_ptr<minikin::FontFamily>> familyVec;
     Typeface* typeface = (fallbackPtr == 0) ? nullptr : toTypeface(fallbackPtr);
     if (typeface != nullptr) {
-        const std::vector<std::shared_ptr<minikin::FontFamily>>& fallbackFamilies =
-            toTypeface(fallbackPtr)->fFontCollection->getFamilies();
-        familyVec.reserve(families.size() + fallbackFamilies.size());
+        const std::shared_ptr<minikin::FontCollection>& fallbackCollection =
+                toTypeface(fallbackPtr)->fFontCollection;
+        familyVec.reserve(families.size() + fallbackCollection->getFamilyCount());
         for (size_t i = 0; i < families.size(); i++) {
             FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(families[i]);
             familyVec.emplace_back(family->family);
         }
-        for (size_t i = 0; i < fallbackFamilies.size(); i++) {
-            familyVec.emplace_back(fallbackFamilies[i]);
+        for (size_t i = 0; i < fallbackCollection->getFamilyCount(); i++) {
+            familyVec.emplace_back(fallbackCollection->getFamilyAt(i));
         }
     } else {
         familyVec.reserve(families.size());
@@ -360,13 +360,13 @@
 
 // Critical Native
 static jint Typeface_getFamilySize(CRITICAL_JNI_PARAMS_COMMA jlong faceHandle) {
-    return toTypeface(faceHandle)->fFontCollection->getFamilies().size();
+    return toTypeface(faceHandle)->fFontCollection->getFamilyCount();
 }
 
 // Critical Native
 static jlong Typeface_getFamily(CRITICAL_JNI_PARAMS_COMMA jlong faceHandle, jint index) {
     std::shared_ptr<minikin::FontFamily> family =
-            toTypeface(faceHandle)->fFontCollection->getFamilies()[index];
+            toTypeface(faceHandle)->fFontCollection->getFamilyAt(index);
     return reinterpret_cast<jlong>(new FontFamilyWrapper(std::move(family)));
 }
 
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index 071667a..c84f5b0 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -172,7 +172,7 @@
             try {
                 mMediaRouterService.startScan(client);
             } catch (RemoteException ex) {
-                Log.e(TAG, "Unable to get sessions. Service probably died.", ex);
+                throw ex.rethrowFromSystemServer();
             }
         }
     }
@@ -196,7 +196,7 @@
             try {
                 mMediaRouterService.stopScan(client);
             } catch (RemoteException ex) {
-                Log.e(TAG, "Unable to get sessions. Service probably died.", ex);
+                throw ex.rethrowFromSystemServer();
             }
         }
     }
@@ -361,9 +361,8 @@
             return mMediaRouterService.getSystemSessionInfoForPackage(
                     getOrCreateClient(), packageName);
         } catch (RemoteException ex) {
-            Log.e(TAG, "Unable to get current system session info", ex);
+            throw ex.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
@@ -429,7 +428,7 @@
             try {
                 return mMediaRouterService.getRemoteSessions(client);
             } catch (RemoteException ex) {
-                Log.e(TAG, "Unable to get sessions. Service probably died.", ex);
+                throw ex.rethrowFromSystemServer();
             }
         }
         return Collections.emptyList();
@@ -521,7 +520,7 @@
                 int requestId = mNextRequestId.getAndIncrement();
                 mMediaRouterService.setRouteVolumeWithManager(client, requestId, route, volume);
             } catch (RemoteException ex) {
-                Log.e(TAG, "Unable to set route volume.", ex);
+                throw ex.rethrowFromSystemServer();
             }
         }
     }
@@ -551,7 +550,7 @@
                 mMediaRouterService.setSessionVolumeWithManager(
                         client, requestId, sessionInfo.getId(), volume);
             } catch (RemoteException ex) {
-                Log.e(TAG, "Unable to set session volume.", ex);
+                throw ex.rethrowFromSystemServer();
             }
         }
     }
@@ -816,7 +815,7 @@
                 mMediaRouterService.selectRouteWithManager(
                         client, requestId, sessionInfo.getId(), route);
             } catch (RemoteException ex) {
-                Log.e(TAG, "selectRoute: Failed to send a request.", ex);
+                throw ex.rethrowFromSystemServer();
             }
         }
     }
@@ -858,7 +857,7 @@
                 mMediaRouterService.deselectRouteWithManager(
                         client, requestId, sessionInfo.getId(), route);
             } catch (RemoteException ex) {
-                Log.e(TAG, "deselectRoute: Failed to send a request.", ex);
+                throw ex.rethrowFromSystemServer();
             }
         }
     }
@@ -883,7 +882,7 @@
                 mMediaRouterService.releaseSessionWithManager(
                         client, requestId, sessionInfo.getId());
             } catch (RemoteException ex) {
-                Log.e(TAG, "releaseSession: Failed to send a request", ex);
+                throw ex.rethrowFromSystemServer();
             }
         }
     }
@@ -903,7 +902,7 @@
                 mMediaRouterService.transferToRouteWithManager(
                         client, requestId, session.getId(), route);
             } catch (RemoteException ex) {
-                Log.e(TAG, "transferToRoute: Failed to send a request.", ex);
+                throw ex.rethrowFromSystemServer();
             }
         }
     }
@@ -923,7 +922,7 @@
                 mMediaRouterService.requestCreateSessionWithManager(
                         client, requestId, oldSession, route);
             } catch (RemoteException ex) {
-                Log.e(TAG, "requestCreateSession: Failed to send a request", ex);
+                throw ex.rethrowFromSystemServer();
             }
         }
     }
@@ -979,10 +978,9 @@
                 mClient = client;
                 return client;
             } catch (RemoteException ex) {
-                Log.e(TAG, "Unable to register media router manager.", ex);
+                throw ex.rethrowFromSystemServer();
             }
         }
-        return null;
     }
 
     /**
diff --git a/native/android/system_fonts.cpp b/native/android/system_fonts.cpp
index 9fe7929..4df745f 100644
--- a/native/android/system_fonts.cpp
+++ b/native/android/system_fonts.cpp
@@ -248,9 +248,10 @@
     minikin::SystemFonts::getFontMap(
             [&fonts](const std::vector<std::shared_ptr<minikin::FontCollection>>& collections) {
                 for (const auto& fc : collections) {
-                    for (const auto& family : fc->getFamilies()) {
-                        for (uint32_t i = 0; i < family->getNumFonts(); ++i) {
-                            const minikin::Font* font = family->getFont(i);
+                    for (uint32_t i = 0; i < fc->getFamilyCount(); ++i) {
+                        const auto& family = fc->getFamilyAt(i);
+                        for (uint32_t j = 0; j < family->getNumFonts(); ++j) {
+                            const minikin::Font* font = family->getFont(j);
 
                             std::optional<std::string> locale;
                             uint32_t localeId = font->getLocaleListId();
diff --git a/packages/SettingsLib/LayoutPreference/res/layout/settings_entity_header.xml b/packages/SettingsLib/LayoutPreference/res/layout/settings_entity_header.xml
index 50f69d1..c629d96 100644
--- a/packages/SettingsLib/LayoutPreference/res/layout/settings_entity_header.xml
+++ b/packages/SettingsLib/LayoutPreference/res/layout/settings_entity_header.xml
@@ -71,6 +71,8 @@
         <TextView
             android:id="@+id/entity_header_second_summary"
             style="@style/TextAppearance.EntityHeaderSummary"
+            android:singleLine="false"
+            android:maxLines="4"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"/>
 
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index a5f4133..f1745ec 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -246,9 +246,9 @@
     <!-- Bluetooth settings. The user-visible string that is used whenever referring to the PAN profile (accessing Internet through remote device). [CHAR LIMIT=40] -->
     <string name="bluetooth_profile_pan">Internet access</string>
     <!-- Bluetooth settings. The user-visible string that is used whenever referring to the PBAP profile. [CHAR LIMIT=40] -->
-    <string name="bluetooth_profile_pbap">Contact sharing</string>
+    <string name="bluetooth_profile_pbap">Contacts and call history sharing</string>
     <!-- Bluetooth settings. The user-visible summary string that is used whenever referring to the PBAP profile (sharing contacts). [CHAR LIMIT=60] -->
-    <string name="bluetooth_profile_pbap_summary">Use for contact sharing</string>
+    <string name="bluetooth_profile_pbap_summary">Use for contacts and call history sharing</string>
     <!-- Bluetooth settings. The user-visible string that is used whenever referring to the PAN profile (sharing this device's Internet connection). [CHAR LIMIT=40] -->
     <string name="bluetooth_profile_pan_nap">Internet connection sharing</string>
     <!-- Bluetooth settings. The user-visible string that is used whenever referring to the map profile. -->
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt
index 47f448d..eb000ad 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt
@@ -49,17 +49,16 @@
  * Note: Avoid instantiating this directly and call [ActivityLaunchAnimator.Controller.fromView]
  * whenever possible instead.
  */
-open class GhostedViewLaunchAnimatorController(
+open class GhostedViewLaunchAnimatorController @JvmOverloads constructor(
     /** The view that will be ghosted and from which the background will be extracted. */
     private val ghostedView: View,
 
     /** The [InteractionJankMonitor.CujType] associated to this animation. */
     private val cujType: Int? = null,
-    private var interactionJankMonitor: InteractionJankMonitor? = null
+    private var interactionJankMonitor: InteractionJankMonitor =
+        InteractionJankMonitor.getInstance(),
 ) : ActivityLaunchAnimator.Controller {
 
-    constructor(view: View, type: Int) : this(view, type, null)
-
     /** The container to which we will add the ghost view and expanding background. */
     override var launchContainer = ghostedView.rootView as ViewGroup
     private val launchContainerOverlay: ViewGroupOverlay
@@ -203,7 +202,7 @@
         val matrix = ghostView?.animationMatrix ?: Matrix.IDENTITY_MATRIX
         matrix.getValues(initialGhostViewMatrixValues)
 
-        cujType?.let { interactionJankMonitor?.begin(ghostedView, it) }
+        cujType?.let { interactionJankMonitor.begin(ghostedView, it) }
     }
 
     override fun onLaunchAnimationProgress(
@@ -289,7 +288,7 @@
             return
         }
 
-        cujType?.let { interactionJankMonitor?.end(it) }
+        cujType?.let { interactionJankMonitor.end(it) }
 
         backgroundDrawable?.wrapped?.alpha = startBackgroundAlpha
 
diff --git a/packages/SystemUI/res/layout/clipboard_overlay.xml b/packages/SystemUI/res/layout/clipboard_overlay.xml
index 99a5a2e..1a1fc75 100644
--- a/packages/SystemUI/res/layout/clipboard_overlay.xml
+++ b/packages/SystemUI/res/layout/clipboard_overlay.xml
@@ -115,6 +115,7 @@
                   android:autoSizeMinTextSize="@dimen/clipboard_overlay_min_font"
                   android:autoSizeMaxTextSize="@dimen/clipboard_overlay_max_font"
                   android:textColor="?attr/overlayButtonTextColor"
+                  android:textColorLink="?attr/overlayButtonTextColor"
                   android:background="?androidprv:attr/colorAccentSecondary"
                   android:layout_width="@dimen/clipboard_preview_size"
                   android:layout_height="@dimen/clipboard_preview_size"/>
diff --git a/packages/SystemUI/res/layout/keyguard_status_bar.xml b/packages/SystemUI/res/layout/keyguard_status_bar.xml
index e47eed9..d27fa19 100644
--- a/packages/SystemUI/res/layout/keyguard_status_bar.xml
+++ b/packages/SystemUI/res/layout/keyguard_status_bar.xml
@@ -60,9 +60,8 @@
         </com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer>
 
         <FrameLayout android:id="@+id/system_icons_container"
-            android:layout_width="0dp"
+            android:layout_width="wrap_content"
             android:layout_height="match_parent"
-            android:layout_weight="1"
             android:layout_marginEnd="@dimen/status_bar_padding_end"
             android:gravity="center_vertical|end">
             <include layout="@layout/system_icons" />
diff --git a/packages/SystemUI/res/layout/notification_icon_area.xml b/packages/SystemUI/res/layout/notification_icon_area.xml
index fa696cc..aadfae8 100644
--- a/packages/SystemUI/res/layout/notification_icon_area.xml
+++ b/packages/SystemUI/res/layout/notification_icon_area.xml
@@ -14,18 +14,9 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License
   -->
-<com.android.keyguard.AlphaOptimizedLinearLayout
+<com.android.systemui.statusbar.phone.NotificationIconContainer
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/notification_icon_area_inner"
-    android:layout_width="match_parent"
+    android:id="@+id/notificationIcons"
+    android:layout_width="wrap_content"
     android:layout_height="match_parent"
-    android:clipChildren="false">
-    <com.android.systemui.statusbar.phone.NotificationIconContainer
-        android:id="@+id/notificationIcons"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_alignParentStart="true"
-        android:gravity="center_vertical"
-        android:orientation="horizontal"
-        android:clipChildren="false"/>
-</com.android.keyguard.AlphaOptimizedLinearLayout>
\ No newline at end of file
+    android:clipChildren="false"/>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index f560e61..80e65a3 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -47,52 +47,63 @@
         android:paddingStart="@dimen/status_bar_padding_start"
         android:paddingEnd="@dimen/status_bar_padding_end"
         android:paddingTop="@dimen/status_bar_padding_top"
-        android:orientation="horizontal"
-        >
+        android:orientation="horizontal">
+
+        <!-- Container for the entire start half of the status bar. It will always use the same
+             width, independent of the number of visible children and sub-children. -->
         <FrameLayout
+            android:id="@+id/status_bar_start_side_container"
             android:layout_height="match_parent"
             android:layout_width="0dp"
             android:layout_weight="1">
 
-            <include layout="@layout/heads_up_status_bar_layout" />
+            <!-- Container that is wrapped around the views on the start half of the status bar.
+                 Its width will change with the number of visible children and sub-children.
+                 It is useful when we want to know the visible bounds of the content. -->
+            <FrameLayout
+                android:id="@+id/status_bar_start_side_content"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:clipChildren="false">
 
-            <!-- The alpha of the left side is controlled by PhoneStatusBarTransitions, and the
-             individual views are controlled by StatusBarManager disable flags DISABLE_CLOCK and
-             DISABLE_NOTIFICATION_ICONS, respectively -->
-            <LinearLayout
-                android:id="@+id/status_bar_left_side"
-                android:layout_height="match_parent"
-                android:layout_width="match_parent"
-                android:clipChildren="false"
-            >
-                <ViewStub
-                    android:id="@+id/operator_name"
-                    android:layout_width="wrap_content"
-                    android:layout_height="match_parent"
-                    android:layout="@layout/operator_name" />
+                <include layout="@layout/heads_up_status_bar_layout" />
 
-                <com.android.systemui.statusbar.policy.Clock
-                    android:id="@+id/clock"
-                    android:layout_width="wrap_content"
-                    android:layout_height="match_parent"
-                    android:textAppearance="@style/TextAppearance.StatusBar.Clock"
-                    android:singleLine="true"
-                    android:paddingStart="@dimen/status_bar_left_clock_starting_padding"
-                    android:paddingEnd="@dimen/status_bar_left_clock_end_padding"
-                    android:gravity="center_vertical|start"
-                />
+                <!-- The alpha of the start side is controlled by PhoneStatusBarTransitions, and the
+                     individual views are controlled by StatusBarManager disable flags DISABLE_CLOCK
+                     and DISABLE_NOTIFICATION_ICONS, respectively -->
+                <LinearLayout
+                    android:id="@+id/status_bar_start_side_except_heads_up"
+                    android:layout_height="wrap_content"
+                    android:layout_width="match_parent"
+                    android:clipChildren="false">
+                    <ViewStub
+                        android:id="@+id/operator_name"
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:layout="@layout/operator_name" />
 
-                <include layout="@layout/ongoing_call_chip" />
+                    <com.android.systemui.statusbar.policy.Clock
+                        android:id="@+id/clock"
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+                        android:singleLine="true"
+                        android:paddingStart="@dimen/status_bar_left_clock_starting_padding"
+                        android:paddingEnd="@dimen/status_bar_left_clock_end_padding"
+                        android:gravity="center_vertical|start"
+                    />
 
-                <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
-                    android:id="@+id/notification_icon_area"
-                    android:layout_width="0dp"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:orientation="horizontal"
-                    android:clipChildren="false"/>
+                    <include layout="@layout/ongoing_call_chip" />
 
-            </LinearLayout>
+                    <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
+                        android:id="@+id/notification_icon_area"
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:orientation="horizontal"
+                        android:clipChildren="false"/>
+
+                </LinearLayout>
+            </FrameLayout>
         </FrameLayout>
 
         <!-- Space should cover the notch (if it exists) and let other views lay out around it -->
@@ -103,42 +114,57 @@
             android:gravity="center_horizontal|center_vertical"
         />
 
-        <com.android.keyguard.AlphaOptimizedLinearLayout android:id="@+id/system_icon_area"
+        <!-- Container for the entire end half of the status bar. It will always use the same
+             width, independent of the number of visible children and sub-children. -->
+        <FrameLayout
+            android:id="@+id/status_bar_end_side_container"
             android:layout_width="0dp"
             android:layout_height="match_parent"
             android:layout_weight="1"
-            android:orientation="horizontal"
-            android:gravity="center_vertical|end"
-            >
+            android:clipChildren="false">
 
-            <com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer
-                android:id="@+id/user_switcher_container"
+            <!-- Container that is wrapped around the views on the end half of the
+                 status bar. Its width will change with the number of visible children and
+                 sub-children.
+                 It is useful when we want know the visible bounds of the content.-->
+            <com.android.keyguard.AlphaOptimizedLinearLayout
+                android:id="@+id/status_bar_end_side_content"
                 android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:gravity="center"
+                android:layout_height="match_parent"
+                android:layout_gravity="end"
                 android:orientation="horizontal"
-                android:paddingTop="4dp"
-                android:paddingBottom="4dp"
-                android:paddingStart="8dp"
-                android:paddingEnd="8dp"
-                android:layout_marginEnd="16dp"
-                android:background="@drawable/status_bar_user_chip_bg"
-                android:visibility="visible" >
-                <ImageView android:id="@+id/current_user_avatar"
-                    android:layout_width="@dimen/multi_user_avatar_keyguard_size"
-                    android:layout_height="@dimen/multi_user_avatar_keyguard_size"
-                    android:scaleType="centerInside"
-                    android:paddingEnd="4dp" />
+                android:gravity="center_vertical|end"
+                android:clipChildren="false">
 
-                <TextView android:id="@+id/current_user_name"
+                <com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer
+                    android:id="@+id/user_switcher_container"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:textAppearance="@style/TextAppearance.StatusBar.Clock"
-                    />
-            </com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer>
+                    android:gravity="center"
+                    android:orientation="horizontal"
+                    android:paddingTop="4dp"
+                    android:paddingBottom="4dp"
+                    android:paddingStart="8dp"
+                    android:paddingEnd="8dp"
+                    android:layout_marginEnd="16dp"
+                    android:background="@drawable/status_bar_user_chip_bg"
+                    android:visibility="visible" >
+                    <ImageView android:id="@+id/current_user_avatar"
+                        android:layout_width="@dimen/multi_user_avatar_keyguard_size"
+                        android:layout_height="@dimen/multi_user_avatar_keyguard_size"
+                        android:scaleType="centerInside"
+                        android:paddingEnd="4dp" />
 
-            <include layout="@layout/system_icons" />
-        </com.android.keyguard.AlphaOptimizedLinearLayout>
+                    <TextView android:id="@+id/current_user_name"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+                        />
+                </com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer>
+
+                <include layout="@layout/system_icons" />
+            </com.android.keyguard.AlphaOptimizedLinearLayout>
+        </FrameLayout>
     </LinearLayout>
 
 </com.android.systemui.statusbar.phone.PhoneStatusBarView>
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
index 15c1761..a553e19 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
@@ -145,6 +145,9 @@
     public static final ResourceBooleanFlag STATUS_BAR_USER_SWITCHER =
             new ResourceBooleanFlag(602, R.bool.flag_user_switcher_chip);
 
+    public static final BooleanFlag STATUS_BAR_LETTERBOX_APPEARANCE =
+            new BooleanFlag(603, false);
+
     /***************************************/
     // 700 - dialer/calls
     public static final BooleanFlag ONGOING_CALL_STATUS_BAR_CHIP =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index 2dc3261..a2140c6ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License
  */
-
 package com.android.systemui.statusbar.phone;
 
 import static com.android.systemui.statusbar.phone.HeadsUpAppearanceController.CONTENT_FADE_DELAY;
@@ -31,6 +30,7 @@
 import android.util.Property;
 import android.view.ContextThemeWrapper;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.animation.Interpolator;
 
 import androidx.annotation.VisibleForTesting;
@@ -40,7 +40,6 @@
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
 import com.android.systemui.animation.Interpolators;
-import com.android.systemui.statusbar.AlphaOptimizedFrameLayout;
 import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.notification.stack.AnimationFilter;
 import com.android.systemui.statusbar.notification.stack.AnimationProperties;
@@ -54,7 +53,7 @@
  * A container for notification icons. It handles overflowing icons properly and positions them
  * correctly on the screen.
  */
-public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
+public class NotificationIconContainer extends ViewGroup {
     /**
      * A float value indicating how much before the overflow start the icons should transform into
      * a dot. A value of 0 means that they are exactly at the end and a value of 1 means it starts
@@ -232,6 +231,31 @@
     }
 
     @Override
+    public boolean hasOverlappingRendering() {
+        // Does the same as "AlphaOptimizedFrameLayout".
+        return false;
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        final int childCount = getChildCount();
+        final int maxVisibleIcons = getMaxVisibleIcons(childCount);
+        final int width = MeasureSpec.getSize(widthMeasureSpec);
+        final int childWidthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.UNSPECIFIED);
+        int totalWidth = (int) (getActualPaddingStart() + getActualPaddingEnd());
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            measureChild(child, childWidthSpec, heightMeasureSpec);
+            if (i <= maxVisibleIcons) {
+                totalWidth += child.getMeasuredWidth();
+            }
+        }
+        final int measuredWidth = resolveSize(totalWidth, widthMeasureSpec);
+        final int measuredHeight = MeasureSpec.getSize(heightMeasureSpec);
+        setMeasuredDimension(measuredWidth, measuredHeight);
+    }
+
+    @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         float centerY = getHeight() / 2.0f;
         // we layout all our children on the left at the top
@@ -408,8 +432,7 @@
         float translationX = getActualPaddingStart();
         int firstOverflowIndex = -1;
         int childCount = getChildCount();
-        int maxVisibleIcons = mOnLockScreen ? MAX_ICONS_ON_AOD :
-                mIsStaticLayout ? MAX_STATIC_ICONS : childCount;
+        int maxVisibleIcons = getMaxVisibleIcons(childCount);
         float layoutEnd = getLayoutEnd();
         mVisualOverflowStart = 0;
         mFirstVisibleIconState = null;
@@ -493,6 +516,11 @@
         }
     }
 
+    private int getMaxVisibleIcons(int childCount) {
+        return mOnLockScreen ? MAX_ICONS_ON_AOD :
+                mIsStaticLayout ? MAX_STATIC_ICONS : childCount;
+    }
+
     private float getLayoutEnd() {
         return getActualWidth() - getActualPaddingEnd();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
index 2052ee6..15c6dcf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarTransitions.java
@@ -31,7 +31,7 @@
 
     private final float mIconAlphaWhenOpaque;
 
-    private View mLeftSide, mStatusIcons, mBattery;
+    private View mStartSide, mStatusIcons, mBattery;
     private Animator mCurrentAnimation;
 
     /**
@@ -41,7 +41,7 @@
         super(backgroundView, R.drawable.status_background);
         final Resources res = statusBarView.getContext().getResources();
         mIconAlphaWhenOpaque = res.getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1);
-        mLeftSide = statusBarView.findViewById(R.id.status_bar_left_side);
+        mStartSide = statusBarView.findViewById(R.id.status_bar_start_side_except_heads_up);
         mStatusIcons = statusBarView.findViewById(R.id.statusIcons);
         mBattery = statusBarView.findViewById(R.id.battery);
         applyModeBackground(-1, getMode(), false /*animate*/);
@@ -75,7 +75,7 @@
     }
 
     private void applyMode(int mode, boolean animate) {
-        if (mLeftSide == null) return; // pre-init
+        if (mStartSide == null) return; // pre-init
         float newAlpha = getNonBatteryClockAlphaFor(mode);
         float newAlphaBC = getBatteryClockAlpha(mode);
         if (mCurrentAnimation != null) {
@@ -84,7 +84,7 @@
         if (animate) {
             AnimatorSet anims = new AnimatorSet();
             anims.playTogether(
-                    animateTransitionTo(mLeftSide, newAlpha),
+                    animateTransitionTo(mStartSide, newAlpha),
                     animateTransitionTo(mStatusIcons, newAlpha),
                     animateTransitionTo(mBattery, newAlphaBC)
                     );
@@ -94,7 +94,7 @@
             anims.start();
             mCurrentAnimation = anims;
         } else {
-            mLeftSide.setAlpha(newAlpha);
+            mStartSide.setAlpha(newAlpha);
             mStatusIcons.setAlpha(newAlpha);
             mBattery.setAlpha(newAlphaBC);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
index 9da2ef73..f9c4c8f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
@@ -21,7 +21,6 @@
 import android.view.View
 import android.view.ViewGroup
 import android.view.ViewTreeObserver
-
 import com.android.systemui.R
 import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator
 import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherController
@@ -32,9 +31,7 @@
 import com.android.systemui.util.ViewController
 import com.android.systemui.util.kotlin.getOrNull
 import com.android.systemui.util.view.ViewUtil
-
 import java.util.Optional
-
 import javax.inject.Inject
 import javax.inject.Named
 
@@ -58,8 +55,8 @@
     override fun onViewAttached() {
         if (moveFromCenterAnimationController == null) return
 
-        val statusBarLeftSide: View = mView.findViewById(R.id.status_bar_left_side)
-        val systemIconArea: ViewGroup = mView.findViewById(R.id.system_icon_area)
+        val statusBarLeftSide: View = mView.findViewById(R.id.status_bar_start_side_except_heads_up)
+        val systemIconArea: ViewGroup = mView.findViewById(R.id.status_bar_end_side_content)
 
         val viewsToAnimate = arrayOf(
             statusBarLeftSide,
@@ -126,11 +123,11 @@
     class StatusBarViewsCenterProvider : UnfoldMoveFromCenterAnimator.ViewCenterProvider {
         override fun getViewCenter(view: View, outPoint: Point) =
             when (view.id) {
-                R.id.status_bar_left_side -> {
+                R.id.status_bar_start_side_except_heads_up -> {
                     // items aligned to the start, return start center point
                     getViewEdgeCenter(view, outPoint, isStart = true)
                 }
-                R.id.system_icon_area -> {
+                R.id.status_bar_end_side_content -> {
                     // items aligned to the end, return end center point
                     getViewEdgeCenter(view, outPoint, isStart = false)
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
index 742ea83..8332f99 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
@@ -96,7 +96,7 @@
     private final StatusBarStateController mStatusBarStateController;
     private final KeyguardStateController mKeyguardStateController;
     private final NotificationPanelViewController mNotificationPanelViewController;
-    private LinearLayout mSystemIconArea;
+    private LinearLayout mEndSideContent;
     private View mClockView;
     private View mOngoingCallChip;
     private View mNotificationIconAreaInner;
@@ -217,15 +217,15 @@
         mDarkIconManager.setShouldLog(true);
         updateBlockedIcons();
         mStatusBarIconController.addIconGroup(mDarkIconManager);
-        mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
+        mEndSideContent = mStatusBar.findViewById(R.id.status_bar_end_side_content);
         mClockView = mStatusBar.findViewById(R.id.clock);
         mOngoingCallChip = mStatusBar.findViewById(R.id.ongoing_call_chip);
-        showSystemIconArea(false);
+        showEndSideContent(false);
         showClock(false);
         initOperatorName();
         initNotificationIconArea();
         mSystemEventAnimator =
-                new StatusBarSystemEventAnimator(mSystemIconArea, getResources());
+                new StatusBarSystemEventAnimator(mEndSideContent, getResources());
         mCarrierConfigTracker.addCallback(mCarrierConfigCallback);
         mCarrierConfigTracker.addDefaultDataSubscriptionChangedListener(mDefaultDataListener);
     }
@@ -351,10 +351,10 @@
         mDisabled2 = state2;
         if ((diff1 & DISABLE_SYSTEM_INFO) != 0 || ((diff2 & DISABLE2_SYSTEM_ICONS) != 0)) {
             if ((state1 & DISABLE_SYSTEM_INFO) != 0 || ((state2 & DISABLE2_SYSTEM_ICONS) != 0)) {
-                hideSystemIconArea(animate);
+                hideEndSideContent(animate);
                 hideOperatorName(animate);
             } else {
-                showSystemIconArea(animate);
+                showEndSideContent(animate);
                 showOperatorName(animate);
             }
         }
@@ -438,15 +438,15 @@
         return mStatusBarHideIconsForBouncerManager.getShouldHideStatusBarIconsForBouncer();
     }
 
-    private void hideSystemIconArea(boolean animate) {
-        animateHide(mSystemIconArea, animate);
+    private void hideEndSideContent(boolean animate) {
+        animateHide(mEndSideContent, animate);
     }
 
-    private void showSystemIconArea(boolean animate) {
+    private void showEndSideContent(boolean animate) {
         // Only show the system icon area if we are not currently animating
         int state = mAnimationScheduler.getAnimationState();
         if (state == IDLE || state == SHOWING_PERSISTENT_DOT) {
-            animateShow(mSystemIconArea, animate);
+            animateShow(mEndSideContent, animate);
         }
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
index 8a5ba42..a3f329b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
@@ -122,7 +122,7 @@
 
         fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
 
-        assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility());
+        assertEquals(View.VISIBLE, getEndSideContentView().getVisibility());
         assertEquals(View.VISIBLE, getClockView().getVisibility());
     }
 
@@ -132,11 +132,11 @@
 
         fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_SYSTEM_INFO, 0, false);
 
-        assertEquals(View.INVISIBLE, getSystemIconAreaView().getVisibility());
+        assertEquals(View.INVISIBLE, getEndSideContentView().getVisibility());
 
         fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
 
-        assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility());
+        assertEquals(View.VISIBLE, getEndSideContentView().getVisibility());
     }
 
     @Test
@@ -231,7 +231,7 @@
 
         fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
 
-        assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility());
+        assertEquals(View.VISIBLE, getEndSideContentView().getVisibility());
         assertEquals(View.VISIBLE, getClockView().getVisibility());
     }
 
@@ -242,7 +242,7 @@
 
         fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
 
-        assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility());
+        assertEquals(View.VISIBLE, getEndSideContentView().getVisibility());
         assertEquals(View.VISIBLE, getClockView().getVisibility());
     }
 
@@ -379,7 +379,7 @@
         return mFragment.getView().findViewById(R.id.clock);
     }
 
-    private View getSystemIconAreaView() {
-        return mFragment.getView().findViewById(R.id.system_icon_area);
+    private View getEndSideContentView() {
+        return mFragment.getView().findViewById(R.id.status_bar_end_side_content);
     }
 }
diff --git a/rs/OWNERS b/rs/OWNERS
index 61853d3..fd03660 100644
--- a/rs/OWNERS
+++ b/rs/OWNERS
@@ -1,5 +1,2 @@
-butlermichael@google.com
-dgross@google.com
-jeanluc@google.com
-miaowang@google.com
-yangni@google.com
+# Bug component: 43047
+include platform/frameworks/rs:/RS_OWNERS  # RenderScript team
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 46b0ded..556fa14 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -10377,6 +10377,11 @@
 
         @Override
         public void setAccessibilityServiceUids(IntArray uids) {
+            // TODO(b/233287010): Fix voice interaction and a11y concurrency in audio policy service
+            if (isPlatformAutomotive()) {
+                return;
+            }
+
             synchronized (mAccessibilityServiceUidsLock) {
                 if (uids.size() == 0) {
                     mAccessibilityServiceUids = null;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 1369f27..172cf29 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2460,11 +2460,11 @@
         SnoozeHelper snoozeHelper = new SnoozeHelper(getContext(), (userId, r, muteOnReturn) -> {
             try {
                 if (DBG) {
-                    Slog.d(TAG, "Reposting " + r.getKey());
+                    Slog.d(TAG, "Reposting " + r.getKey() + " " + muteOnReturn);
                 }
                 enqueueNotificationInternal(r.getSbn().getPackageName(), r.getSbn().getOpPkg(),
                         r.getSbn().getUid(), r.getSbn().getInitialPid(), r.getSbn().getTag(),
-                        r.getSbn().getId(),  r.getSbn().getNotification(), userId, true);
+                        r.getSbn().getId(),  r.getSbn().getNotification(), userId, muteOnReturn);
             } catch (Exception e) {
                 Slog.e(TAG, "Cannot un-snooze notification", e);
             }
diff --git a/services/core/java/com/android/server/pm/VerifyingSession.java b/services/core/java/com/android/server/pm/VerifyingSession.java
index 726bfba..9bad4a8 100644
--- a/services/core/java/com/android/server/pm/VerifyingSession.java
+++ b/services/core/java/com/android/server/pm/VerifyingSession.java
@@ -65,6 +65,7 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.incremental.IncrementalManager;
 import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.text.TextUtils;
@@ -426,10 +427,11 @@
 
         final String baseCodePath = mPackageLite.getBaseApkPath();
         final String[] splitCodePaths = mPackageLite.getSplitApkPaths();
-        final String rootHashString = PackageManagerServiceUtils.buildVerificationRootHashString(
-                baseCodePath, splitCodePaths);
 
-        if (rootHashString != null) {
+        if (IncrementalManager.isIncrementalPath(baseCodePath)) {
+            final String rootHashString =
+                    PackageManagerServiceUtils.buildVerificationRootHashString(
+                            baseCodePath, splitCodePaths);
             verification.putExtra(PackageManager.EXTRA_VERIFICATION_ROOT_HASH, rootHashString);
         }
 
diff --git a/services/core/java/com/android/server/timedetector/ConfigurationInternal.java b/services/core/java/com/android/server/timedetector/ConfigurationInternal.java
index 683eaeb..372bcc6 100644
--- a/services/core/java/com/android/server/timedetector/ConfigurationInternal.java
+++ b/services/core/java/com/android/server/timedetector/ConfigurationInternal.java
@@ -46,9 +46,10 @@
 
     private final boolean mAutoDetectionSupported;
     private final int mSystemClockUpdateThresholdMillis;
-    private final Instant mAutoTimeLowerBound;
+    private final Instant mAutoSuggestionLowerBound;
+    private final Instant mManualSuggestionLowerBound;
+    private final Instant mSuggestionUpperBound;
     private final @Origin int[] mOriginPriorities;
-    private final boolean mDeviceHasY2038Issue;
     private final boolean mAutoDetectionEnabledSetting;
     private final @UserIdInt int mUserId;
     private final boolean mUserConfigAllowed;
@@ -56,9 +57,10 @@
     private ConfigurationInternal(Builder builder) {
         mAutoDetectionSupported = builder.mAutoDetectionSupported;
         mSystemClockUpdateThresholdMillis = builder.mSystemClockUpdateThresholdMillis;
-        mAutoTimeLowerBound = Objects.requireNonNull(builder.mAutoTimeLowerBound);
+        mAutoSuggestionLowerBound = Objects.requireNonNull(builder.mAutoSuggestionLowerBound);
+        mManualSuggestionLowerBound = Objects.requireNonNull(builder.mManualSuggestionLowerBound);
+        mSuggestionUpperBound = Objects.requireNonNull(builder.mSuggestionUpperBound);
         mOriginPriorities = Objects.requireNonNull(builder.mOriginPriorities);
-        mDeviceHasY2038Issue = builder.mDeviceHasY2038Issue;
         mAutoDetectionEnabledSetting = builder.mAutoDetectionEnabledSetting;
 
         mUserId = builder.mUserId;
@@ -80,14 +82,31 @@
     }
 
     /**
-     * Returns the lower bound for valid automatic times. It is guaranteed to be in the past,
-     * i.e. it is unrelated to the current system clock time.
+     * Returns the lower bound for valid automatic time suggestions. It is guaranteed to be in the
+     * past, i.e. it is unrelated to the current system clock time.
      * It holds no other meaning; it could be related to when the device system image was built,
      * or could be updated by a mainline module.
      */
     @NonNull
-    public Instant getAutoTimeLowerBound() {
-        return mAutoTimeLowerBound;
+    public Instant getAutoSuggestionLowerBound() {
+        return mAutoSuggestionLowerBound;
+    }
+
+    /**
+     * Returns the lower bound for valid manual time suggestions. It is guaranteed to be in the
+     * past, i.e. it is unrelated to the current system clock time.
+     */
+    @NonNull
+    public Instant getManualSuggestionLowerBound() {
+        return mManualSuggestionLowerBound;
+    }
+
+    /**
+     * Returns the upper bound for valid time suggestions (manual and automatic).
+     */
+    @NonNull
+    public Instant getSuggestionUpperBound() {
+        return mSuggestionUpperBound;
     }
 
     /**
@@ -98,14 +117,6 @@
         return mOriginPriorities;
     }
 
-    /**
-     * Returns {@code true} if the device may be at risk of time_t overflow (because bionic
-     * defines time_t as a 32-bit signed integer for 32-bit processes).
-     */
-    public boolean getDeviceHasY2038Issue() {
-        return mDeviceHasY2038Issue;
-    }
-
     /** Returns the value of the auto time detection enabled setting. */
     public boolean getAutoDetectionEnabledSetting() {
         return mAutoDetectionEnabledSetting;
@@ -207,16 +218,17 @@
                 && mAutoDetectionEnabledSetting == that.mAutoDetectionEnabledSetting
                 && mUserId == that.mUserId && mUserConfigAllowed == that.mUserConfigAllowed
                 && mSystemClockUpdateThresholdMillis == that.mSystemClockUpdateThresholdMillis
-                && mAutoTimeLowerBound.equals(that.mAutoTimeLowerBound)
-                && mDeviceHasY2038Issue == that.mDeviceHasY2038Issue
+                && mAutoSuggestionLowerBound.equals(that.mAutoSuggestionLowerBound)
+                && mManualSuggestionLowerBound.equals(that.mManualSuggestionLowerBound)
+                && mSuggestionUpperBound.equals(that.mSuggestionUpperBound)
                 && Arrays.equals(mOriginPriorities, that.mOriginPriorities);
     }
 
     @Override
     public int hashCode() {
         int result = Objects.hash(mAutoDetectionSupported, mAutoDetectionEnabledSetting, mUserId,
-                mUserConfigAllowed, mSystemClockUpdateThresholdMillis, mAutoTimeLowerBound,
-                mDeviceHasY2038Issue);
+                mUserConfigAllowed, mSystemClockUpdateThresholdMillis, mAutoSuggestionLowerBound,
+                mManualSuggestionLowerBound, mSuggestionUpperBound);
         result = 31 * result + Arrays.hashCode(mOriginPriorities);
         return result;
     }
@@ -230,10 +242,13 @@
         return "ConfigurationInternal{"
                 + "mAutoDetectionSupported=" + mAutoDetectionSupported
                 + ", mSystemClockUpdateThresholdMillis=" + mSystemClockUpdateThresholdMillis
-                + ", mAutoTimeLowerBound=" + mAutoTimeLowerBound
-                + "(" + mAutoTimeLowerBound.toEpochMilli() + ")"
+                + ", mAutoSuggestionLowerBound=" + mAutoSuggestionLowerBound
+                + "(" + mAutoSuggestionLowerBound.toEpochMilli() + ")"
+                + ", mManualSuggestionLowerBound=" + mManualSuggestionLowerBound
+                + "(" + mManualSuggestionLowerBound.toEpochMilli() + ")"
+                + ", mSuggestionUpperBound=" + mSuggestionUpperBound
+                + "(" + mSuggestionUpperBound.toEpochMilli() + ")"
                 + ", mOriginPriorities=" + originPrioritiesString
-                + ", mDeviceHasY2038Issue=" + mDeviceHasY2038Issue
                 + ", mAutoDetectionEnabled=" + mAutoDetectionEnabledSetting
                 + ", mUserId=" + mUserId
                 + ", mUserConfigAllowed=" + mUserConfigAllowed
@@ -243,9 +258,10 @@
     static final class Builder {
         private boolean mAutoDetectionSupported;
         private int mSystemClockUpdateThresholdMillis;
-        @NonNull private Instant mAutoTimeLowerBound;
+        @NonNull private Instant mAutoSuggestionLowerBound;
+        @NonNull private Instant mManualSuggestionLowerBound;
+        @NonNull private Instant mSuggestionUpperBound;
         @NonNull private @Origin int[] mOriginPriorities;
-        private boolean mDeviceHasY2038Issue;
         private boolean mAutoDetectionEnabledSetting;
 
         private final @UserIdInt int mUserId;
@@ -263,9 +279,10 @@
             this.mUserConfigAllowed = toCopy.mUserConfigAllowed;
             this.mAutoDetectionSupported = toCopy.mAutoDetectionSupported;
             this.mSystemClockUpdateThresholdMillis = toCopy.mSystemClockUpdateThresholdMillis;
-            this.mAutoTimeLowerBound = toCopy.mAutoTimeLowerBound;
+            this.mAutoSuggestionLowerBound = toCopy.mAutoSuggestionLowerBound;
+            this.mManualSuggestionLowerBound = toCopy.mManualSuggestionLowerBound;
+            this.mSuggestionUpperBound = toCopy.mSuggestionUpperBound;
             this.mOriginPriorities = toCopy.mOriginPriorities;
-            this.mDeviceHasY2038Issue = toCopy.mDeviceHasY2038Issue;
             this.mAutoDetectionEnabledSetting = toCopy.mAutoDetectionEnabledSetting;
         }
 
@@ -296,10 +313,26 @@
         }
 
         /**
-         * Sets the lower bound for valid automatic times.
+         * Sets the lower bound for valid automatic time suggestions.
          */
-        public Builder setAutoTimeLowerBound(@NonNull Instant autoTimeLowerBound) {
-            mAutoTimeLowerBound = Objects.requireNonNull(autoTimeLowerBound);
+        public Builder setAutoSuggestionLowerBound(@NonNull Instant autoSuggestionLowerBound) {
+            mAutoSuggestionLowerBound = Objects.requireNonNull(autoSuggestionLowerBound);
+            return this;
+        }
+
+        /**
+         * Sets the lower bound for valid manual time suggestions.
+         */
+        public Builder setManualSuggestionLowerBound(@NonNull Instant manualSuggestionLowerBound) {
+            mManualSuggestionLowerBound = Objects.requireNonNull(manualSuggestionLowerBound);
+            return this;
+        }
+
+        /**
+         * Sets the upper bound for valid time suggestions (manual and automatic).
+         */
+        public Builder setSuggestionUpperBound(@NonNull Instant suggestionUpperBound) {
+            mSuggestionUpperBound = Objects.requireNonNull(suggestionUpperBound);
             return this;
         }
 
@@ -320,15 +353,6 @@
             return this;
         }
 
-        /**
-         * Returns {@code true} if the device may be at risk of time_t overflow (because bionic
-         * defines time_t as a 32-bit signed integer for 32-bit processes).
-         */
-        Builder setDeviceHasY2038Issue(boolean deviceHasY2038Issue) {
-            mDeviceHasY2038Issue = deviceHasY2038Issue;
-            return this;
-        }
-
         /** Returns a new {@link ConfigurationInternal}. */
         @NonNull
         ConfigurationInternal build() {
diff --git a/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java b/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
index e4f3a80..888304a 100644
--- a/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
+++ b/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
@@ -31,6 +31,7 @@
 import android.app.time.TimeCapabilities;
 import android.app.time.TimeCapabilitiesAndConfig;
 import android.app.time.TimeConfiguration;
+import android.app.timedetector.TimeDetectorHelper;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -38,7 +39,6 @@
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.database.ContentObserver;
-import android.os.Build;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -74,13 +74,6 @@
     private static final @Origin int[]
             DEFAULT_AUTOMATIC_TIME_ORIGIN_PRIORITIES = { ORIGIN_TELEPHONY, ORIGIN_NETWORK };
 
-    /**
-     * Time in the past. If an automatic time suggestion is before this point, it is sure to be
-     * incorrect.
-     */
-    private static final Instant TIME_LOWER_BOUND_DEFAULT = Instant.ofEpochMilli(
-            Long.max(android.os.Environment.getRootDirectory().lastModified(), Build.TIME));
-
     /** Device config keys that affect the {@link TimeDetectorService}. */
     private static final Set<String> SERVER_FLAGS_KEYS_TO_WATCH = Set.of(
             KEY_TIME_DETECTOR_LOWER_BOUND_MILLIS_OVERRIDE,
@@ -237,14 +230,16 @@
     @Override
     @NonNull
     public synchronized ConfigurationInternal getConfigurationInternal(@UserIdInt int userId) {
+        TimeDetectorHelper timeDetectorHelper = TimeDetectorHelper.INSTANCE;
         return new ConfigurationInternal.Builder(userId)
                 .setUserConfigAllowed(isUserConfigAllowed(userId))
                 .setAutoDetectionSupported(isAutoDetectionSupported())
                 .setAutoDetectionEnabledSetting(getAutoDetectionEnabledSetting())
                 .setSystemClockUpdateThresholdMillis(getSystemClockUpdateThresholdMillis())
-                .setAutoTimeLowerBound(getAutoTimeLowerBound())
+                .setAutoSuggestionLowerBound(getAutoSuggestionLowerBound())
+                .setManualSuggestionLowerBound(timeDetectorHelper.getManualSuggestionLowerBound())
+                .setSuggestionUpperBound(timeDetectorHelper.getSuggestionUpperBound())
                 .setOriginPriorities(getOriginPriorities())
-                .setDeviceHasY2038Issue(getDeviceHasY2038Issue())
                 .build();
     }
 
@@ -291,9 +286,9 @@
     }
 
     @NonNull
-    private Instant getAutoTimeLowerBound() {
+    private Instant getAutoSuggestionLowerBound() {
         return mServerFlags.getOptionalInstant(KEY_TIME_DETECTOR_LOWER_BOUND_MILLIS_OVERRIDE)
-                .orElse(TIME_LOWER_BOUND_DEFAULT);
+                .orElse(TimeDetectorHelper.INSTANCE.getAutoSuggestionLowerBoundDefault());
     }
 
     @NonNull
@@ -310,10 +305,6 @@
         return DEFAULT_AUTOMATIC_TIME_ORIGIN_PRIORITIES;
     }
 
-    private boolean getDeviceHasY2038Issue() {
-        return Build.SUPPORTED_32_BIT_ABIS.length > 0;
-    }
-
     /**
      * A base supplier of an array of time origin integers in priority order.
      * It handles memoization of the result to avoid repeated string parsing when nothing has
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
index 017306a..547cf9d 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
@@ -84,9 +84,6 @@
      */
     private static final int KEEP_SUGGESTION_HISTORY_SIZE = 10;
 
-    /** The value in Unix epoch milliseconds of the Y2038 issue. */
-    private static final long Y2038_LIMIT_IN_MILLIS = 1000L * Integer.MAX_VALUE;
-
     /**
      * A log that records the decisions / decision metadata that affected the device's system clock
      * time. This is logged in bug reports to assist with debugging issues with detection.
@@ -248,7 +245,7 @@
 
         final TimestampedValue<Long> newUnixEpochTime = suggestion.getUnixEpochTime();
 
-        if (!validateSuggestionTime(newUnixEpochTime, suggestion)) {
+        if (!validateManualSuggestionTime(newUnixEpochTime, suggestion)) {
             return false;
         }
 
@@ -424,7 +421,7 @@
     }
 
     @GuardedBy("this")
-    private boolean validateSuggestionTime(
+    private boolean validateSuggestionCommon(
             @NonNull TimestampedValue<Long> newUnixEpochTime, @NonNull Object suggestion) {
         if (newUnixEpochTime.getValue() == null) {
             Slog.w(LOG_TAG, "Suggested time value is null. suggestion=" + suggestion);
@@ -441,8 +438,8 @@
             return false;
         }
 
-        if (newUnixEpochTime.getValue() > Y2038_LIMIT_IN_MILLIS
-                && mCurrentConfigurationInternal.getDeviceHasY2038Issue()) {
+        if (newUnixEpochTime.getValue()
+                > mCurrentConfigurationInternal.getSuggestionUpperBound().toEpochMilli()) {
             // This check won't prevent a device's system clock exceeding Integer.MAX_VALUE Unix
             // seconds through the normal passage of time, but it will stop it jumping above 2038
             // because of a "bad" suggestion. b/204193177
@@ -453,20 +450,40 @@
         return true;
     }
 
+    /**
+     * Returns {@code true} if an automatic time suggestion time is valid.
+     * See also {@link #validateManualSuggestionTime(TimestampedValue, Object)}.
+     */
     @GuardedBy("this")
     private boolean validateAutoSuggestionTime(
             @NonNull TimestampedValue<Long> newUnixEpochTime, @NonNull Object suggestion)  {
-        return validateSuggestionTime(newUnixEpochTime, suggestion)
-                && validateSuggestionAgainstLowerBound(newUnixEpochTime, suggestion);
+        Instant lowerBound = mCurrentConfigurationInternal.getAutoSuggestionLowerBound();
+        return validateSuggestionCommon(newUnixEpochTime, suggestion)
+                && validateSuggestionAgainstLowerBound(newUnixEpochTime, suggestion,
+                lowerBound);
+    }
+
+    /**
+     * Returns {@code true} if a manual time suggestion time is valid.
+     * See also {@link #validateAutoSuggestionTime(TimestampedValue, Object)}.
+     */
+    @GuardedBy("this")
+    private boolean validateManualSuggestionTime(
+            @NonNull TimestampedValue<Long> newUnixEpochTime, @NonNull Object suggestion)  {
+        Instant lowerBound = mCurrentConfigurationInternal.getManualSuggestionLowerBound();
+
+        // Suggestion is definitely wrong if it comes before lower time bound.
+        return validateSuggestionCommon(newUnixEpochTime, suggestion)
+                && validateSuggestionAgainstLowerBound(newUnixEpochTime, suggestion, lowerBound);
     }
 
     @GuardedBy("this")
     private boolean validateSuggestionAgainstLowerBound(
-            @NonNull TimestampedValue<Long> newUnixEpochTime, @NonNull Object suggestion) {
-        Instant lowerBound = mCurrentConfigurationInternal.getAutoTimeLowerBound();
+            @NonNull TimestampedValue<Long> newUnixEpochTime, @NonNull Object suggestion,
+            @NonNull Instant lowerBound) {
 
         // Suggestion is definitely wrong if it comes before lower time bound.
-        if (lowerBound.isAfter(Instant.ofEpochMilli(newUnixEpochTime.getValue()))) {
+        if (lowerBound.toEpochMilli() > newUnixEpochTime.getValue()) {
             Slog.w(LOG_TAG, "Suggestion points to time before lower bound, skipping it. "
                     + "suggestion=" + suggestion + ", lower bound=" + lowerBound);
             return false;
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 59dbf22..f5c5a13 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -724,13 +724,15 @@
                 // used here because it may be cleared in setTargetRootTaskIfNeeded.
                 final ActivityOptions originalOptions = mRequest.activityOptions != null
                         ? mRequest.activityOptions.getOriginalOptions() : null;
+                // Only track the launch time of activity that will be resumed.
+                final ActivityRecord launchingRecord = mDoResume ? mLastStartActivityRecord : null;
                 // If the new record is the one that started, a new activity has created.
-                final boolean newActivityCreated = mStartActivity == mLastStartActivityRecord;
+                final boolean newActivityCreated = mStartActivity == launchingRecord;
                 // Notify ActivityMetricsLogger that the activity has launched.
                 // ActivityMetricsLogger will then wait for the windows to be drawn and populate
                 // WaitResult.
                 mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, res,
-                        newActivityCreated, mLastStartActivityRecord, originalOptions);
+                        newActivityCreated, launchingRecord, originalOptions);
                 if (mRequest.waitResult != null) {
                     mRequest.waitResult.result = res;
                     res = waitResultIfNeeded(mRequest.waitResult, mLastStartActivityRecord,
@@ -1214,7 +1216,7 @@
         }
 
         mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
-                request.voiceInteractor, startFlags, true /* doResume */, checkedOptions,
+                request.voiceInteractor, startFlags, checkedOptions,
                 inTask, inTaskFragment, restrictedBgActivity, intentGrants);
 
         if (request.outActivity != null) {
@@ -1640,7 +1642,7 @@
      */
     private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
             IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
-            int startFlags, boolean doResume, ActivityOptions options, Task inTask,
+            int startFlags, ActivityOptions options, Task inTask,
             TaskFragment inTaskFragment, boolean restrictedBgActivity,
             NeededUriGrants intentGrants) {
         int result = START_CANCELED;
@@ -1664,7 +1666,7 @@
             try {
                 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
                 result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
-                        startFlags, doResume, options, inTask, inTaskFragment, restrictedBgActivity,
+                        startFlags, options, inTask, inTaskFragment, restrictedBgActivity,
                         intentGrants);
             } finally {
                 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
@@ -1808,10 +1810,10 @@
     @VisibleForTesting
     int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
             IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
-            int startFlags, boolean doResume, ActivityOptions options, Task inTask,
+            int startFlags, ActivityOptions options, Task inTask,
             TaskFragment inTaskFragment, boolean restrictedBgActivity,
             NeededUriGrants intentGrants) {
-        setInitialState(r, options, inTask, inTaskFragment, doResume, startFlags, sourceRecord,
+        setInitialState(r, options, inTask, inTaskFragment, startFlags, sourceRecord,
                 voiceSession, voiceInteractor, restrictedBgActivity);
 
         computeLaunchingTaskFlags();
@@ -2429,7 +2431,7 @@
     }
 
     private void setInitialState(ActivityRecord r, ActivityOptions options, Task inTask,
-            TaskFragment inTaskFragment, boolean doResume, int startFlags,
+            TaskFragment inTaskFragment, int startFlags,
             ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession,
             IVoiceInteractor voiceInteractor, boolean restrictedBgActivity) {
         reset(false /* clearRequest */);
@@ -2494,10 +2496,11 @@
         // If the caller has asked not to resume at this point, we make note
         // of this in the record so that we can skip it when trying to find
         // the top running activity.
-        mDoResume = doResume;
-        if (!doResume || !r.showToCurrentUser() || mLaunchTaskBehind) {
+        if (!r.showToCurrentUser() || mLaunchTaskBehind) {
             r.delayedResume = true;
             mDoResume = false;
+        } else {
+            mDoResume = true;
         }
 
         if (mOptions != null) {
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 804ccc5..3d40f64 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -18,7 +18,6 @@
     name: "services.net",
     defaults: ["platform_service_defaults"],
     srcs: [
-        ":net-module-utils-srcs",
         ":services.net-sources",
     ],
     static_libs: [
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/ConfigurationInternalTest.java b/services/tests/servicestests/src/com/android/server/timedetector/ConfigurationInternalTest.java
index c3d40da..208f99a 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/ConfigurationInternalTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/ConfigurationInternalTest.java
@@ -45,7 +45,9 @@
 
     private static final int ARBITRARY_USER_ID = 99999;
     private static final int ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS = 1234;
-    private static final Instant ARBITRARY_AUTO_TIME_LOWER_BOUND = Instant.ofEpochMilli(0);
+    private static final Instant ARBITRARY_SUGGESTION_LOWER_BOUND = Instant.ofEpochMilli(0);
+    private static final Instant ARBITRARY_SUGGESTION_UPPER_BOUND =
+            Instant.ofEpochMilli(Long.MAX_VALUE);
     private static final @Origin int[] ARBITRARY_ORIGIN_PRIORITIES = { ORIGIN_NETWORK };
 
     /**
@@ -59,9 +61,10 @@
                 .setUserConfigAllowed(true)
                 .setAutoDetectionSupported(true)
                 .setSystemClockUpdateThresholdMillis(ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
-                .setAutoTimeLowerBound(ARBITRARY_AUTO_TIME_LOWER_BOUND)
+                .setAutoSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+                .setManualSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+                .setSuggestionUpperBound(ARBITRARY_SUGGESTION_UPPER_BOUND)
                 .setOriginPriorities(ARBITRARY_ORIGIN_PRIORITIES)
-                .setDeviceHasY2038Issue(true)
                 .setAutoDetectionEnabledSetting(true)
                 .build();
         {
@@ -110,9 +113,10 @@
                 .setUserConfigAllowed(false)
                 .setAutoDetectionSupported(true)
                 .setSystemClockUpdateThresholdMillis(ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
-                .setAutoTimeLowerBound(ARBITRARY_AUTO_TIME_LOWER_BOUND)
+                .setAutoSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+                .setManualSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+                .setSuggestionUpperBound(ARBITRARY_SUGGESTION_UPPER_BOUND)
                 .setOriginPriorities(ARBITRARY_ORIGIN_PRIORITIES)
-                .setDeviceHasY2038Issue(true)
                 .setAutoDetectionEnabledSetting(true)
                 .build();
         {
@@ -159,9 +163,10 @@
                 .setUserConfigAllowed(true)
                 .setAutoDetectionSupported(false)
                 .setSystemClockUpdateThresholdMillis(ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
-                .setAutoTimeLowerBound(ARBITRARY_AUTO_TIME_LOWER_BOUND)
+                .setAutoSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+                .setManualSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+                .setSuggestionUpperBound(ARBITRARY_SUGGESTION_UPPER_BOUND)
                 .setOriginPriorities(ARBITRARY_ORIGIN_PRIORITIES)
-                .setDeviceHasY2038Issue(true)
                 .setAutoDetectionEnabledSetting(true)
                 .build();
         {
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
index b9c74ba..67c8c4f 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -69,7 +69,9 @@
 
     private static final int ARBITRARY_USER_ID = 9999;
     private static final int ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS = 1234;
-    private static final Instant ARBITRARY_AUTO_TIME_LOWER_BOUND = Instant.ofEpochMilli(0);
+    private static final Instant ARBITRARY_SUGGESTION_LOWER_BOUND = Instant.ofEpochMilli(0);
+    private static final Instant ARBITRARY_SUGGESTION_UPPER_BOUND =
+            Instant.ofEpochMilli(Long.MAX_VALUE);
     private static final int[] ARBITRARY_ORIGIN_PRIORITIES = { ORIGIN_NETWORK };
 
     private Context mMockContext;
@@ -444,9 +446,10 @@
                 .setUserConfigAllowed(true)
                 .setAutoDetectionSupported(true)
                 .setSystemClockUpdateThresholdMillis(ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
-                .setAutoTimeLowerBound(ARBITRARY_AUTO_TIME_LOWER_BOUND)
+                .setAutoSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+                .setManualSuggestionLowerBound(ARBITRARY_SUGGESTION_LOWER_BOUND)
+                .setSuggestionUpperBound(ARBITRARY_SUGGESTION_UPPER_BOUND)
                 .setOriginPriorities(ARBITRARY_ORIGIN_PRIORITIES)
-                .setDeviceHasY2038Issue(true)
                 .setAutoDetectionEnabledSetting(autoDetectionEnabled)
                 .build();
     }
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
index aeb5c65..1aea672 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
@@ -53,7 +53,16 @@
 
     private static final @UserIdInt int ARBITRARY_USER_ID = 9876;
     private static final int ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS = 1234;
-    private static final Instant TIME_LOWER_BOUND = createUnixEpochTime(2009, 1, 1, 12, 0, 0);
+    private static final Instant DEFAULT_SUGGESTION_LOWER_BOUND =
+            createUnixEpochTime(2005, 1, 1, 1, 0, 0);
+    /** A value after {@link #DEFAULT_SUGGESTION_LOWER_BOUND} */
+    private static final Instant TEST_SUGGESTION_LOWER_BOUND =
+            createUnixEpochTime(2006, 1, 1, 1, 0, 0);
+    private static final Instant DEFAULT_SUGGESTION_UPPER_BOUND =
+            createUnixEpochTime(2099, 12, 1, 1, 0, 0);
+    /** A value before {@link #DEFAULT_SUGGESTION_UPPER_BOUND} */
+    private static final Instant TEST_SUGGESTION_UPPER_BOUND =
+            createUnixEpochTime(2037, 12, 1, 1, 0, 0);
 
     private static final TimestampedValue<Instant> ARBITRARY_CLOCK_INITIALIZATION_INFO =
             new TimestampedValue<>(
@@ -77,9 +86,10 @@
                     .setAutoDetectionSupported(true)
                     .setSystemClockUpdateThresholdMillis(
                             ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
-                    .setAutoTimeLowerBound(TIME_LOWER_BOUND)
+                    .setAutoSuggestionLowerBound(DEFAULT_SUGGESTION_LOWER_BOUND)
+                    .setManualSuggestionLowerBound(DEFAULT_SUGGESTION_LOWER_BOUND)
+                    .setSuggestionUpperBound(DEFAULT_SUGGESTION_UPPER_BOUND)
                     .setOriginPriorities(ORIGIN_PRIORITIES)
-                    .setDeviceHasY2038Issue(true)
                     .setAutoDetectionEnabledSetting(false)
                     .build();
 
@@ -89,9 +99,10 @@
                     .setAutoDetectionSupported(true)
                     .setSystemClockUpdateThresholdMillis(
                             ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
-                    .setAutoTimeLowerBound(TIME_LOWER_BOUND)
+                    .setAutoSuggestionLowerBound(DEFAULT_SUGGESTION_LOWER_BOUND)
+                    .setManualSuggestionLowerBound(DEFAULT_SUGGESTION_LOWER_BOUND)
+                    .setSuggestionUpperBound(DEFAULT_SUGGESTION_UPPER_BOUND)
                     .setOriginPriorities(ORIGIN_PRIORITIES)
-                    .setDeviceHasY2038Issue(true)
                     .setAutoDetectionEnabledSetting(true)
                     .build();
 
@@ -344,22 +355,6 @@
     }
 
     @Test
-    public void telephonyTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() {
-        Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
-
-        int slotIndex = ARBITRARY_SLOT_INDEX;
-        Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
-
-        TelephonyTimeSuggestion timeSuggestion =
-                script.generateTelephonyTimeSuggestion(
-                        slotIndex, suggestedTime);
-
-        script.simulateTelephonyTimeSuggestion(timeSuggestion)
-                .verifySystemClockWasNotSetAndResetCallTracking()
-                .assertLatestTelephonySuggestion(slotIndex, null);
-    }
-
-    @Test
     public void testSuggestTelephonyTime_timeDetectionToggled() {
         final int clockIncrementMillis = 100;
         final int systemClockUpdateThresholdMillis = 2000;
@@ -453,6 +448,70 @@
     }
 
     @Test
+    public void testSuggestTelephonyTime_rejectedBelowLowerBound() {
+        ConfigurationInternal configInternal =
+                new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
+                        .setOriginPriorities(ORIGIN_TELEPHONY)
+                        .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+                        .build();
+        Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+        Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
+        TelephonyTimeSuggestion timeSuggestion =
+                script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, belowLowerBound);
+        script.simulateTelephonyTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasNotSetAndResetCallTracking();
+    }
+
+    @Test
+    public void testSuggestTelephonyTime_notRejectedAboveLowerBound() {
+        ConfigurationInternal configInternal =
+                new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+                        .setOriginPriorities(ORIGIN_TELEPHONY)
+                        .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+                        .build();
+        Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+        Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
+        TelephonyTimeSuggestion timeSuggestion =
+                script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, aboveLowerBound);
+        script.simulateTelephonyTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
+    }
+
+    @Test
+    public void testSuggestTelephonyTime_rejectedAboveUpperBound() {
+        ConfigurationInternal configInternal =
+                new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+                        .setOriginPriorities(ORIGIN_TELEPHONY)
+                        .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+                        .build();
+        Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+        Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
+        TelephonyTimeSuggestion timeSuggestion =
+                script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, aboveUpperBound);
+        script.simulateTelephonyTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasNotSetAndResetCallTracking();
+    }
+
+    @Test
+    public void testSuggestTelephonyTime_notRejectedBelowUpperBound() {
+        ConfigurationInternal configInternal =
+                new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+                        .setOriginPriorities(ORIGIN_TELEPHONY)
+                        .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+                        .build();
+        Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+        Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
+        TelephonyTimeSuggestion timeSuggestion =
+                script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, belowUpperBound);
+        script.simulateTelephonyTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
+    }
+
+    @Test
     public void testSuggestManualTime_autoTimeDisabled() {
         Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED);
 
@@ -530,7 +589,7 @@
     }
 
     @Test
-    public void manualTimeSuggestion_isIgnored_whenAutoTimeEnabled() {
+    public void testSuggestManualTime_isIgnored_whenAutoTimeEnabled() {
         Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
 
         ManualTimeSuggestion timeSuggestion =
@@ -543,16 +602,63 @@
     }
 
     @Test
-    public void manualTimeSuggestion_ignoresTimeLowerBound() {
-        Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED);
-        Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
+    public void testSuggestManualTime_rejectedAboveUpperBound() {
+        ConfigurationInternal configInternal =
+                new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
+                        .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+                        .build();
+        Script script = new Script().simulateConfigurationInternalChange(configInternal);
 
-        ManualTimeSuggestion timeSuggestion =
-                script.generateManualTimeSuggestion(suggestedTime);
-
+        Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
+        ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(aboveUpperBound);
         script.simulateManualTimeSuggestion(
-                ARBITRARY_USER_ID, timeSuggestion, true /* expectedResult */)
-                .verifySystemClockWasSetAndResetCallTracking(suggestedTime.toEpochMilli());
+                        ARBITRARY_USER_ID, timeSuggestion, false /* expectedResult */)
+                .verifySystemClockWasNotSetAndResetCallTracking();
+    }
+
+    @Test
+    public void testSuggestManualTime_notRejectedBelowUpperBound() {
+        ConfigurationInternal configInternal =
+                new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
+                        .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+                        .build();
+        Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+        Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
+        ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(belowUpperBound);
+        script.simulateManualTimeSuggestion(
+                        ARBITRARY_USER_ID, timeSuggestion, true /* expectedResult */)
+                .verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
+    }
+
+    @Test
+    public void testSuggestManualTime_rejectedBelowLowerBound() {
+        ConfigurationInternal configInternal =
+                new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
+                        .setManualSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+                        .build();
+        Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+        Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
+        ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(belowLowerBound);
+        script.simulateManualTimeSuggestion(
+                        ARBITRARY_USER_ID, timeSuggestion, false /* expectedResult */)
+                .verifySystemClockWasNotSetAndResetCallTracking();
+    }
+
+    @Test
+    public void testSuggestManualTimes_notRejectedAboveLowerBound() {
+        ConfigurationInternal configInternal =
+                new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
+                        .setManualSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+                        .build();
+        Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+        Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
+        ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(aboveLowerBound);
+        script.simulateManualTimeSuggestion(
+                        ARBITRARY_USER_ID, timeSuggestion, true /* expectedResult */)
+                .verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
     }
 
     @Test
@@ -591,20 +697,67 @@
     }
 
     @Test
-    public void networkTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() {
+    public void testSuggestNetworkTime_rejectedBelowLowerBound() {
         ConfigurationInternal configInternal =
                 new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
                         .setOriginPriorities(ORIGIN_NETWORK)
+                        .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
                         .build();
         Script script = new Script().simulateConfigurationInternalChange(configInternal);
 
-        Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
+        Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
         NetworkTimeSuggestion timeSuggestion =
-                script.generateNetworkTimeSuggestion(suggestedTime);
-
+                script.generateNetworkTimeSuggestion(belowLowerBound);
         script.simulateNetworkTimeSuggestion(timeSuggestion)
-                .verifySystemClockWasNotSetAndResetCallTracking()
-                .assertLatestNetworkSuggestion(null);
+                .verifySystemClockWasNotSetAndResetCallTracking();
+    }
+
+    @Test
+    public void testSuggestNetworkTime_notRejectedAboveLowerBound() {
+        ConfigurationInternal configInternal =
+                new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+                        .setOriginPriorities(ORIGIN_NETWORK)
+                        .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+                        .build();
+        Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+        Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
+        NetworkTimeSuggestion timeSuggestion =
+                script.generateNetworkTimeSuggestion(aboveLowerBound);
+        script.simulateNetworkTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
+    }
+
+    @Test
+    public void testSuggestNetworkTime_rejectedAboveUpperBound() {
+        ConfigurationInternal configInternal =
+                new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+                        .setOriginPriorities(ORIGIN_NETWORK)
+                        .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+                        .build();
+        Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+        Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
+        NetworkTimeSuggestion timeSuggestion =
+                script.generateNetworkTimeSuggestion(aboveUpperBound);
+        script.simulateNetworkTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasNotSetAndResetCallTracking();
+    }
+
+    @Test
+    public void testSuggestNetworkTime_notRejectedBelowUpperBound() {
+        ConfigurationInternal configInternal =
+                new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+                        .setOriginPriorities(ORIGIN_NETWORK)
+                        .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+                        .build();
+        Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+        Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
+        NetworkTimeSuggestion timeSuggestion =
+                script.generateNetworkTimeSuggestion(belowUpperBound);
+        script.simulateNetworkTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
     }
 
     @Test
@@ -643,6 +796,70 @@
     }
 
     @Test
+    public void testSuggestGnssTime_rejectedBelowLowerBound() {
+        ConfigurationInternal configInternal =
+                new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+                        .setOriginPriorities(ORIGIN_GNSS)
+                        .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+                        .build();
+        Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+        Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
+        GnssTimeSuggestion timeSuggestion =
+                script.generateGnssTimeSuggestion(belowLowerBound);
+        script.simulateGnssTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasNotSetAndResetCallTracking();
+    }
+
+    @Test
+    public void testSuggestGnssTime_notRejectedAboveLowerBound() {
+        ConfigurationInternal configInternal =
+                new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+                        .setOriginPriorities(ORIGIN_GNSS)
+                        .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+                        .build();
+        Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+        Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
+        GnssTimeSuggestion timeSuggestion =
+                script.generateGnssTimeSuggestion(aboveLowerBound);
+        script.simulateGnssTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
+    }
+
+    @Test
+    public void testSuggestGnssTime_rejectedAboveUpperBound() {
+        ConfigurationInternal configInternal =
+                new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+                        .setOriginPriorities(ORIGIN_GNSS)
+                        .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+                        .build();
+        Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+        Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
+        GnssTimeSuggestion timeSuggestion =
+                script.generateGnssTimeSuggestion(aboveUpperBound);
+        script.simulateGnssTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasNotSetAndResetCallTracking();
+    }
+
+    @Test
+    public void testSuggestGnssTime_notRejectedBelowUpperBound() {
+        ConfigurationInternal configInternal =
+                new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+                        .setOriginPriorities(ORIGIN_GNSS)
+                        .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+                        .build();
+        Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+        Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
+        GnssTimeSuggestion timeSuggestion =
+                script.generateGnssTimeSuggestion(belowUpperBound);
+        script.simulateGnssTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
+    }
+
+    @Test
     public void testSuggestExternalTime_autoTimeEnabled() {
         ConfigurationInternal configInternal =
                 new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
@@ -678,20 +895,67 @@
     }
 
     @Test
-    public void externalTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() {
+    public void testSuggestExternalTime_rejectedBelowLowerBound() {
         ConfigurationInternal configInternal =
                 new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
                         .setOriginPriorities(ORIGIN_EXTERNAL)
+                        .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
                         .build();
         Script script = new Script().simulateConfigurationInternalChange(configInternal);
 
-        Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
+        Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
         ExternalTimeSuggestion timeSuggestion =
-                script.generateExternalTimeSuggestion(suggestedTime);
-
+                script.generateExternalTimeSuggestion(belowLowerBound);
         script.simulateExternalTimeSuggestion(timeSuggestion)
-                .verifySystemClockWasNotSetAndResetCallTracking()
-                .assertLatestExternalSuggestion(null);
+                .verifySystemClockWasNotSetAndResetCallTracking();
+    }
+
+    @Test
+    public void testSuggestExternalTime_notRejectedAboveLowerBound() {
+        ConfigurationInternal configInternal =
+                new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+                        .setOriginPriorities(ORIGIN_EXTERNAL)
+                        .setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
+                        .build();
+        Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+        Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
+        ExternalTimeSuggestion timeSuggestion =
+                script.generateExternalTimeSuggestion(aboveLowerBound);
+        script.simulateExternalTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
+    }
+
+    @Test
+    public void testSuggestExternalTime_rejectedAboveUpperBound() {
+        ConfigurationInternal configInternal =
+                new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+                        .setOriginPriorities(ORIGIN_EXTERNAL)
+                        .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+                        .build();
+        Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+        Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
+        ExternalTimeSuggestion timeSuggestion =
+                script.generateExternalTimeSuggestion(aboveUpperBound);
+        script.simulateExternalTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasNotSetAndResetCallTracking();
+    }
+
+    @Test
+    public void testSuggestExternalTime_notRejectedBelowUpperBound() {
+        ConfigurationInternal configInternal =
+                new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
+                        .setOriginPriorities(ORIGIN_EXTERNAL)
+                        .setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
+                        .build();
+        Script script = new Script().simulateConfigurationInternalChange(configInternal);
+
+        Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
+        ExternalTimeSuggestion timeSuggestion =
+                script.generateExternalTimeSuggestion(belowUpperBound);
+        script.simulateExternalTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
     }
 
     @Test
@@ -1198,56 +1462,6 @@
                 .verifySystemClockWasSetAndResetCallTracking(ARBITRARY_TEST_TIME.toEpochMilli());
     }
 
-    @Test
-    public void manualY2038SuggestionsAreRejectedOnAffectedDevices() {
-        ConfigurationInternal configInternal =
-                new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
-                        .setOriginPriorities(ORIGIN_TELEPHONY)
-                        .setDeviceHasY2038Issue(true)
-                        .build();
-        Script script = new Script().simulateConfigurationInternalChange(configInternal);
-
-        Instant y2038IssueTime = Instant.ofEpochMilli((1L + Integer.MAX_VALUE) * 1000L);
-        ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(y2038IssueTime);
-        script.simulateManualTimeSuggestion(
-                ARBITRARY_USER_ID, timeSuggestion, false /* expectedResult */)
-                .verifySystemClockWasNotSetAndResetCallTracking();
-    }
-
-    @Test
-    public void telephonyY2038SuggestionsAreRejectedOnAffectedDevices() {
-        ConfigurationInternal configInternal =
-                new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
-                        .setOriginPriorities(ORIGIN_TELEPHONY)
-                        .setDeviceHasY2038Issue(true)
-                        .build();
-        Script script = new Script().simulateConfigurationInternalChange(configInternal);
-
-        final int slotIndex = 0;
-        Instant y2038IssueTime = Instant.ofEpochMilli((1L + Integer.MAX_VALUE) * 1000L);
-        TelephonyTimeSuggestion timeSuggestion =
-                script.generateTelephonyTimeSuggestion(slotIndex, y2038IssueTime);
-        script.simulateTelephonyTimeSuggestion(timeSuggestion)
-                .verifySystemClockWasNotSetAndResetCallTracking();
-    }
-
-    @Test
-    public void telephonyY2038SuggestionsAreNotRejectedOnUnaffectedDevices() {
-        ConfigurationInternal configInternal =
-                new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
-                        .setOriginPriorities(ORIGIN_TELEPHONY)
-                        .setDeviceHasY2038Issue(false)
-                        .build();
-        Script script = new Script().simulateConfigurationInternalChange(configInternal);
-
-        final int slotIndex = 0;
-        Instant y2038IssueTime = Instant.ofEpochMilli((1L + Integer.MAX_VALUE) * 1000L);
-        TelephonyTimeSuggestion timeSuggestion =
-                script.generateTelephonyTimeSuggestion(slotIndex, y2038IssueTime);
-        script.simulateTelephonyTimeSuggestion(timeSuggestion)
-                .verifySystemClockWasSetAndResetCallTracking(y2038IssueTime.toEpochMilli());
-    }
-
     /**
      * A fake implementation of {@link TimeDetectorStrategyImpl.Environment}. Besides tracking
      * changes and behaving like the real thing should, it also asserts preconditions.
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index fe3c26a..cd087e6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -1406,7 +1406,7 @@
             ActivityRecord source, ActivityOptions options, Task inTask,
             TaskFragment inTaskFragment) {
         starter.startActivityInner(target, source, null /* voiceSession */,
-                null /* voiceInteractor */, 0 /* startFlags */, true /* doResume */,
+                null /* voiceInteractor */, 0 /* startFlags */,
                 options, inTask, inTaskFragment, false /* restrictedBgActivity */,
                 null /* intentGrants */);
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java
index 47c2176..21197ba 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java
@@ -184,7 +184,6 @@
                 /* voiceSession */null,
                 /* voiceInteractor */ null,
                 /* startFlags */ 0,
-                /* doResume */true,
                 /* options */null,
                 /* inTask */null,
                 /* inTaskFragment */ null,
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt
index 0f809ee..470fa58 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt
@@ -193,18 +193,22 @@
     }
 
     /** {@inheritDoc} */
+    @Test
     @Ignore("Visibility changes depending on orientation and navigation mode")
     override fun navBarLayerIsVisibleAtStartAndEnd() { }
 
     /** {@inheritDoc} */
+    @Test
     @Ignore("Visibility changes depending on orientation and navigation mode")
     override fun navBarLayerPositionAtStartAndEnd() { }
 
     /** {@inheritDoc} */
+    @Test
     @Ignore("Visibility changes depending on orientation and navigation mode")
     override fun statusBarLayerPositionAtStartAndEnd() { }
 
     /** {@inheritDoc} */
+    @Test
     @Ignore("Visibility changes depending on orientation and navigation mode")
     override fun statusBarLayerIsVisibleAtStartAndEnd() { }
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
index 242a884..220e4ca 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
@@ -91,6 +91,7 @@
     override fun appWindowBecomesTopWindow() = super.appWindowBecomesTopWindow()
 
     /** {@inheritDoc} */
+    @Test
     @Ignore("Display is off at the start")
     override fun navBarLayerPositionAtStartAndEnd() { }
 
@@ -105,6 +106,7 @@
     }
 
     /** {@inheritDoc} */
+    @Test
     @Ignore("Display is off at the start")
     override fun statusBarLayerPositionAtStartAndEnd() { }
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
index 3619505..9ed1bde 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
@@ -117,6 +117,7 @@
         super.visibleWindowsShownMoreThanOneConsecutiveEntry()
 
     /** {@inheritDoc} */
+    @Test
     @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
     override fun navBarLayerPositionAtStartAndEnd() { }
 
@@ -131,6 +132,7 @@
     }
 
     /** {@inheritDoc} */
+    @Test
     @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
     override fun statusBarLayerPositionAtStartAndEnd() { }
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
index 5a4b369..1d8b0a6 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
@@ -102,18 +102,22 @@
     override fun appWindowBecomesVisible() = super.appWindowBecomesVisible()
 
     /** {@inheritDoc} */
+    @Test
     @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
     override fun navBarLayerPositionAtStartAndEnd() { }
 
     /** {@inheritDoc} */
+    @Test
     @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
     override fun statusBarLayerPositionAtStartAndEnd() { }
 
     /** {@inheritDoc} */
+    @Test
     @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
     override fun taskBarLayerIsVisibleAtStartAndEnd() { }
 
     /** {@inheritDoc} */
+    @Test
     @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
     override fun taskBarWindowIsAlwaysVisible() { }
 
@@ -135,6 +139,7 @@
     fun statusBarLayerPositionAtEnd() = testSpec.statusBarLayerPositionAtEnd()
 
     /** {@inheritDoc} */
+    @Test
     @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
     override fun statusBarLayerIsVisibleAtStartAndEnd() { }
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
index c03cb56..1ad5426 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
@@ -132,22 +132,27 @@
     }
 
     /** {@inheritDoc} */
+    @Test
     @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
     override fun taskBarLayerIsVisibleAtStartAndEnd() { }
 
     /** {@inheritDoc} */
+    @Test
     @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
     override fun navBarLayerIsVisibleAtStartAndEnd() { }
 
     /** {@inheritDoc} */
+    @Test
     @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
     override fun taskBarWindowIsAlwaysVisible() { }
 
     /** {@inheritDoc} */
+    @Test
     @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
     override fun navBarWindowIsAlwaysVisible() { }
 
     /** {@inheritDoc} */
+    @Test
     @Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
     override fun statusBarWindowIsAlwaysVisible() { }
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
index b2a2381..1e3caa4 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
@@ -164,14 +164,17 @@
     }
 
     /** {@inheritDoc} */
+    @Test
     @Ignore("Not applicable to this CUJ. App is full screen")
     override fun statusBarLayerPositionAtStartAndEnd() { }
 
     /** {@inheritDoc} */
+    @Test
     @Ignore("Not applicable to this CUJ. App is full screen")
     override fun statusBarLayerIsVisibleAtStartAndEnd() { }
 
     /** {@inheritDoc} */
+    @Test
     @Ignore("Not applicable to this CUJ. App is full screen")
     override fun statusBarWindowIsAlwaysVisible() { }