Merge "Support ignoring orientation request on DisplayArea level"
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 7c44f16..8ac9842 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -122,7 +122,6 @@
 droidstubs {
     name: "api-stubs-docs",
     defaults: ["metalava-full-api-stubs-default"],
-    removed_dex_api_filename: "removed-dex.txt",
     arg_files: [
         "core/res/AndroidManifest.xml",
     ],
@@ -183,7 +182,6 @@
 droidstubs {
     name: "system-api-stubs-docs",
     defaults: ["metalava-full-api-stubs-default"],
-    removed_dex_api_filename: "system-removed-dex.txt",
     arg_files: [
         "core/res/AndroidManifest.xml",
     ],
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java b/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java
index f672e4b..45ea233 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java
@@ -16,10 +16,13 @@
 
 package com.android.server.alarm;
 
+import static android.app.AlarmManager.ELAPSED_REALTIME;
 import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
 import static android.app.AlarmManager.RTC;
 import static android.app.AlarmManager.RTC_WAKEUP;
 
+import static com.android.server.alarm.AlarmManagerService.clampPositive;
+
 import android.app.AlarmManager;
 import android.app.IAlarmListener;
 import android.app.PendingIntent;
@@ -32,8 +35,28 @@
 import java.text.SimpleDateFormat;
 import java.util.Date;
 
+/**
+ * Class to describe an alarm that is used to the set the kernel timer that returns when the timer
+ * expires. The timer will wake up the device if the alarm is a "wakeup" alarm.
+ */
 class Alarm {
+    private static final int NUM_POLICIES = 2;
+    /**
+     * Index used to store the time the alarm was requested to expire. To be used with
+     * {@link #setPolicyElapsed(int, long)}
+     */
+    public static final int REQUESTER_POLICY_INDEX = 0;
+    /**
+     * Index used to store the earliest time the alarm can expire based on app-standby policy.
+     * To be used with {@link #setPolicyElapsed(int, long)}
+     */
+    public static final int APP_STANDBY_POLICY_INDEX = 1;
+
     public final int type;
+    /**
+     * The original trigger time supplied by the caller. This can be in the elapsed or rtc time base
+     * depending on the type of this alarm
+     */
     public final long origWhen;
     public final boolean wakeup;
     public final PendingIntent operation;
@@ -47,42 +70,40 @@
     public final int creatorUid;
     public final String packageName;
     public final String sourcePackage;
+    public final long windowLength;
+    public final long repeatInterval;
     public int count;
-    public long when;
-    public long windowLength;
-    public long whenElapsed;    // 'when' in the elapsed time base
-    public long maxWhenElapsed; // also in the elapsed time base
-    // Expected alarm expiry time before app standby deferring is applied.
-    public long expectedWhenElapsed;
-    public long expectedMaxWhenElapsed;
-    public long repeatInterval;
+    /** The earliest time this alarm is eligible to fire according to each policy */
+    private long[] mPolicyWhenElapsed;
+    /** The ultimate delivery time to be used for this alarm */
+    private long mWhenElapsed;
+    private long mMaxWhenElapsed;
     public AlarmManagerService.PriorityClass priorityClass;
 
-    Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
-            long _interval, PendingIntent _op, IAlarmListener _rec, String _listenerTag,
-            WorkSource _ws, int _flags, AlarmManager.AlarmClockInfo _info,
-            int _uid, String _pkgName) {
-        type = _type;
-        origWhen = _when;
-        wakeup = _type == AlarmManager.ELAPSED_REALTIME_WAKEUP
-                || _type == AlarmManager.RTC_WAKEUP;
-        when = _when;
-        whenElapsed = _whenElapsed;
-        expectedWhenElapsed = _whenElapsed;
-        windowLength = _windowLength;
-        maxWhenElapsed = expectedMaxWhenElapsed = AlarmManagerService.clampPositive(_maxWhen);
-        repeatInterval = _interval;
-        operation = _op;
-        listener = _rec;
-        listenerTag = _listenerTag;
-        statsTag = makeTag(_op, _listenerTag, _type);
-        workSource = _ws;
-        flags = _flags;
-        alarmClock = _info;
-        uid = _uid;
-        packageName = _pkgName;
+    Alarm(int type, long when, long requestedWhenElapsed, long windowLength, long interval,
+            PendingIntent op, IAlarmListener rec, String listenerTag, WorkSource ws, int flags,
+            AlarmManager.AlarmClockInfo info, int uid, String pkgName) {
+        this.type = type;
+        origWhen = when;
+        wakeup = type == AlarmManager.ELAPSED_REALTIME_WAKEUP
+                || type == AlarmManager.RTC_WAKEUP;
+        mPolicyWhenElapsed = new long[NUM_POLICIES];
+        mPolicyWhenElapsed[REQUESTER_POLICY_INDEX] = requestedWhenElapsed;
+        mWhenElapsed = requestedWhenElapsed;
+        this.windowLength = windowLength;
+        mMaxWhenElapsed = clampPositive(requestedWhenElapsed + windowLength);
+        repeatInterval = interval;
+        operation = op;
+        listener = rec;
+        this.listenerTag = listenerTag;
+        statsTag = makeTag(op, listenerTag, type);
+        workSource = ws;
+        this.flags = flags;
+        alarmClock = info;
+        this.uid = uid;
+        packageName = pkgName;
         sourcePackage = (operation != null) ? operation.getCreatorPackage() : packageName;
-        creatorUid = (operation != null) ? operation.getCreatorUid() : uid;
+        creatorUid = (operation != null) ? operation.getCreatorUid() : this.uid;
     }
 
     public static String makeTag(PendingIntent pi, String tag, int type) {
@@ -91,13 +112,6 @@
         return (pi != null) ? pi.getTag(alarmString) : (alarmString + tag);
     }
 
-    public AlarmManagerService.WakeupEvent makeWakeupEvent(long nowRTC) {
-        return new AlarmManagerService.WakeupEvent(nowRTC, creatorUid,
-                (operation != null)
-                    ? operation.getIntent().getAction()
-                    : ("<listener>:" + listenerTag));
-    }
-
     // Returns true if either matches
     public boolean matches(PendingIntent pi, IAlarmListener rec) {
         return (operation != null)
@@ -109,6 +123,65 @@
         return packageName.equals(sourcePackage);
     }
 
+    /**
+     * Get the earliest time this alarm is allowed to expire based on the given policy.
+     *
+     * @param policyIndex The index of the policy. One of [{@link #REQUESTER_POLICY_INDEX},
+     *                    {@link #APP_STANDBY_POLICY_INDEX}].
+     */
+    public long getPolicyElapsed(int policyIndex) {
+        return mPolicyWhenElapsed[policyIndex];
+    }
+
+    /**
+     * Get the earliest time that this alarm should be delivered to the requesting app.
+     */
+    public long getWhenElapsed() {
+        return mWhenElapsed;
+    }
+
+    /**
+     * Get the latest time that this alarm should be delivered to the requesting app. Will be equal
+     * to {@link #getWhenElapsed()} in case this is an exact alarm.
+     */
+    public long getMaxWhenElapsed() {
+        return mMaxWhenElapsed;
+    }
+
+    /**
+     * Set the earliest time this alarm can expire based on the passed policy index.
+     *
+     * @return {@code true} if this change resulted in a change in the ultimate delivery time (or
+     * time window in the case of inexact alarms) of this alarm.
+     * @see #getWhenElapsed()
+     * @see #getMaxWhenElapsed()
+     * @see #getPolicyElapsed(int)
+     */
+    public boolean setPolicyElapsed(int policyIndex, long policyElapsed) {
+        mPolicyWhenElapsed[policyIndex] = policyElapsed;
+        return updateWhenElapsed();
+    }
+
+    /**
+     * @return {@code true} if either {@link #mWhenElapsed} or {@link #mMaxWhenElapsed} changes
+     * due to this call.
+     */
+    private boolean updateWhenElapsed() {
+        final long oldWhenElapsed = mWhenElapsed;
+        mWhenElapsed = 0;
+        for (int i = 0; i < NUM_POLICIES; i++) {
+            mWhenElapsed = Math.max(mWhenElapsed, mPolicyWhenElapsed[i]);
+        }
+
+        final long oldMaxWhenElapsed = mMaxWhenElapsed;
+        // windowLength should always be >= 0 here.
+        final long maxRequestedElapsed = clampPositive(
+                mPolicyWhenElapsed[REQUESTER_POLICY_INDEX] + windowLength);
+        mMaxWhenElapsed = Math.max(maxRequestedElapsed, mWhenElapsed);
+
+        return (oldWhenElapsed != mWhenElapsed) || (oldMaxWhenElapsed != mMaxWhenElapsed);
+    }
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder(128);
@@ -116,11 +189,11 @@
         sb.append(Integer.toHexString(System.identityHashCode(this)));
         sb.append(" type ");
         sb.append(type);
-        sb.append(" when ");
-        sb.append(when);
+        sb.append(" origWhen ");
+        sb.append(origWhen);
         sb.append(" ");
         sb.append(" whenElapsed ");
-        sb.append(whenElapsed);
+        sb.append(getWhenElapsed());
         sb.append(" ");
         sb.append(sourcePackage);
         sb.append('}');
@@ -136,30 +209,46 @@
         dump(ipw, nowELAPSED, sdf);
     }
 
+    private static String policyIndexToString(int index) {
+        switch (index) {
+            case REQUESTER_POLICY_INDEX:
+                return "requester";
+            case APP_STANDBY_POLICY_INDEX:
+                return "app_standby";
+            default:
+                return "unknown";
+        }
+    }
+
+    public static String typeToString(int type) {
+        switch (type) {
+            case RTC:
+                return "RTC";
+            case RTC_WAKEUP:
+                return "RTC_WAKEUP";
+            case ELAPSED_REALTIME:
+                return "ELAPSED";
+            case ELAPSED_REALTIME_WAKEUP:
+                return "ELAPSED_WAKEUP";
+            default:
+                return "--unknown--";
+        }
+    }
+
     public void dump(IndentingPrintWriter ipw, long nowELAPSED, SimpleDateFormat sdf) {
         final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
         ipw.print("tag=");
         ipw.println(statsTag);
 
         ipw.print("type=");
-        ipw.print(type);
-        ipw.print(" expectedWhenElapsed=");
-        TimeUtils.formatDuration(expectedWhenElapsed, nowELAPSED, ipw);
-        ipw.print(" expectedMaxWhenElapsed=");
-        TimeUtils.formatDuration(expectedMaxWhenElapsed, nowELAPSED, ipw);
-        ipw.print(" whenElapsed=");
-        TimeUtils.formatDuration(whenElapsed, nowELAPSED, ipw);
-        ipw.print(" maxWhenElapsed=");
-        TimeUtils.formatDuration(maxWhenElapsed, nowELAPSED, ipw);
-        ipw.print(" when=");
+        ipw.print(typeToString(type));
+        ipw.print(" origWhen=");
         if (isRtc) {
-            ipw.print(sdf.format(new Date(when)));
+            ipw.print(sdf.format(new Date(origWhen)));
         } else {
-            TimeUtils.formatDuration(when, nowELAPSED, ipw);
+            TimeUtils.formatDuration(origWhen, nowELAPSED, ipw);
         }
-        ipw.println();
-
-        ipw.print("window=");
+        ipw.print(" window=");
         TimeUtils.formatDuration(windowLength, ipw);
         ipw.print(" repeatInterval=");
         ipw.print(repeatInterval);
@@ -168,6 +257,19 @@
         ipw.print(" flags=0x");
         ipw.println(Integer.toHexString(flags));
 
+        ipw.print("policyWhenElapsed:");
+        for (int i = 0; i < NUM_POLICIES; i++) {
+            ipw.print(" " + policyIndexToString(i) + "=");
+            TimeUtils.formatDuration(mPolicyWhenElapsed[i], nowELAPSED, ipw);
+        }
+        ipw.println();
+
+        ipw.print("whenElapsed=");
+        TimeUtils.formatDuration(getWhenElapsed(), nowELAPSED, ipw);
+        ipw.print(" maxWhenElapsed=");
+        TimeUtils.formatDuration(mMaxWhenElapsed, nowELAPSED, ipw);
+        ipw.println();
+
         if (alarmClock != null) {
             ipw.println("Alarm clock:");
 
@@ -177,9 +279,10 @@
             ipw.print("  showIntent=");
             ipw.println(alarmClock.getShowIntent());
         }
-        ipw.print("operation=");
-        ipw.println(operation);
-
+        if (operation != null) {
+            ipw.print("operation=");
+            ipw.println(operation);
+        }
         if (listener != null) {
             ipw.print("listener=");
             ipw.println(listener.asBinder());
@@ -191,7 +294,7 @@
 
         proto.write(AlarmProto.TAG, statsTag);
         proto.write(AlarmProto.TYPE, type);
-        proto.write(AlarmProto.TIME_UNTIL_WHEN_ELAPSED_MS, whenElapsed - nowElapsed);
+        proto.write(AlarmProto.TIME_UNTIL_WHEN_ELAPSED_MS, getWhenElapsed() - nowElapsed);
         proto.write(AlarmProto.WINDOW_LENGTH_MS, windowLength);
         proto.write(AlarmProto.REPEAT_INTERVAL_MS, repeatInterval);
         proto.write(AlarmProto.COUNT, count);
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index 05910a5..82819da 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -26,6 +26,9 @@
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 import static android.os.UserHandle.USER_SYSTEM;
 
+import static com.android.server.alarm.Alarm.APP_STANDBY_POLICY_INDEX;
+import static com.android.server.alarm.Alarm.REQUESTER_POLICY_INDEX;
+
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
 import android.app.Activity;
@@ -727,9 +730,9 @@
             }
 
             // within each class, sort by nominal delivery time
-            if (lhs.whenElapsed < rhs.whenElapsed) {
+            if (lhs.getWhenElapsed() < rhs.getWhenElapsed()) {
                 return -1;
-            } else if (lhs.whenElapsed > rhs.whenElapsed) {
+            } else if (lhs.getWhenElapsed() > rhs.getWhenElapsed()) {
                 return 1;
             }
 
@@ -798,9 +801,12 @@
         this(context, new Injector(context));
     }
 
+    private static boolean isRtc(int type) {
+        return (type == RTC || type == RTC_WAKEUP);
+    }
+
     private long convertToElapsed(long when, int type) {
-        final boolean isRtc = (type == RTC || type == RTC_WAKEUP);
-        if (isRtc) {
+        if (isRtc(type)) {
             when -= mInjector.getCurrentTimeMillis() - mInjector.getElapsedRealtime();
         }
         return when;
@@ -823,13 +829,29 @@
     }
 
     // The RTC clock has moved arbitrarily, so we need to recalculate all the RTC alarm deliveries.
-    void reevaluateRtcAlarms(final long nowElapsed) {
+    void reevaluateRtcAlarms() {
         synchronized (mLock) {
-            final ArrayList<Alarm> rtcAlarms = mAlarmStore.remove(a -> (a.type == RTC
-                    || a.type == RTC_WAKEUP));
-            for (final Alarm a : rtcAlarms) {
-                restoreAlarmLocked(a, nowElapsed);
-                setImplLocked(a);
+            boolean changed = mAlarmStore.updateAlarmDeliveries(a -> {
+                if (!isRtc(a.type)) {
+                    return false;
+                }
+                return restoreRequestedTime(a);
+            });
+
+            if (mNextWakeFromIdle != null && isRtc(mNextWakeFromIdle.type)) {
+                // The next wake from idle got updated due to the rtc time change, implying we need
+                // to update the time we have to come out of idle too.
+                changed |= mAlarmStore.updateAlarmDeliveries(a -> {
+                    if (a != mPendingIdleUntil) {
+                        return false;
+                    }
+                    return adjustIdleUntilTime(a);
+                });
+            }
+
+            if (changed) {
+                rescheduleKernelAlarmsLocked();
+                // Only time shifted, so the next alarm clock will not change
             }
         }
     }
@@ -844,7 +866,7 @@
     boolean reorderAlarmsBasedOnStandbyBuckets(ArraySet<Pair<String, Integer>> targetPackages) {
         final long start = mStatLogger.getTime();
 
-        final boolean changed = mAlarmStore.recalculateAlarmDeliveries(a -> {
+        final boolean changed = mAlarmStore.updateAlarmDeliveries(a -> {
             final Pair<String, Integer> packageUser =
                     Pair.create(a.sourcePackage, UserHandle.getUserId(a.creatorUid));
             if (targetPackages != null && !targetPackages.contains(packageUser)) {
@@ -857,23 +879,8 @@
         return changed;
     }
 
-    private void restoreAlarmLocked(Alarm a, long nowElapsed) {
-        a.when = a.origWhen;
-        long whenElapsed = convertToElapsed(a.when, a.type);
-        final long maxElapsed;
-        if (a.windowLength == AlarmManager.WINDOW_EXACT) {
-            // Exact
-            maxElapsed = whenElapsed;
-        } else {
-            // Not exact.  Preserve any explicit window, otherwise recalculate
-            // the window based on the alarm's new futurity.  Note that this
-            // reflects a policy of preferring timely to deferred delivery.
-            maxElapsed = (a.windowLength > 0)
-                    ? clampPositive(whenElapsed + a.windowLength)
-                    : maxTriggerTime(nowElapsed, whenElapsed, a.repeatInterval);
-        }
-        a.expectedWhenElapsed = a.whenElapsed = whenElapsed;
-        a.expectedMaxWhenElapsed = a.maxWhenElapsed = maxElapsed;
+    private boolean restoreRequestedTime(Alarm a) {
+        return a.setPolicyElapsed(REQUESTER_POLICY_INDEX, convertToElapsed(a.origWhen, a.type));
     }
 
     static long clampPositive(long val) {
@@ -973,14 +980,17 @@
             // Recurring alarms may have passed several alarm intervals while the
             // alarm was kept pending. Send the appropriate trigger count.
             if (alarm.repeatInterval > 0) {
-                alarm.count += (nowELAPSED - alarm.expectedWhenElapsed) / alarm.repeatInterval;
+                alarm.count += (nowELAPSED - alarm.getPolicyElapsed(REQUESTER_POLICY_INDEX))
+                        / alarm.repeatInterval;
                 // Also schedule its next recurrence
                 final long delta = alarm.count * alarm.repeatInterval;
-                final long nextElapsed = alarm.expectedWhenElapsed + delta;
-                setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
-                        maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
-                        alarm.repeatInterval, alarm.operation, null, null, alarm.flags,
-                        alarm.workSource, alarm.alarmClock, alarm.uid, alarm.packageName);
+                final long nextElapsed = alarm.getPolicyElapsed(REQUESTER_POLICY_INDEX) + delta;
+                final long nextMaxElapsed = maxTriggerTime(nowELAPSED, nextElapsed,
+                        alarm.repeatInterval);
+                setImplLocked(alarm.type, alarm.origWhen + delta, nextElapsed,
+                        nextMaxElapsed - nextElapsed, alarm.repeatInterval, alarm.operation, null,
+                        null, alarm.flags, alarm.workSource, alarm.alarmClock, alarm.uid,
+                        alarm.packageName);
                 // Kernel alarms will be rescheduled as needed in setImplLocked
             }
         }
@@ -1026,18 +1036,10 @@
         if (mPendingWhileIdleAlarms.size() > 0) {
             ArrayList<Alarm> alarms = mPendingWhileIdleAlarms;
             mPendingWhileIdleAlarms = new ArrayList<>();
-            final long nowElapsed = mInjector.getElapsedRealtime();
             for (int i = alarms.size() - 1; i >= 0; i--) {
-                Alarm a = alarms.get(i);
-                restoreAlarmLocked(a, nowElapsed);
-                setImplLocked(a);
+                setImplLocked(alarms.get(i));
             }
         }
-
-        // Reschedule everything.
-        rescheduleKernelAlarmsLocked();
-        updateNextAlarmClockLocked();
-
     }
 
     static final class InFlight {
@@ -1449,6 +1451,11 @@
             }
         }
 
+        if ((flags & AlarmManager.FLAG_IDLE_UNTIL) != 0) {
+            // Do not support windows for idle-until alarms.
+            windowLength = AlarmManager.WINDOW_EXACT;
+        }
+
         // Sanity check the window length.  This will catch people mistakenly
         // trying to pass an end-of-window timestamp rather than a duration.
         if (windowLength > AlarmManager.INTERVAL_HALF_DAY) {
@@ -1515,17 +1522,17 @@
                 Slog.w(TAG, errorMsg);
                 throw new IllegalStateException(errorMsg);
             }
-            setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed,
-                    interval, operation, directReceiver, listenerTag, flags, workSource,
-                    alarmClock, callingUid, callingPackage);
+            setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, interval, operation,
+                    directReceiver, listenerTag, flags, workSource, alarmClock, callingUid,
+                    callingPackage);
         }
     }
 
     private void setImplLocked(int type, long when, long whenElapsed, long windowLength,
-            long maxWhen, long interval, PendingIntent operation, IAlarmListener directReceiver,
+            long interval, PendingIntent operation, IAlarmListener directReceiver,
             String listenerTag, int flags, WorkSource workSource,
             AlarmManager.AlarmClockInfo alarmClock, int callingUid, String callingPackage) {
-        Alarm a = new Alarm(type, when, whenElapsed, windowLength, maxWhen, interval,
+        final Alarm a = new Alarm(type, when, whenElapsed, windowLength, interval,
                 operation, directReceiver, listenerTag, workSource, flags, alarmClock,
                 callingUid, callingPackage);
         if (mActivityManagerInternal.isAppStartModeDisabled(callingUid, callingPackage)) {
@@ -1560,72 +1567,55 @@
     }
 
     /**
-     * Adjusts the idle-until alarm delivery time based on the upcoming wake-from-idle alarm.
+     * An alarm with {@link AlarmManager#FLAG_IDLE_UNTIL} is a special alarm that will put the
+     * system into idle until it goes off. We need to pull it earlier if there are existing alarms
+     * that have requested to bring us out of idle at an earlier time.
      *
      * @param alarm The alarm to adjust
      * @return true if the alarm delivery time was updated.
      */
     private boolean adjustIdleUntilTime(Alarm alarm) {
-        if ((alarm.flags & AlarmManager.FLAG_IDLE_UNTIL) != 0) {
+        if ((alarm.flags & AlarmManager.FLAG_IDLE_UNTIL) == 0) {
             return false;
         }
-        // This is a special alarm that will put the system into idle until it goes off.
-        // The caller has given the time they want this to happen at, however we need
-        // to pull that earlier if there are existing alarms that have requested to
-        // bring us out of idle at an earlier time.
-        if (mNextWakeFromIdle != null && alarm.whenElapsed > mNextWakeFromIdle.whenElapsed) {
-            alarm.when = alarm.whenElapsed = alarm.maxWhenElapsed = mNextWakeFromIdle.whenElapsed;
+        restoreRequestedTime(alarm);
+        long triggerBeforeFuzz = alarm.getPolicyElapsed(REQUESTER_POLICY_INDEX);
+        if (mNextWakeFromIdle != null && triggerBeforeFuzz > mNextWakeFromIdle.getWhenElapsed()) {
+            triggerBeforeFuzz = mNextWakeFromIdle.getWhenElapsed();
         }
         // Add fuzz to make the alarm go off some time before the actual desired time.
-        final long nowElapsed = mInjector.getElapsedRealtime();
-        final int fuzz = fuzzForDuration(alarm.whenElapsed - nowElapsed);
+        final int fuzz = fuzzForDuration(alarm.getWhenElapsed() - mInjector.getElapsedRealtime());
+        final int delta;
         if (fuzz > 0) {
             if (mRandom == null) {
                 mRandom = new Random();
             }
-            final int delta = mRandom.nextInt(fuzz);
-            alarm.whenElapsed -= delta;
-            if (false) {
-                Slog.d(TAG, "Alarm when: " + alarm.whenElapsed);
-                Slog.d(TAG, "Delta until alarm: " + (alarm.whenElapsed - nowElapsed));
-                Slog.d(TAG, "Applied fuzz: " + fuzz);
-                Slog.d(TAG, "Final delta: " + delta);
-                Slog.d(TAG, "Final when: " + alarm.whenElapsed);
-            }
-            alarm.when = alarm.maxWhenElapsed = alarm.whenElapsed;
+            delta = mRandom.nextInt(fuzz);
+        } else {
+            delta = 0;
         }
+        alarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, triggerBeforeFuzz - delta);
         return true;
     }
 
     /**
-     * Adjusts the alarm delivery time based on the current app standby bucket.
+     * Adjusts the alarm's policy time for app_standby.
      *
-     * @param alarm The alarm to adjust
-     * @return true if the alarm delivery time was updated.
+     * @param alarm The alarm to update.
+     * @return {@code true} if the actual delivery time of the given alarm was updated due to
+     *         adjustments made in this call.
      */
     private boolean adjustDeliveryTimeBasedOnBucketLocked(Alarm alarm) {
-        if (isExemptFromAppStandby(alarm)) {
-            return false;
+        final long nowElapsed = mInjector.getElapsedRealtime();
+        if (isExemptFromAppStandby(alarm) || mAppStandbyParole) {
+            return alarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, nowElapsed);
         }
-        if (mAppStandbyParole) {
-            if (alarm.whenElapsed > alarm.expectedWhenElapsed) {
-                // We did defer this alarm earlier, restore original requirements
-                alarm.whenElapsed = alarm.expectedWhenElapsed;
-                alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed;
-                return true;
-            }
-            return false;
-        }
-        final long oldWhenElapsed = alarm.whenElapsed;
-        final long oldMaxWhenElapsed = alarm.maxWhenElapsed;
 
         final String sourcePackage = alarm.sourcePackage;
         final int sourceUserId = UserHandle.getUserId(alarm.creatorUid);
         final int standbyBucket = mUsageStatsManagerInternal.getAppStandbyBucket(
-                sourcePackage, sourceUserId, mInjector.getElapsedRealtime());
+                sourcePackage, sourceUserId, nowElapsed);
 
-        // Quota deferring implementation:
-        boolean deferred = false;
         final int wakeupsInWindow = mAppWakeupHistory.getTotalWakeupsInWindow(sourcePackage,
                 sourceUserId);
         if (standbyBucket == UsageStatsManager.STANDBY_BUCKET_RESTRICTED) {
@@ -1635,14 +1625,9 @@
             if (wakeupsInWindow > 0) {
                 final long lastWakeupTime = mAppWakeupHistory.getNthLastWakeupForPackage(
                         sourcePackage, sourceUserId, mConstants.APP_STANDBY_RESTRICTED_QUOTA);
-                if (mInjector.getElapsedRealtime() - lastWakeupTime
-                        < mConstants.APP_STANDBY_RESTRICTED_WINDOW) {
-                    final long minElapsed =
-                            lastWakeupTime + mConstants.APP_STANDBY_RESTRICTED_WINDOW;
-                    if (alarm.expectedWhenElapsed < minElapsed) {
-                        alarm.whenElapsed = alarm.maxWhenElapsed = minElapsed;
-                        deferred = true;
-                    }
+                if ((nowElapsed - lastWakeupTime) < mConstants.APP_STANDBY_RESTRICTED_WINDOW) {
+                    return alarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX,
+                            lastWakeupTime + mConstants.APP_STANDBY_RESTRICTED_WINDOW);
                 }
             }
         } else {
@@ -1651,7 +1636,7 @@
                 final long minElapsed;
                 if (quotaForBucket <= 0) {
                     // Just keep deferring for a day till the quota changes
-                    minElapsed = mInjector.getElapsedRealtime() + MILLIS_IN_DAY;
+                    minElapsed = nowElapsed + MILLIS_IN_DAY;
                 } else {
                     // Suppose the quota for window was q, and the qth last delivery time for this
                     // package was t(q) then the next delivery must be after t(q) + <window_size>
@@ -1659,19 +1644,11 @@
                             sourcePackage, sourceUserId, quotaForBucket);
                     minElapsed = t + mConstants.APP_STANDBY_WINDOW;
                 }
-                if (alarm.expectedWhenElapsed < minElapsed) {
-                    alarm.whenElapsed = alarm.maxWhenElapsed = minElapsed;
-                    deferred = true;
-                }
+                return alarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, minElapsed);
             }
         }
-        if (!deferred) {
-            // Restore original requirements in case they were changed earlier.
-            alarm.whenElapsed = alarm.expectedWhenElapsed;
-            alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed;
-        }
-
-        return (oldWhenElapsed != alarm.whenElapsed || oldMaxWhenElapsed != alarm.maxWhenElapsed);
+        // wakeupsInWindow are less than the permitted quota, hence no deferring is needed.
+        return alarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, nowElapsed);
     }
 
     private static boolean isAllowedWhileIdle(Alarm a) {
@@ -1691,7 +1668,7 @@
                 ent.tag = a.operation.getTag("");
                 ent.op = "SET";
                 ent.elapsedRealtime = mInjector.getElapsedRealtime();
-                ent.argRealtime = a.whenElapsed;
+                ent.argRealtime = a.getWhenElapsed();
                 mAllowWhileIdleDispatches.add(ent);
                 if (mPendingIdleUntil == null) {
                     IdleDispatchEntry ent2 = new IdleDispatchEntry();
@@ -1704,6 +1681,7 @@
             if ((mPendingIdleUntil != a) && (mPendingIdleUntil != null)) {
                 Slog.wtfStack(TAG, "setImplLocked: idle until changed from " + mPendingIdleUntil
                         + " to " + a);
+                mAlarmStore.remove(mPendingIdleUntil::equals);
             }
             mPendingIdleUntil = a;
             final ArrayList<Alarm> notAllowedWhileIdleAlarms = mAlarmStore.remove(
@@ -1718,18 +1696,16 @@
             }
         }
         if ((a.flags & AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
-            if (mNextWakeFromIdle == null || mNextWakeFromIdle.whenElapsed > a.whenElapsed) {
+            if (mNextWakeFromIdle == null || mNextWakeFromIdle.getWhenElapsed()
+                    > a.getWhenElapsed()) {
                 mNextWakeFromIdle = a;
                 // If this wake from idle is earlier than whatever was previously scheduled,
-                // and we are currently idling, then we need to rebatch alarms in case the idle
-                // until time needs to be updated.
+                // and we are currently idling, then the idle-until time needs to be updated.
                 if (mPendingIdleUntil != null) {
-                    final long nowElapsed = mInjector.getElapsedRealtime();
-                    mAlarmStore.recalculateAlarmDeliveries(alarm -> {
+                    mAlarmStore.updateAlarmDeliveries(alarm -> {
                         if (alarm != mPendingIdleUntil) {
                             return false;
                         }
-                        restoreAlarmLocked(alarm, nowElapsed);
                         return adjustIdleUntilTime(alarm);
                     });
                 }
@@ -2563,7 +2539,7 @@
 
     long getNextWakeFromIdleTimeImpl() {
         synchronized (mLock) {
-            return mNextWakeFromIdle != null ? mNextWakeFromIdle.whenElapsed : Long.MAX_VALUE;
+            return mNextWakeFromIdle != null ? mNextWakeFromIdle.getWhenElapsed() : Long.MAX_VALUE;
         }
     }
 
@@ -2784,12 +2760,11 @@
                 restorePending = true;
             }
             if (mNextWakeFromIdle != null && mNextWakeFromIdle.matches(operation, directReceiver)) {
-                mNextWakeFromIdle = null;
-                mAlarmStore.recalculateAlarmDeliveries(alarm -> {
+                mNextWakeFromIdle = mAlarmStore.getNextWakeFromIdleAlarm();
+                mAlarmStore.updateAlarmDeliveries(alarm -> {
                     if (alarm != mPendingIdleUntil) {
                         return false;
                     }
-                    restoreAlarmLocked(alarm, mInjector.getElapsedRealtime());
                     return adjustIdleUntilTime(alarm);
                 });
             }
@@ -2834,15 +2809,14 @@
                 mPendingBackgroundAlarms.removeAt(i);
             }
         }
-        // If we're currently keying off of this app's alarms for doze transitions,
-        // make sure to reset to other triggers.
+        // If we're currently using this app's alarms to come out of doze,
+        // make sure to reset to any remaining WAKE_FROM_IDLE alarms.
         if (mNextWakeFromIdle != null && mNextWakeFromIdle.uid == uid) {
-            mNextWakeFromIdle = null;
-            mAlarmStore.recalculateAlarmDeliveries(alarm -> {
+            mNextWakeFromIdle = mAlarmStore.getNextWakeFromIdleAlarm();
+            mAlarmStore.updateAlarmDeliveries(alarm -> {
                 if (alarm != mPendingIdleUntil) {
                     return false;
                 }
-                restoreAlarmLocked(alarm, mInjector.getElapsedRealtime());
                 return adjustIdleUntilTime(alarm);
             });
         }
@@ -2906,15 +2880,14 @@
                 mPendingBackgroundAlarms.removeAt(i);
             }
         }
-        // If we're currently keying off of this app's alarms for doze transitions,
-        // make sure to reset to other triggers.
+        // If we're currently using this app's alarms to come out of doze,
+        // make sure to reset to any remaining WAKE_FROM_IDLE alarms.
         if (removedNextWakeFromIdle.value) {
-            mNextWakeFromIdle = null;
-            mAlarmStore.recalculateAlarmDeliveries(alarm -> {
+            mNextWakeFromIdle = mAlarmStore.getNextWakeFromIdleAlarm();
+            mAlarmStore.updateAlarmDeliveries(alarm -> {
                 if (alarm != mPendingIdleUntil) {
                     return false;
                 }
-                restoreAlarmLocked(alarm, mInjector.getElapsedRealtime());
                 return adjustIdleUntilTime(alarm);
             });
         }
@@ -3071,20 +3044,6 @@
         }
     }
 
-    private static final String labelForType(int type) {
-        switch (type) {
-            case RTC:
-                return "RTC";
-            case RTC_WAKEUP:
-                return "RTC_WAKEUP";
-            case ELAPSED_REALTIME:
-                return "ELAPSED";
-            case ELAPSED_REALTIME_WAKEUP:
-                return "ELAPSED_WAKEUP";
-        }
-        return "--unknown--";
-    }
-
     private static final void dumpAlarmList(PrintWriter pw, ArrayList<Alarm> list,
             String prefix, long nowELAPSED, SimpleDateFormat sdf) {
         final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, prefix, prefix);
@@ -3095,7 +3054,7 @@
             long nowELAPSED, SimpleDateFormat sdf) {
         for (int i = list.size() - 1; i >= 0; i--) {
             final Alarm a = list.get(i);
-            final String label = labelForType(a.type);
+            final String label = Alarm.typeToString(a.type);
             ipw.print(label);
             ipw.print(" #");
             ipw.print(i);
@@ -3125,6 +3084,9 @@
         }
         final String sourcePackage = alarm.sourcePackage;
         final int sourceUid = alarm.creatorUid;
+        if (UserHandle.isCore(sourceUid)) {
+            return false;
+        }
         return (mAppStateTracker != null) &&
                 mAppStateTracker.areAlarmsRestricted(sourceUid, sourcePackage,
                         exemptOnBatterySaver);
@@ -3169,11 +3131,7 @@
                     // Whoops, it hasn't been long enough since the last ALLOW_WHILE_IDLE
                     // alarm went off for this app.  Reschedule the alarm to be in the
                     // correct time period.
-                    alarm.expectedWhenElapsed = alarm.whenElapsed = minTime;
-                    if (alarm.maxWhenElapsed < minTime) {
-                        alarm.maxWhenElapsed = minTime;
-                    }
-                    alarm.expectedMaxWhenElapsed = alarm.maxWhenElapsed;
+                    alarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, minTime);
                     if (RECORD_DEVICE_IDLE_ALARMS) {
                         IdleDispatchEntry ent = new IdleDispatchEntry();
                         ent.uid = alarm.uid;
@@ -3213,12 +3171,11 @@
                 restorePendingWhileIdleAlarmsLocked();
             }
             if (mNextWakeFromIdle == alarm) {
-                mNextWakeFromIdle = null;
-                mAlarmStore.recalculateAlarmDeliveries(a -> {
+                mNextWakeFromIdle = mAlarmStore.getNextWakeFromIdleAlarm();
+                mAlarmStore.updateAlarmDeliveries(a -> {
                     if (a != mPendingIdleUntil) {
                         return false;
                     }
-                    restoreAlarmLocked(a, nowELAPSED);
                     return adjustIdleUntilTime(a);
                 });
             }
@@ -3228,14 +3185,17 @@
             if (alarm.repeatInterval > 0) {
                 // this adjustment will be zero if we're late by
                 // less than one full repeat interval
-                alarm.count += (nowELAPSED - alarm.expectedWhenElapsed) / alarm.repeatInterval;
+                alarm.count += (nowELAPSED - alarm.getPolicyElapsed(REQUESTER_POLICY_INDEX))
+                        / alarm.repeatInterval;
                 // Also schedule its next recurrence
                 final long delta = alarm.count * alarm.repeatInterval;
-                final long nextElapsed = alarm.expectedWhenElapsed + delta;
-                setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
-                        maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
-                        alarm.repeatInterval, alarm.operation, null, null, alarm.flags,
-                        alarm.workSource, alarm.alarmClock, alarm.uid, alarm.packageName);
+                final long nextElapsed = alarm.getPolicyElapsed(REQUESTER_POLICY_INDEX) + delta;
+                final long nextMaxElapsed = maxTriggerTime(nowELAPSED, nextElapsed,
+                        alarm.repeatInterval);
+                setImplLocked(alarm.type, alarm.origWhen + delta, nextElapsed,
+                        nextMaxElapsed - nextElapsed, alarm.repeatInterval, alarm.operation, null,
+                        null, alarm.flags, alarm.workSource, alarm.alarmClock, alarm.uid,
+                        alarm.packageName);
             }
 
             if (alarm.wakeup) {
@@ -3277,7 +3237,7 @@
         }
     }
 
-    static int fuzzForDuration(long duration) {
+    int fuzzForDuration(long duration) {
         if (duration < 15 * 60 * 1000) {
             // If the duration until the time is less than 15 minutes, the maximum fuzz
             // is the duration.
@@ -3480,7 +3440,7 @@
                         FrameworkStatsLog.write(FrameworkStatsLog.WALL_CLOCK_TIME_SHIFTED, nowRTC);
                         removeImpl(null, mTimeTickTrigger);
                         removeImpl(mDateChangeSender, null);
-                        reevaluateRtcAlarms(nowELAPSED);
+                        reevaluateRtcAlarms();
                         mClockReceiver.scheduleTimeTickEvent();
                         mClockReceiver.scheduleDateChangedEvent();
                         synchronized (mLock) {
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmStore.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmStore.java
index 9fdbb8b..7a846b9 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmStore.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmStore.java
@@ -48,6 +48,15 @@
     ArrayList<Alarm> remove(Predicate<Alarm> whichAlarms);
 
     /**
+     * Gets the earliest alarm with the flag {@link android.app.AlarmManager#FLAG_WAKE_FROM_IDLE}
+     * based on {@link Alarm#getWhenElapsed()}.
+     *
+     * @return An alarm object matching the description above or {@code null} if no such alarm was
+     *         found.
+     */
+    Alarm getNextWakeFromIdleAlarm();
+
+    /**
      * Returns the total number of alarms in this store.
      */
     int size();
@@ -71,7 +80,7 @@
     /**
      * Removes all alarms that are pending delivery at the given time.
      *
-     * @param nowElapsed    The time at which delivery eligibility is evaluated.
+     * @param nowElapsed The time at which delivery eligibility is evaluated.
      * @return The list of alarms pending at the given time.
      */
     ArrayList<Alarm> removePendingAlarms(long nowElapsed);
@@ -82,7 +91,7 @@
      *
      * @return {@code true} if any of the alarm deliveries changed due to this call.
      */
-    boolean recalculateAlarmDeliveries(AlarmDeliveryCalculator deliveryCalculator);
+    boolean updateAlarmDeliveries(AlarmDeliveryCalculator deliveryCalculator);
 
     /**
      * Returns all the alarms in the form of a list.
@@ -97,6 +106,7 @@
      * Primary useful for debugging. Can be called from the
      * {@link android.os.Binder#dump(FileDescriptor PrintWriter, String[]) dump} method of the
      * caller.
+     *
      * @param ipw        The {@link IndentingPrintWriter} to write to.
      * @param nowElapsed the time when the dump is requested in the
      *                   {@link SystemClock#elapsedRealtime()
@@ -112,7 +122,7 @@
 
     /**
      * A functional interface used to update the alarm. Used to describe the update in
-     * {@link #recalculateAlarmDeliveries(AlarmDeliveryCalculator)}
+     * {@link #updateAlarmDeliveries(AlarmDeliveryCalculator)}
      */
     @FunctionalInterface
     interface AlarmDeliveryCalculator {
@@ -125,3 +135,4 @@
         boolean updateAlarmDelivery(Alarm a);
     }
 }
+
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/BatchingAlarmStore.java b/apex/jobscheduler/service/java/com/android/server/alarm/BatchingAlarmStore.java
index 91c0c05..cbfe80b 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/BatchingAlarmStore.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/BatchingAlarmStore.java
@@ -66,8 +66,8 @@
     };
 
     private static final Comparator<Alarm> sIncreasingTimeOrder = (a1, a2) -> {
-        long when1 = a1.whenElapsed;
-        long when2 = a2.whenElapsed;
+        long when1 = a1.getWhenElapsed();
+        long when2 = a2.getWhenElapsed();
         if (when1 > when2) {
             return 1;
         }
@@ -99,11 +99,28 @@
         }
         if (!removed.isEmpty()) {
             mSize -= removed.size();
+            // Not needed if only whole batches were removed, but keeping existing behavior.
             rebatchAllAlarms();
         }
         return removed;
     }
 
+    @Override
+    public Alarm getNextWakeFromIdleAlarm() {
+        for (final Batch batch : mAlarmBatches) {
+            if ((batch.mFlags & AlarmManager.FLAG_WAKE_FROM_IDLE) == 0) {
+                continue;
+            }
+            for (int i = 0; i < batch.size(); i++) {
+                final Alarm a = batch.get(i);
+                if ((a.flags & AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
+                    return a;
+                }
+            }
+        }
+        return null;
+    }
+
     private void rebatchAllAlarms() {
         final long start = mStatLogger.getTime();
         final ArrayList<Batch> oldBatches = (ArrayList<Batch>) mAlarmBatches.clone();
@@ -157,7 +174,7 @@
     }
 
     @Override
-    public boolean recalculateAlarmDeliveries(AlarmDeliveryCalculator deliveryCalculator) {
+    public boolean updateAlarmDeliveries(AlarmDeliveryCalculator deliveryCalculator) {
         boolean changed = false;
         for (final Batch b : mAlarmBatches) {
             for (int i = 0; i < b.size(); i++) {
@@ -204,7 +221,7 @@
 
     private void insertAndBatchAlarm(Alarm alarm) {
         final int whichBatch = ((alarm.flags & AlarmManager.FLAG_STANDALONE) != 0) ? -1
-                : attemptCoalesce(alarm.whenElapsed, alarm.maxWhenElapsed);
+                : attemptCoalesce(alarm.getWhenElapsed(), alarm.getMaxWhenElapsed());
 
         if (whichBatch < 0) {
             addBatch(mAlarmBatches, new Batch(alarm));
@@ -247,8 +264,8 @@
         final ArrayList<Alarm> mAlarms = new ArrayList<>();
 
         Batch(Alarm seed) {
-            mStart = seed.whenElapsed;
-            mEnd = clampPositive(seed.maxWhenElapsed);
+            mStart = seed.getWhenElapsed();
+            mEnd = clampPositive(seed.getMaxWhenElapsed());
             mFlags = seed.flags;
             mAlarms.add(seed);
         }
@@ -276,12 +293,12 @@
             if (DEBUG_BATCH) {
                 Slog.v(TAG, "Adding " + alarm + " to " + this);
             }
-            if (alarm.whenElapsed > mStart) {
-                mStart = alarm.whenElapsed;
+            if (alarm.getWhenElapsed() > mStart) {
+                mStart = alarm.getWhenElapsed();
                 newStart = true;
             }
-            if (alarm.maxWhenElapsed < mEnd) {
-                mEnd = alarm.maxWhenElapsed;
+            if (alarm.getMaxWhenElapsed() < mEnd) {
+                mEnd = alarm.getMaxWhenElapsed();
             }
             mFlags |= alarm.flags;
 
@@ -309,11 +326,11 @@
                         Slog.wtf(TAG, "Removed TIME_TICK alarm");
                     }
                 } else {
-                    if (alarm.whenElapsed > newStart) {
-                        newStart = alarm.whenElapsed;
+                    if (alarm.getWhenElapsed() > newStart) {
+                        newStart = alarm.getWhenElapsed();
                     }
-                    if (alarm.maxWhenElapsed < newEnd) {
-                        newEnd = alarm.maxWhenElapsed;
+                    if (alarm.getMaxWhenElapsed() < newEnd) {
+                        newEnd = alarm.getMaxWhenElapsed();
                     }
                     newFlags |= alarm.flags;
                     i++;
diff --git a/api/test-current.txt b/api/test-current.txt
index 9069eea..e7c6445 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -3485,6 +3485,7 @@
     field public static final String DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD = "dynamic_power_savings_disable_threshold";
     field public static final String DYNAMIC_POWER_SAVINGS_ENABLED = "dynamic_power_savings_enabled";
     field public static final String HIDDEN_API_BLACKLIST_EXEMPTIONS = "hidden_api_blacklist_exemptions";
+    field public static final String HIDDEN_API_POLICY = "hidden_api_policy";
     field public static final String HIDE_ERROR_DIALOGS = "hide_error_dialogs";
     field public static final String LOCATION_GLOBAL_KILL_SWITCH = "location_global_kill_switch";
     field public static final String LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST = "location_ignore_settings_package_whitelist";
diff --git a/api/test-lint-baseline.txt b/api/test-lint-baseline.txt
index a314702..0440d1a 100644
--- a/api/test-lint-baseline.txt
+++ b/api/test-lint-baseline.txt
@@ -2511,6 +2511,8 @@
     
 NoSettingsProvider: android.provider.Settings.Global#HIDDEN_API_BLACKLIST_EXEMPTIONS:
     
+NoSettingsProvider: android.provider.Settings.Global#HIDDEN_API_POLICY:
+    
 NoSettingsProvider: android.provider.Settings.Global#HIDE_ERROR_DIALOGS:
     
 NoSettingsProvider: android.provider.Settings.Global#LOCATION_GLOBAL_KILL_SWITCH:
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index e5dbb42..091e9a7 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -3834,6 +3834,12 @@
     // App startup time (until call to Activity#reportFullyDrawn()).
     optional int64 app_startup_time_millis = 6;
 
+    // The compiler filter used when when the package was optimized.
+    optional int32 package_optimization_compilation_filter = 7;
+
+    // The reason why the package was optimized.
+    optional int32 package_optimization_compilation_reason = 8;
+
     enum SourceType {
         UNAVAILABLE = 0;
         LAUNCHER = 1;
@@ -3841,11 +3847,11 @@
         LOCKSCREEN = 3;
     }
     // The type of the startup source.
-    optional SourceType source_type = 7;
+    optional SourceType source_type = 9;
 
     // The time from the startup source to the beginning of handling the startup event.
     // -1 means not available.
-    optional int32 source_event_delay_millis = 8;
+    optional int32 source_event_delay_millis = 10;
 }
 
 /**
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 90401ad..b020c70 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -81,6 +81,7 @@
 import android.hardware.biometrics.BiometricManager;
 import android.hardware.biometrics.IAuthService;
 import android.hardware.camera2.CameraManager;
+import android.hardware.devicestate.DeviceStateManager;
 import android.hardware.display.ColorDisplayManager;
 import android.hardware.display.DisplayManager;
 import android.hardware.face.FaceManager;
@@ -1348,6 +1349,12 @@
                             throws ServiceNotFoundException {
                         return new DreamManager(ctx);
                     }});
+        registerService(Context.DEVICE_STATE_SERVICE, DeviceStateManager.class,
+                new CachedServiceFetcher<DeviceStateManager>() {
+                    @Override
+                    public DeviceStateManager createService(ContextImpl ctx) {
+                        return new DeviceStateManager();
+                    }});
 
         sInitializing = true;
         try {
@@ -1404,6 +1411,7 @@
                 case Context.CONTENT_CAPTURE_MANAGER_SERVICE:
                 case Context.APP_PREDICTION_SERVICE:
                 case Context.INCREMENTAL_SERVICE:
+                case Context.ETHERNET_SERVICE:
                     return null;
             }
             Slog.wtf(TAG, "Manager wrapper not available: " + name);
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index 79f05a3..eedf958 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -852,15 +852,6 @@
     }
 
     /**
-     * Returns true if this container may be scaled without resizing, and windows within may need
-     * to be configured as such.
-     * @hide
-     */
-    public boolean windowsAreScaleable() {
-        return mWindowingMode == WINDOWING_MODE_PINNED;
-    }
-
-    /**
      * Returns true if windows in this container should be given move animations by default.
      * @hide
      */
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 9c216a3..c4157cf 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3508,6 +3508,7 @@
             PERMISSION_SERVICE,
             LIGHTS_SERVICE,
             //@hide: PEOPLE_SERVICE,
+            //@hide: DEVICE_STATE_SERVICE,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ServiceName {}
@@ -5246,6 +5247,14 @@
     public static final String PEOPLE_SERVICE = "people";
 
     /**
+     * Use with {@link #getSystemService(String)} to access device state service.
+     *
+     * @see #getSystemService(String)
+     * @hide
+     */
+    public static final String DEVICE_STATE_SERVICE = "device_state";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
diff --git a/core/java/android/hardware/devicestate/DeviceStateManager.java b/core/java/android/hardware/devicestate/DeviceStateManager.java
new file mode 100644
index 0000000..a52f983
--- /dev/null
+++ b/core/java/android/hardware/devicestate/DeviceStateManager.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 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.hardware.devicestate;
+
+import android.annotation.SystemService;
+import android.content.Context;
+
+/**
+ * Manages the state of the system for devices with user-configurable hardware like a foldable
+ * phone.
+ *
+ * @hide
+ */
+@SystemService(Context.DEVICE_STATE_SERVICE)
+public final class DeviceStateManager {
+    /** Invalid device state. */
+    public static final int INVALID_DEVICE_STATE = -1;
+
+    private DeviceStateManagerGlobal mGlobal;
+
+    public DeviceStateManager() {
+        mGlobal = DeviceStateManagerGlobal.getInstance();
+    }
+}
diff --git a/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java b/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
new file mode 100644
index 0000000..4e7cf4a
--- /dev/null
+++ b/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2020 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.hardware.devicestate;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.ServiceManager;
+
+/**
+ * Provides communication with the device state system service on behalf of applications.
+ *
+ * @see DeviceStateManager
+ * @hide
+ */
+final class DeviceStateManagerGlobal {
+    private static DeviceStateManagerGlobal sInstance;
+
+    /**
+     * Returns an instance of {@link DeviceStateManagerGlobal}. May return {@code null} if a
+     * connection with the device state service couldn't be established.
+     */
+    @Nullable
+    static DeviceStateManagerGlobal getInstance() {
+        synchronized (DeviceStateManagerGlobal.class) {
+            if (sInstance == null) {
+                IBinder b = ServiceManager.getService(Context.DEVICE_STATE_SERVICE);
+                if (b != null) {
+                    sInstance = new DeviceStateManagerGlobal(IDeviceStateManager
+                            .Stub.asInterface(b));
+                }
+            }
+            return sInstance;
+        }
+    }
+
+    @NonNull
+    private final IDeviceStateManager mDeviceStateManager;
+
+    private DeviceStateManagerGlobal(@NonNull IDeviceStateManager deviceStateManager) {
+        mDeviceStateManager = deviceStateManager;
+    }
+}
diff --git a/core/java/android/hardware/devicestate/IDeviceStateManager.aidl b/core/java/android/hardware/devicestate/IDeviceStateManager.aidl
new file mode 100644
index 0000000..24913e9
--- /dev/null
+++ b/core/java/android/hardware/devicestate/IDeviceStateManager.aidl
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2020, 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.hardware.devicestate;
+
+/** @hide */
+interface IDeviceStateManager {}
diff --git a/core/java/android/net/NetworkProvider.java b/core/java/android/net/NetworkProvider.java
index 75086cf..d31218d 100644
--- a/core/java/android/net/NetworkProvider.java
+++ b/core/java/android/net/NetworkProvider.java
@@ -30,7 +30,7 @@
 
 /**
  * Base class for network providers such as telephony or Wi-Fi. NetworkProviders connect the device
- * to networks and makes them available to to the core network stack by creating
+ * to networks and makes them available to the core network stack by creating
  * {@link NetworkAgent}s. The networks can then provide connectivity to apps and can be interacted
  * with via networking APIs such as {@link ConnectivityManager}.
  *
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 8ad7669..b133bcd 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -13412,6 +13412,7 @@
          *
          * @hide
          */
+        @TestApi
         public static final String HIDDEN_API_POLICY = "hidden_api_policy";
 
         /**
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 5b0d950..0847a17 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -739,7 +739,7 @@
      * Set the scaling mode to be used for this surfaces buffers
      * @hide
      */
-    void setScalingMode(@ScalingMode int scalingMode) {
+     public void setScalingMode(@ScalingMode int scalingMode) {
         synchronized (mLock) {
             checkNotReleasedLocked();
             int err = nativeSetScalingMode(mNativeObject, scalingMode);
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index ed9deec..566ebf3 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -187,8 +187,6 @@
     private static native void nativeReparent(long transactionObj, long nativeObject,
             long newParentNativeObject);
     private static native void nativeSeverChildren(long transactionObj, long nativeObject);
-    private static native void nativeSetOverrideScalingMode(long transactionObj, long nativeObject,
-            int scalingMode);
 
     private static native Display.HdrCapabilities nativeGetHdrCapabilities(IBinder displayToken);
 
@@ -1521,16 +1519,6 @@
     /**
      * @hide
      */
-    public void setOverrideScalingMode(int scalingMode) {
-        checkNotReleased();
-        synchronized(SurfaceControl.class) {
-            sGlobalTransaction.setOverrideScalingMode(this, scalingMode);
-        }
-    }
-
-    /**
-     * @hide
-     */
     @UnsupportedAppUsage
     public void setLayer(int zorder) {
         checkNotReleased();
@@ -2989,16 +2977,6 @@
         }
 
         /**
-         * @hide
-         */
-        public Transaction setOverrideScalingMode(SurfaceControl sc, int overrideScalingMode) {
-            checkPreconditions(sc);
-            nativeSetOverrideScalingMode(mNativeObject, sc.mNativeObject,
-                    overrideScalingMode);
-            return this;
-        }
-
-        /**
          * Fills the surface with the specified color.
          * @param color A float array with three values to represent r, g, b in range [0..1]. An
          * invalid color will remove the color fill.
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 1419855..a61903d 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -1360,15 +1360,6 @@
     transaction->detachChildren(ctrl);
 }
 
-static void nativeSetOverrideScalingMode(JNIEnv* env, jclass clazz, jlong transactionObj,
-        jlong nativeObject,
-        jint scalingMode) {
-    auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
-
-    auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
-    transaction->setOverrideScalingMode(ctrl, scalingMode);
-}
-
 static jobject nativeGetHdrCapabilities(JNIEnv* env, jclass clazz, jobject tokenObject) {
     sp<IBinder> token(ibinderForJavaObject(env, tokenObject));
     if (token == NULL) return NULL;
@@ -1694,8 +1685,6 @@
             (void*)nativeReparent },
     {"nativeSeverChildren", "(JJ)V",
             (void*)nativeSeverChildren } ,
-    {"nativeSetOverrideScalingMode", "(JJI)V",
-            (void*)nativeSetOverrideScalingMode },
     {"nativeCaptureDisplay",
             "(Landroid/view/SurfaceControl$DisplayCaptureArgs;Landroid/view/SurfaceControl$ScreenCaptureListener;)I",
             (void*)nativeCaptureDisplay },
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 7fac615..32ce5e2 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -2751,4 +2751,9 @@
 
     // OS: R QPR2
     BLUETOOTH_PAIRING_RECEIVER = 1851;
+
+    // OPEN: Settings > Display > Screen timeout
+    // CATEGORY: SETTINGS
+    // OS: S
+    SCREEN_TIMEOUT = 1852;
 }
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 7057b844..012acf5 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1206,7 +1206,7 @@
     <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_1">%2$d</xliff:g> ичинен <xliff:g id="NUMBER_0">%1$d</xliff:g> колдонмо ыңгайлаштырылууда."</string>
     <string name="android_preparing_apk" msgid="589736917792300956">"<xliff:g id="APPNAME">%1$s</xliff:g> даярдалууда."</string>
     <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Колдонмолорду иштетип баштоо"</string>
-    <string name="android_upgrading_complete" msgid="409800058018374746">"Жүктөө аякталууда."</string>
+    <string name="android_upgrading_complete" msgid="409800058018374746">"Жүктөлүүдө"</string>
     <string name="heavy_weight_notification" msgid="8382784283600329576">"<xliff:g id="APP">%1$s</xliff:g> иштеп жатат"</string>
     <string name="heavy_weight_notification_detail" msgid="6802247239468404078">"Оюнга кайтуу үчүн таптаңыз"</string>
     <string name="heavy_weight_switcher_title" msgid="3861984210040100886">"Оюн тандоо"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 1418248..2183d010 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -957,18 +957,18 @@
     <string name="autofill_parish" msgid="6847960518334530198">"Мөргөлч"</string>
     <string name="autofill_area" msgid="8289022370678448983">"Хэсэг"</string>
     <string name="autofill_emirate" msgid="2544082046790551168">"Эмират"</string>
-    <string name="permlab_readHistoryBookmarks" msgid="9102293913842539697">"өөрийн Вэб хавчуурга болон түүхийг унших"</string>
+    <string name="permlab_readHistoryBookmarks" msgid="9102293913842539697">"өөрийн Веб хавчуурга болон түүхийг унших"</string>
     <string name="permdesc_readHistoryBookmarks" msgid="2323799501008967852">"Апп нь Хөтчийн зочилж байсан бүх URL-н түүх болон Хөтчийн бүх хавчуургыг унших боломжтой. Анхаар: Энэ зөвшөөрөл нь гуравдагч талын хөтөч эсвэл вебээр хөтөчлөх чадавхтай аппликейшнүүдэд ашиглагдахгүй байх боломжтой."</string>
-    <string name="permlab_writeHistoryBookmarks" msgid="6090259925187986937">"вэб хавчуурга болон түүхийг бичих"</string>
+    <string name="permlab_writeHistoryBookmarks" msgid="6090259925187986937">"веб хавчуурга болон түүхийг бичих"</string>
     <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="573341025292489065">"Апп нь таны таблет дээр хадгалагдсан Хөтчийн түүх эсвэл хавчуургыг өөрчлөх боломжтой. Энэ нь апп-д Хөтчийн датаг арилгах эсвэл өөрчлөх боломжийг олгоно. Анхаар: Энэ зөвшөөрөл нь гуравдагч талын хөтөч эсвэл вебээр хөтөчлөх чадвартай аппликейшнд ажиллахгүй байх боломжтой."</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="88642768580408561">"Аппад таны Android TV төхөөрөмжид хадгалсан Хөтчийн түүх эсвэл хавчуургыг өөрчлөхийг зөвшөөрнө. Энэ нь аппад Хөтчийн өгөгдлийг устгах эсвэл өөрчлөхийг зөвшөөрч болзошгүй. Санамж: энэ зөвшөөрөл нь гуравдагч талын хөтөч эсвэл вэб хөтчийн чадамжтай бусад аппад хэрэгжихгүй байж болзошгүй."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="88642768580408561">"Аппад таны Android TV төхөөрөмжид хадгалсан Хөтчийн түүх эсвэл хавчуургыг өөрчлөхийг зөвшөөрнө. Энэ нь аппад Хөтчийн өгөгдлийг устгах эсвэл өөрчлөхийг зөвшөөрч болзошгүй. Санамж: энэ зөвшөөрөл нь гуравдагч талын хөтөч эсвэл веб хөтчийн чадамжтай бусад аппад хэрэгжихгүй байж болзошгүй."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="2245203087160913652">"Апп нь таны утсан дээр хадгалагдсан Хөтчийн түүх эсвэл хавчуургыг өөрчлөх боломжтой. Энэ нь апп-д Хөтчийн датаг арилгах эсвэл өөрчлөх боломжийг олгоно. Анхаар: Энэ зөвшөөрөл нь гуравдагч талын хөтөч эсвэл вебээр хөтөчлөх чадвартай аппликейшнд ажиллахгүй байх боломжтой."</string>
     <string name="permlab_setAlarm" msgid="1158001610254173567">"сэрүүлэг тохируулах"</string>
     <string name="permdesc_setAlarm" msgid="2185033720060109640">"Апп нь суулгагдсан сэрүүлэгний апп дээр сэрүүлэг тохируулах боломжтой. Зарим сэрүүлэгний апп нь энэ функцийг дэмжихгүй байж болзошгүй."</string>
     <string name="permlab_addVoicemail" msgid="4770245808840814471">"дуут шуудан нэмэх"</string>
     <string name="permdesc_addVoicemail" msgid="5470312139820074324">"Таны дуут шуудангийн ирсэн мэйлд зурвас нэмэхийг апп-д зөвшөөрөх."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="8605631647492879449">"Хөтчийн геобайршлын зөвшөөрлийг өөрчлөх"</string>
-    <string name="permdesc_writeGeolocationPermissions" msgid="5817346421222227772">"Апп нь Хөтчийн гео байршлын зөвшөөрлийг өөрчлөх боломжтой. Хортой апп нь энийг ашиглан дурын вэб хуудасруу байршлын мэдээллийг илгээх боломжтой."</string>
+    <string name="permdesc_writeGeolocationPermissions" msgid="5817346421222227772">"Апп нь Хөтчийн гео байршлын зөвшөөрлийг өөрчлөх боломжтой. Хортой апп нь энийг ашиглан дурын веб хуудасруу байршлын мэдээллийг илгээх боломжтой."</string>
     <string name="save_password_message" msgid="2146409467245462965">"Та хөтчид энэ нууц үгийг сануулах уу?"</string>
     <string name="save_password_notnow" msgid="2878327088951240061">"Одоо биш"</string>
     <string name="save_password_remember" msgid="6490888932657708341">"Санах"</string>
@@ -1459,7 +1459,7 @@
     <string name="progress_erasing" msgid="6891435992721028004">"Хуваалцсан хадгалах санг устгаж байна…"</string>
     <string name="share" msgid="4157615043345227321">"Хуваалцах"</string>
     <string name="find" msgid="5015737188624767706">"Олох"</string>
-    <string name="websearch" msgid="5624340204512793290">"Вэб хайлт"</string>
+    <string name="websearch" msgid="5624340204512793290">"Веб хайлт"</string>
     <string name="find_next" msgid="5341217051549648153">"Дараагийнхыг хайх"</string>
     <string name="find_previous" msgid="4405898398141275532">"Өмнөхөөс олох"</string>
     <string name="gpsNotifTicker" msgid="3207361857637620780">"<xliff:g id="NAME">%s</xliff:g>-н байршлын хүсэлт"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 2cdf709..092686b 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1389,7 +1389,7 @@
     <string name="ext_media_status_unmountable" msgid="7043574843541087748">"बिग्रेको"</string>
     <string name="ext_media_status_unsupported" msgid="5460509911660539317">"असमर्थित"</string>
     <string name="ext_media_status_ejecting" msgid="7532403368044013797">"निकाल्दै..."</string>
-    <string name="ext_media_status_formatting" msgid="774148701503179906">"फरम्याट गर्दै…"</string>
+    <string name="ext_media_status_formatting" msgid="774148701503179906">"फर्म्याट गर्दै…"</string>
     <string name="ext_media_status_missing" msgid="6520746443048867314">"सम्मिलित छैन"</string>
     <string name="activity_list_empty" msgid="4219430010716034252">"कुनै मिल्ने गतिविधि पाइएन।"</string>
     <string name="permlab_route_media_output" msgid="8048124531439513118">"मिडिया निकास दिशानिर्देश गराउनुहोस्"</string>
diff --git a/core/tests/coretests/src/android/text/TextShaperTest.java b/core/tests/coretests/src/android/text/TextShaperTest.java
new file mode 100644
index 0000000..f92ea99
--- /dev/null
+++ b/core/tests/coretests/src/android/text/TextShaperTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 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.text;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.graphics.text.PositionedGlyphs;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class TextShaperTest {
+
+    @Test
+    public void testFontWithPath() {
+        TextPaint p = new TextPaint();
+        p.setFontFeatureSettings("'wght' 900");
+        List<PositionedGlyphs> glyphs = StyledTextShaper.shapeText("a", 0, 1,
+                TextDirectionHeuristics.LTR, p);
+        assertThat(glyphs.size()).isEqualTo(1);
+        // This test only passes if the font of the Latin font is variable font.
+        assertThat(glyphs.get(0).getFont(0).getFile()).isNotNull();
+
+    }
+}
diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java
index 21b8fc6..97cd8ab 100644
--- a/graphics/java/android/graphics/fonts/Font.java
+++ b/graphics/java/android/graphics/fonts/Font.java
@@ -687,7 +687,9 @@
                 charBuffer[3] = (char) ((packedAxis & 0x0000_00FF_0000_0000L) >> 32);
                 axes[i] = new FontVariationAxis(new String(charBuffer), value);
             }
-            Font.Builder builder = new Font.Builder(buffer)
+            String path = nGetFontPath(ptr);
+            File file = (path == null) ? null : new File(path);
+            Font.Builder builder = new Font.Builder(buffer, file, "")
                     .setWeight(weight)
                     .setSlant(italic ? FontStyle.FONT_SLANT_ITALIC : FontStyle.FONT_SLANT_UPRIGHT)
                     .setTtcIndex(ttcIndex)
@@ -712,6 +714,9 @@
     private static native long nGetAxisInfo(long ptr, int i);
 
     @FastNative
+    private static native String nGetFontPath(long ptr);
+
+    @FastNative
     private static native float nGetGlyphBounds(long font, int glyphId, long paint, RectF rect);
 
     @FastNative
diff --git a/libs/hwui/jni/fonts/Font.cpp b/libs/hwui/jni/fonts/Font.cpp
index 6bc318d..aeb096d 100644
--- a/libs/hwui/jni/fonts/Font.cpp
+++ b/libs/hwui/jni/fonts/Font.cpp
@@ -221,6 +221,17 @@
     return (static_cast<uint64_t>(var.axisTag) << 32) | static_cast<uint64_t>(floatBinary);
 }
 
+// FastNative
+static jstring Font_getFontPath(JNIEnv* env, jobject, jlong fontHandle) {
+    const minikin::Font* font = reinterpret_cast<minikin::Font*>(fontHandle);
+    MinikinFontSkia* minikinSkia = static_cast<MinikinFontSkia*>(font->typeface().get());
+    const std::string& filePath = minikinSkia->getFilePath();
+    if (filePath.empty()) {
+        return nullptr;
+    }
+    return env->NewStringUTF(filePath.c_str());
+}
+
 // Critical Native
 static jlong Font_getNativeFontPtr(CRITICAL_JNI_PARAMS_COMMA jlong fontHandle) {
     FontWrapper* font = reinterpret_cast<FontWrapper*>(fontHandle);
@@ -274,6 +285,7 @@
     { "nGetFontMetrics", "(JJLandroid/graphics/Paint$FontMetrics;)F", (void*) Font_getFontMetrics },
     { "nGetFontInfo", "(J)J", (void*) Font_getFontInfo },
     { "nGetAxisInfo", "(JI)J", (void*) Font_getAxisInfo },
+    { "nGetFontPath", "(J)Ljava/lang/String;", (void*) Font_getFontPath },
     { "nGetNativeFontPtr", "(J)J", (void*) Font_getNativeFontPtr },
 };
 
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index eb2e23e..4a095c9 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -28,7 +28,6 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
-import android.telephony.PhoneNumberUtils;
 import android.telephony.PhoneStateListener;
 import android.telephony.TelephonyManager;
 import android.util.Log;
@@ -161,7 +160,7 @@
                        be set to true when the phone is having emergency call, and then will
                        be set to false by mPhoneStateListener when the emergency call ends.
                 */
-                mIsInEmergencyCall = PhoneNumberUtils.isEmergencyNumber(phoneNumber);
+                mIsInEmergencyCall = mTelephonyManager.isEmergencyNumber(phoneNumber);
                 if (DEBUG) Log.v(TAG, "ACTION_NEW_OUTGOING_CALL - " + getInEmergency());
             } else if (action.equals(LocationManager.MODE_CHANGED_ACTION)) {
                 updateLocationMode();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index f1727ec..094e866 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -124,6 +124,7 @@
     private float mAppearAnimationTranslation;
     private int mNormalColor;
     private boolean mIsBelowSpeedBump;
+    private long mLastActionUpTime;
 
     private float mNormalBackgroundVisibilityAmount;
     private float mDimmedBackgroundFadeInAmount = -1;
@@ -225,6 +226,22 @@
         return super.onInterceptTouchEvent(ev);
     }
 
+    /** Sets the last action up time this view was touched. */
+    void setLastActionUpTime(long eventTime) {
+        mLastActionUpTime = eventTime;
+    }
+
+    /**
+     * Returns the last action up time. The last time will also be cleared because the source of
+     * action is not only from touch event. That prevents the caller from utilizing the time with
+     * unrelated event. The time can be 0 if the event is unavailable.
+     */
+    public long getAndResetLastActionUpTime() {
+        long lastActionUpTime = mLastActionUpTime;
+        mLastActionUpTime = 0;
+        return lastActionUpTime;
+    }
+
     protected boolean disallowSingleClick(MotionEvent ev) {
         return false;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java
index dd30c89..41ce51c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.notification.row;
 
+import android.os.SystemClock;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.accessibility.AccessibilityManager;
@@ -92,6 +93,9 @@
                 mBlockNextTouch = false;
                 return true;
             }
+            if (ev.getAction() == MotionEvent.ACTION_UP) {
+                mView.setLastActionUpTime(SystemClock.uptimeMillis());
+            }
             if (mNeedsDimming && !mAccessibilityManager.isTouchExplorationEnabled()
                     && mView.isInteractive()) {
                 if (mNeedsDimming && !mView.isDimmed()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 456e99c..873d40f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -4282,6 +4282,19 @@
     }
 
     public static Bundle getActivityOptions(@Nullable RemoteAnimationAdapter animationAdapter) {
+        return getDefaultActivityOptions(animationAdapter).toBundle();
+    }
+
+    public static Bundle getActivityOptions(@Nullable RemoteAnimationAdapter animationAdapter,
+            boolean isKeyguardShowing, long eventTime) {
+        ActivityOptions options = getDefaultActivityOptions(animationAdapter);
+        options.setSourceInfo(isKeyguardShowing ? ActivityOptions.SourceInfo.TYPE_LOCKSCREEN
+                : ActivityOptions.SourceInfo.TYPE_NOTIFICATION, eventTime);
+        return options.toBundle();
+    }
+
+    public static ActivityOptions getDefaultActivityOptions(
+            @Nullable RemoteAnimationAdapter animationAdapter) {
         ActivityOptions options;
         if (animationAdapter != null) {
             options = ActivityOptions.makeRemoteAnimation(animationAdapter);
@@ -4291,7 +4304,7 @@
         // Anything launched from the notification shade should always go into the secondary
         // split-screen windowing mode.
         options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY);
-        return options.toBundle();
+        return options;
     }
 
     void visibilityChanged(boolean visible) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index aa01642..256ee20 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -30,6 +30,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.AsyncTask;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.RemoteException;
@@ -40,7 +41,6 @@
 import android.text.TextUtils;
 import android.util.EventLog;
 import android.view.RemoteAnimationAdapter;
-import android.view.View;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.statusbar.NotificationVisibility;
@@ -402,7 +402,7 @@
             PendingIntent intent,
             Intent fillInIntent,
             NotificationEntry entry,
-            View row,
+            ExpandableNotificationRow row,
             boolean wasOccluded,
             boolean isActivityIntent) {
         RemoteAnimationAdapter adapter = mActivityLaunchAnimator.getLaunchAnimation(row,
@@ -414,8 +414,11 @@
                         .registerRemoteAnimationForNextActivityStart(
                                 intent.getCreatorPackage(), adapter);
             }
+            long eventTime = row.getAndResetLastActionUpTime();
+            Bundle options = eventTime > 0 ? getActivityOptions(adapter,
+                    mKeyguardStateController.isShowing(), eventTime) : getActivityOptions(adapter);
             int launchResult = intent.sendAndReturnResult(mContext, 0, fillInIntent, null,
-                    null, null, getActivityOptions(adapter));
+                    null, null, options);
             mMainThreadHandler.post(() -> {
                 mActivityLaunchAnimator.setLaunchResult(launchResult, isActivityIntent);
             });
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 9ddf7a4..d71b919 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -941,10 +941,19 @@
             if (resolvedUserId != mCurrentUserId) {
                 return null;
             }
-            if (mA11yWindowManager.findA11yWindowInfoByIdLocked(windowId) == null) {
+            final AccessibilityWindowInfo accessibilityWindowInfo = mA11yWindowManager
+                    .findA11yWindowInfoByIdLocked(windowId);
+            if (accessibilityWindowInfo == null) {
                 return null;
             }
-            return mA11yWindowManager.getWindowTokenForUserAndWindowIdLocked(userId, windowId);
+            // We use AccessibilityWindowInfo#getId instead of windowId. When the windowId comes
+            // from an embedded hierarchy, the system can't find correct window token because
+            // embedded hierarchy doesn't have windowInfo. Calling
+            // AccessibilityWindowManager#findA11yWindowInfoByIdLocked can look for its parent's
+            // windowInfo, so it is safer to use AccessibilityWindowInfo#getId
+            // to get window token to find real window.
+            return mA11yWindowManager.getWindowTokenForUserAndWindowIdLocked(userId,
+                    accessibilityWindowInfo.getId());
         }
     }
 
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
index 4cff5c0..7e3c1ab 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
@@ -16,8 +16,11 @@
 
 package com.android.server.devicestate;
 
+import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
+
 import android.annotation.NonNull;
 import android.content.Context;
+import android.hardware.devicestate.IDeviceStateManager;
 import android.util.IntArray;
 import android.util.Slog;
 
@@ -49,9 +52,6 @@
  * @see DeviceStatePolicy
  */
 public final class DeviceStateManagerService extends SystemService {
-    /** Invalid device state. */
-    public static final int INVALID_DEVICE_STATE = -1;
-
     private static final String TAG = "DeviceStateManagerService";
     private static final boolean DEBUG = false;
 
@@ -88,6 +88,7 @@
     @Override
     public void onStart() {
         mDeviceStatePolicy.getDeviceStateProvider().setListener(new DeviceStateProviderListener());
+        publishBinderService(Context.DEVICE_STATE_SERVICE, new BinderService());
     }
 
     /**
@@ -267,4 +268,9 @@
             requestState(state);
         }
     }
+
+    /** Implementation of {@link IDeviceStateManager} published as a binder service. */
+    private final class BinderService extends IDeviceStateManager.Stub {
+
+    }
 }
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index eb2c7e6..93cada7 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -208,7 +208,6 @@
     private PackageManager mPackageManager;
     private Context mContext;
 
-    private DisplayDeviceConfig mDisplayDeviceConfig;
     private final Injector mInjector;
 
     AutomaticBrightnessController(Callbacks callbacks, Looper looper,
@@ -217,14 +216,13 @@
             float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate,
             long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
             boolean resetAmbientLuxAfterWarmUpConfig, HysteresisLevels ambientBrightnessThresholds,
-            HysteresisLevels screenBrightnessThresholds, Context context, DisplayDeviceConfig
-            displayDeviceConfig) {
+            HysteresisLevels screenBrightnessThresholds, Context context) {
         this(new Injector(), callbacks, looper, sensorManager, lightSensor, mapper,
                 lightSensorWarmUpTime, brightnessMin, brightnessMax, dozeScaleFactor,
                 lightSensorRate, initialLightSensorRate, brighteningLightDebounceConfig,
                 darkeningLightDebounceConfig, resetAmbientLuxAfterWarmUpConfig,
-                ambientBrightnessThresholds, screenBrightnessThresholds, context,
-                displayDeviceConfig);
+                ambientBrightnessThresholds, screenBrightnessThresholds, context
+        );
     }
 
     @VisibleForTesting
@@ -234,8 +232,7 @@
             float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate,
             long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
             boolean resetAmbientLuxAfterWarmUpConfig, HysteresisLevels ambientBrightnessThresholds,
-            HysteresisLevels screenBrightnessThresholds, Context context, DisplayDeviceConfig
-            displayDeviceConfig) {
+            HysteresisLevels screenBrightnessThresholds, Context context) {
         mInjector = injector;
         mContext = context;
         mCallbacks = callbacks;
@@ -257,7 +254,6 @@
         mScreenBrightnessThresholds = screenBrightnessThresholds;
         mShortTermModelValid = true;
         mShortTermModelAnchor = -1;
-        mDisplayDeviceConfig = displayDeviceConfig;
         mHandler = new AutomaticBrightnessHandler(looper);
         mAmbientLightRingBuffer =
             new AmbientLightRingBuffer(mNormalLightSensorRate, mAmbientLightHorizon);
diff --git a/services/core/java/com/android/server/display/DisplayBlanker.java b/services/core/java/com/android/server/display/DisplayBlanker.java
index d294898..e2129ba 100644
--- a/services/core/java/com/android/server/display/DisplayBlanker.java
+++ b/services/core/java/com/android/server/display/DisplayBlanker.java
@@ -20,5 +20,5 @@
  * Interface used to update the actual display state.
  */
 public interface DisplayBlanker {
-    void requestDisplayState(int state, float brightness);
+    void requestDisplayState(int displayId, int state, float brightness);
 }
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index ca94efc..ffce3be 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -2382,7 +2382,7 @@
             synchronized (mSyncRoot) {
                 DisplayBlanker blanker = new DisplayBlanker() {
                     @Override
-                    public void requestDisplayState(int state, float brightness) {
+                    public void requestDisplayState(int displayId, int state, float brightness) {
                         // The order of operations is important for legacy reasons.
                         if (state == Display.STATE_OFF) {
                             requestGlobalDisplayStateInternal(state, brightness);
@@ -2395,11 +2395,9 @@
                         }
                     }
                 };
-                LogicalDisplay defaultDisplay =
-                        mLogicalDisplayMapper.getLocked(Display.DEFAULT_DISPLAY);
-                DisplayDevice defaultDevice = defaultDisplay.getPrimaryDisplayDeviceLocked();
                 mDisplayPowerController = new DisplayPowerController(
-                        mContext, callbacks, handler, sensorManager, blanker, defaultDevice);
+                        mContext, callbacks, handler, sensorManager, blanker,
+                        Display.DEFAULT_DISPLAY);
                 mSensorManager = sensorManager;
             }
 
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 58ef9d1..0211876 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -163,8 +163,8 @@
     // The display blanker.
     private final DisplayBlanker mBlanker;
 
-    // The display device.
-    private final DisplayDevice mDisplayDevice;
+    // The ID of the LogicalDisplay tied to this DisplayPowerController.
+    private final int mDisplayId;
 
     // Tracker for brightness changes.
     private final BrightnessTracker mBrightnessTracker;
@@ -406,7 +406,7 @@
      */
     public DisplayPowerController(Context context,
             DisplayPowerCallbacks callbacks, Handler handler,
-            SensorManager sensorManager, DisplayBlanker blanker, DisplayDevice displayDevice) {
+            SensorManager sensorManager, DisplayBlanker blanker, int displayId) {
         mHandler = new DisplayControllerHandler(handler.getLooper());
         mBrightnessTracker = new BrightnessTracker(context, null);
         mSettingsObserver = new SettingsObserver(mHandler);
@@ -417,10 +417,9 @@
         mBlanker = blanker;
         mContext = context;
         mBrightnessSynchronizer = new BrightnessSynchronizer(context);
-        mDisplayDevice = displayDevice;
+        mDisplayId = displayId;
 
         PowerManager pm =  context.getSystemService(PowerManager.class);
-        DisplayDeviceConfig displayDeviceConfig = mDisplayDevice.getDisplayDeviceConfig();
 
         final Resources resources = context.getResources();
 
@@ -515,7 +514,7 @@
                         mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
                         initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
                         autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds,
-                        screenBrightnessThresholds, context, displayDeviceConfig);
+                        screenBrightnessThresholds, context);
             } else {
                 mUseSoftwareAutoBrightnessConfig = false;
             }
@@ -684,7 +683,7 @@
         // Initialize the power state object for the default display.
         // In the future, we might manage multiple displays independently.
         mPowerState = new DisplayPowerState(mBlanker,
-                mColorFadeEnabled ? new ColorFade(Display.DEFAULT_DISPLAY) : null);
+                mColorFadeEnabled ? new ColorFade(mDisplayId) : null, mDisplayId);
 
         if (mColorFadeEnabled) {
             mColorFadeOnAnimator = ObjectAnimator.ofFloat(
@@ -1153,7 +1152,7 @@
         if (ready && state != Display.STATE_OFF
                 && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_ON) {
             setReportedScreenState(REPORTED_TO_POLICY_SCREEN_ON);
-            mWindowManagerPolicy.screenTurnedOn();
+            mWindowManagerPolicy.screenTurnedOn(mDisplayId);
         }
 
         // Grab a wake lock if we have unfinished business.
@@ -1277,7 +1276,7 @@
                 if (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_ON) {
                     setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_OFF);
                     blockScreenOff();
-                    mWindowManagerPolicy.screenTurningOff(mPendingScreenOffUnblocker);
+                    mWindowManagerPolicy.screenTurningOff(mDisplayId, mPendingScreenOffUnblocker);
                     unblockScreenOff();
                 } else if (mPendingScreenOffUnblocker != null) {
                     // Abort doing the state change until screen off is unblocked.
@@ -1309,14 +1308,14 @@
                 && !mScreenOffBecauseOfProximity) {
             setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);
             unblockScreenOn();
-            mWindowManagerPolicy.screenTurnedOff();
+            mWindowManagerPolicy.screenTurnedOff(mDisplayId);
         } else if (!isOff
                 && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_OFF) {
 
             // We told policy already that screen was turning off, but now we changed our minds.
             // Complete the full state transition on -> turningOff -> off.
             unblockScreenOff();
-            mWindowManagerPolicy.screenTurnedOff();
+            mWindowManagerPolicy.screenTurnedOff(mDisplayId);
             setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);
         }
         if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF) {
@@ -1326,7 +1325,7 @@
             } else {
                 unblockScreenOn();
             }
-            mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker);
+            mWindowManagerPolicy.screenTurningOn(mDisplayId, mPendingScreenOnUnblocker);
         }
 
         // Return true if the screen isn't blocked.
diff --git a/services/core/java/com/android/server/display/DisplayPowerState.java b/services/core/java/com/android/server/display/DisplayPowerState.java
index 4b6430d..54f30a9 100644
--- a/services/core/java/com/android/server/display/DisplayPowerState.java
+++ b/services/core/java/com/android/server/display/DisplayPowerState.java
@@ -58,6 +58,7 @@
     private final DisplayBlanker mBlanker;
     private final ColorFade mColorFade;
     private final PhotonicModulator mPhotonicModulator;
+    private final int mDisplayId;
 
     private int mScreenState;
     private float mScreenBrightness;
@@ -71,13 +72,14 @@
 
     private Runnable mCleanListener;
 
-    public DisplayPowerState(DisplayBlanker blanker, ColorFade colorFade) {
+    public DisplayPowerState(DisplayBlanker blanker, ColorFade colorFade, int displayId) {
         mHandler = new Handler(true /*async*/);
         mChoreographer = Choreographer.getInstance();
         mBlanker = blanker;
         mColorFade = colorFade;
         mPhotonicModulator = new PhotonicModulator();
         mPhotonicModulator.start();
+        mDisplayId = displayId;
 
         // At boot time, we know that the screen is on and the electron beam
         // animation is not playing.  We don't know the screen's brightness though,
@@ -434,10 +436,10 @@
 
                 // Apply pending change.
                 if (DEBUG) {
-                    Slog.d(TAG, "Updating screen state: state="
+                    Slog.d(TAG, "Updating screen state: id=" + mDisplayId +  ", state="
                             + Display.stateToString(state) + ", backlight=" + brightnessState);
                 }
-                mBlanker.requestDisplayState(state, brightnessState);
+                mBlanker.requestDisplayState(mDisplayId, state, brightnessState);
             }
         }
     }
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index df283e2..0313aae 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -4506,7 +4506,11 @@
 
     // Called on the DisplayManager's DisplayPowerController thread.
     @Override
-    public void screenTurnedOff() {
+    public void screenTurnedOff(int displayId) {
+        if (displayId != DEFAULT_DISPLAY) {
+            return;
+        }
+
         if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
 
         updateScreenOffSleepToken(true);
@@ -4529,7 +4533,11 @@
 
     // Called on the DisplayManager's DisplayPowerController thread.
     @Override
-    public void screenTurningOn(final ScreenOnListener screenOnListener) {
+    public void screenTurningOn(int displayId, final ScreenOnListener screenOnListener) {
+        if (displayId != DEFAULT_DISPLAY) {
+            return;
+        }
+
         if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
 
         Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenTurningOn", 0 /* cookie */);
@@ -4552,7 +4560,11 @@
 
     // Called on the DisplayManager's DisplayPowerController thread.
     @Override
-    public void screenTurnedOn() {
+    public void screenTurnedOn(int displayId) {
+        if (displayId != DEFAULT_DISPLAY) {
+            return;
+        }
+
         synchronized (mLock) {
             if (mKeyguardDelegate != null) {
                 mKeyguardDelegate.onScreenTurnedOn();
@@ -4562,7 +4574,11 @@
     }
 
     @Override
-    public void screenTurningOff(ScreenOffListener screenOffListener) {
+    public void screenTurningOff(int displayId, ScreenOffListener screenOffListener) {
+        if (displayId != DEFAULT_DISPLAY) {
+            return;
+        }
+
         mWindowManagerFuncs.screenTurningOff(screenOffListener);
         synchronized (mLock) {
             if (mKeyguardDelegate != null) {
@@ -4824,8 +4840,8 @@
         }
         startedWakingUp(ON_BECAUSE_OF_UNKNOWN);
         finishedWakingUp(ON_BECAUSE_OF_UNKNOWN);
-        screenTurningOn(null);
-        screenTurnedOn();
+        screenTurningOn(DEFAULT_DISPLAY, null);
+        screenTurnedOn(DEFAULT_DISPLAY);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index b96d65c..0d8d347 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -831,7 +831,7 @@
     public void finishedGoingToSleep(int why);
 
     /**
-     * Called when the device is about to turn on the screen to show content.
+     * Called when the display is about to turn on to show content.
      * When waking up, this method will be called once after the call to wakingUp().
      * When dozing, the method will be called sometime after the call to goingToSleep() and
      * may be called repeatedly in the case where the screen is pulsing on and off.
@@ -839,13 +839,13 @@
      * Must call back on the listener to tell it when the higher-level system
      * is ready for the screen to go on (i.e. the lock screen is shown).
      */
-    public void screenTurningOn(ScreenOnListener screenOnListener);
+    public void screenTurningOn(int displayId, ScreenOnListener screenOnListener);
 
     /**
-     * Called when the device has actually turned on the screen, i.e. the display power state has
-     * been set to ON and the screen is unblocked.
+     * Called when the display has actually turned on, i.e. the display power state has been set to
+     * ON and the screen is unblocked.
      */
-    public void screenTurnedOn();
+    public void screenTurnedOn(int displayId);
 
     /**
      * Called when the display would like to be turned off. This gives policy a chance to do some
@@ -854,12 +854,12 @@
      * @param screenOffListener Must be called to tell that the display power state can actually be
      *                          changed now after policy has done its work.
      */
-    public void screenTurningOff(ScreenOffListener screenOffListener);
+    public void screenTurningOff(int displayId, ScreenOffListener screenOffListener);
 
     /**
-     * Called when the device has turned the screen off.
+     * Called when the display has turned off.
      */
-    public void screenTurnedOff();
+    public void screenTurnedOff(int displayId);
 
     public interface ScreenOnListener {
         void onScreenOn();
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index fb06a9c..9d08b1b 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -397,6 +397,13 @@
                     return -1;
             }
         }
+
+        PackageOptimizationInfo getPackageOptimizationInfo(ArtManagerInternal artManagerInternal) {
+            return artManagerInternal == null || launchedActivityAppRecordRequiredAbi == null
+                    ? PackageOptimizationInfo.createWithNoInfo()
+                    : artManagerInternal.getPackageOptimizationInfo(applicationInfo,
+                            launchedActivityAppRecordRequiredAbi, launchedActivityName);
+        }
     }
 
     ActivityMetricsLogger(ActivityStackSupervisor supervisor, Looper looper) {
@@ -857,14 +864,8 @@
                     info.bindApplicationDelayMs);
         }
         builder.addTaggedData(APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS, info.windowsDrawnDelayMs);
-        final ArtManagerInternal artManagerInternal = getArtManagerInternal();
         final PackageOptimizationInfo packageOptimizationInfo =
-                (artManagerInternal == null) || (info.launchedActivityAppRecordRequiredAbi == null)
-                ? PackageOptimizationInfo.createWithNoInfo()
-                : artManagerInternal.getPackageOptimizationInfo(
-                        info.applicationInfo,
-                        info.launchedActivityAppRecordRequiredAbi,
-                        info.launchedActivityName);
+                info.getPackageOptimizationInfo(getArtManagerInternal());
         builder.addTaggedData(PACKAGE_OPTIMIZATION_COMPILATION_REASON,
                 packageOptimizationInfo.getCompilationReason());
         builder.addTaggedData(PACKAGE_OPTIMIZATION_COMPILATION_FILTER,
@@ -985,6 +986,8 @@
         builder.addTaggedData(APP_TRANSITION_PROCESS_RUNNING,
                 info.mProcessRunning ? 1 : 0);
         mMetricsLogger.write(builder);
+        final PackageOptimizationInfo packageOptimizationInfo =
+                infoSnapshot.getPackageOptimizationInfo(getArtManagerInternal());
         FrameworkStatsLog.write(
                 FrameworkStatsLog.APP_START_FULLY_DRAWN,
                 info.mLastLaunchedActivity.info.applicationInfo.uid,
@@ -995,6 +998,8 @@
                 info.mLastLaunchedActivity.info.name,
                 info.mProcessRunning,
                 startupTimeMs,
+                packageOptimizationInfo.getCompilationReason(),
+                packageOptimizationInfo.getCompilationFilter(),
                 info.mSourceType,
                 info.mSourceEventDelayMs);
 
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index 25732e7..7ed22a1 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -203,16 +203,14 @@
                     .setCallsite("ScreenRotationAnimation")
                     .build();
 
-            // In case display bounds change, screenshot buffer and surface may mismatch so set a
-            // scaling mode.
-            SurfaceControl.Transaction t2 = mService.mTransactionFactory.get();
-            t2.setOverrideScalingMode(mScreenshotLayer, Surface.SCALING_MODE_SCALE_TO_WINDOW);
-            t2.apply(true /* sync */);
-
             // Capture a screenshot into the surface we just created.
             final int displayId = displayContent.getDisplayId();
             final Surface surface = mService.mSurfaceFactory.get();
+            // In case display bounds change, screenshot buffer and surface may mismatch so set a
+            // scaling mode.
             surface.copyFrom(mScreenshotLayer);
+            surface.setScalingMode(Surface.SCALING_MODE_SCALE_TO_WINDOW);
+
             SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer =
                     mService.mDisplayManagerInternal.systemScreenshot(displayId);
             if (screenshotBuffer != null) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 249fe03..0077182 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1474,14 +1474,6 @@
         // Update task bounds if needed.
         adjustBoundsForDisplayChangeIfNeeded(getDisplayContent());
 
-        if (getWindowConfiguration().windowsAreScaleable()) {
-            // We force windows out of SCALING_MODE_FREEZE so that we can continue to animate them
-            // while a resize is pending.
-            forceWindowsScaleable(true /* force */);
-        } else {
-            forceWindowsScaleable(false /* force */);
-        }
-
         mRootWindowContainer.updateUIDsPresentOnDisplay();
 
         // Resume next focusable stack after reparenting to another display if we aren't removing
@@ -3780,17 +3772,6 @@
         positionChildAt(position, child, false /* includeParents */);
     }
 
-    void forceWindowsScaleable(boolean force) {
-        mWmService.openSurfaceTransaction();
-        try {
-            for (int i = mChildren.size() - 1; i >= 0; i--) {
-                mChildren.get(i).forceWindowsScaleableInTransaction(force);
-            }
-        } finally {
-            mWmService.closeSurfaceTransaction("forceWindowsScaleable");
-        }
-    }
-
     void setTaskDescription(TaskDescription taskDescription) {
         mTaskDescription = taskDescription;
     }
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 95d8662..0edaa1d 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -861,13 +861,6 @@
         }
     }
 
-    void forceWindowsScaleableInTransaction(boolean force) {
-        for (int i = mChildren.size() - 1; i >= 0; --i) {
-            final WindowContainer wc = mChildren.get(i);
-            wc.forceWindowsScaleableInTransaction(force);
-        }
-    }
-
     /**
      * @return {@code true} when an application can override an app transition animation on this
      * container.
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 0b53bf6..3b79241 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2172,16 +2172,7 @@
         }
     }
 
-    @Override
-    void forceWindowsScaleableInTransaction(boolean force) {
-        if (mWinAnimator != null && mWinAnimator.hasSurface()) {
-            mWinAnimator.mSurfaceController.forceScaleableInTransaction(force);
-        }
-
-        super.forceWindowsScaleableInTransaction(force);
-    }
-
-    @Override
+  @Override
     void removeImmediately() {
         super.removeImmediately();
 
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index f342976..6349e6d 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -971,10 +971,6 @@
      * @return Returns true if the surface was successfully shown.
      */
     private boolean showSurfaceRobustlyLocked() {
-        if (mWin.getWindowConfiguration().windowsAreScaleable()) {
-            mSurfaceController.forceScaleableInTransaction(true);
-        }
-
         boolean shown = mSurfaceController.showRobustlyInTransaction();
         if (!shown)
             return false;
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index cbe0a42..d2c36e2 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -342,11 +342,9 @@
         return false;
     }
 
-    void forceScaleableInTransaction(boolean force) {
-        // -1 means we don't override the default or client specified
-        // scaling mode.
-        int scalingMode = force ? SCALING_MODE_SCALE_TO_WINDOW : -1;
-        mSurfaceControl.setOverrideScalingMode(scalingMode);
+    void deferTransactionUntil(SurfaceControl barrier, long frame) {
+        // TODO: Logging
+        mSurfaceControl.deferTransactionUntil(barrier, frame);
     }
 
     boolean clearWindowContentFrameStats() {
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index d61783e..a5f0834 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -48,10 +48,13 @@
 import static com.android.server.alarm.AlarmManagerService.IS_WAKEUP_MASK;
 import static com.android.server.alarm.AlarmManagerService.TIME_CHANGED_MASK;
 import static com.android.server.alarm.AlarmManagerService.WORKING_INDEX;
+import static com.android.server.alarm.Constants.TEST_CALLING_PACKAGE;
+import static com.android.server.alarm.Constants.TEST_CALLING_UID;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
@@ -82,6 +85,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.provider.DeviceConfig;
 import android.provider.Settings;
+import android.util.IndentingPrintWriter;
 import android.util.Log;
 import android.util.SparseArray;
 
@@ -108,6 +112,8 @@
 import org.mockito.quality.Strictness;
 import org.mockito.stubbing.Answer;
 
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.concurrent.Executor;
@@ -116,9 +122,7 @@
 @RunWith(AndroidJUnit4.class)
 public class AlarmManagerServiceTest {
     private static final String TAG = AlarmManagerServiceTest.class.getSimpleName();
-    private static final String TEST_CALLING_PACKAGE = "com.android.framework.test-package";
     private static final int SYSTEM_UI_UID = 12345;
-    private static final int TEST_CALLING_UID = 67890;
     private static final int TEST_CALLING_USER = UserHandle.getUserId(TEST_CALLING_UID);
 
     private long mAppStandbyWindow;
@@ -350,19 +354,31 @@
     }
 
     private void setTestAlarm(int type, long triggerTime, PendingIntent operation) {
-        setTestAlarm(type, triggerTime, operation, 0, TEST_CALLING_UID);
+        setTestAlarm(type, triggerTime, operation, 0, AlarmManager.FLAG_STANDALONE,
+                TEST_CALLING_UID);
     }
 
     private void setRepeatingTestAlarm(int type, long firstTrigger, long interval,
             PendingIntent pi) {
-        setTestAlarm(type, firstTrigger, pi, interval, TEST_CALLING_UID);
+        setTestAlarm(type, firstTrigger, pi, interval, AlarmManager.FLAG_STANDALONE,
+                TEST_CALLING_UID);
+    }
+
+    private void setIdleUntilAlarm(int type, long triggerTime, PendingIntent pi) {
+        setTestAlarm(type, triggerTime, pi, 0, AlarmManager.FLAG_IDLE_UNTIL, TEST_CALLING_UID);
+    }
+
+    private void setWakeFromIdle(int type, long triggerTime, PendingIntent pi) {
+        // Note: Only alarm clock alarms are allowed to include this flag in the actual service.
+        // But this is a unit test so we'll only test the flag for granularity and convenience.
+        setTestAlarm(type, triggerTime, pi, 0,
+                AlarmManager.FLAG_WAKE_FROM_IDLE | AlarmManager.FLAG_STANDALONE, TEST_CALLING_UID);
     }
 
     private void setTestAlarm(int type, long triggerTime, PendingIntent operation, long interval,
-            int callingUid) {
-        mService.setImpl(type, triggerTime, AlarmManager.WINDOW_EXACT, interval,
-                operation, null, "test", AlarmManager.FLAG_STANDALONE, null, null,
-                callingUid, TEST_CALLING_PACKAGE);
+            int flags, int callingUid) {
+        mService.setImpl(type, triggerTime, AlarmManager.WINDOW_EXACT, interval, operation, null,
+                "test", flags, null, null, callingUid, TEST_CALLING_PACKAGE);
     }
 
     private void setTestAlarmWithListener(int type, long triggerTime, IAlarmListener listener) {
@@ -1002,7 +1018,7 @@
         for (int i = 0; i < numAlarms; i++) {
             int mockUid = UserHandle.getUid(mockUserId, 1234 + i);
             setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 10,
-                    getNewMockPendingIntent(mockUid), 0, mockUid);
+                    getNewMockPendingIntent(mockUid), 0, AlarmManager.FLAG_STANDALONE, mockUid);
         }
         assertEquals(numAlarms, mService.mAlarmsPerUid.size());
         mService.removeUserLocked(mockUserId);
@@ -1142,6 +1158,116 @@
         }
     }
 
+    @Test
+    public void singleIdleUntil() {
+        doReturn(0).when(mService).fuzzForDuration(anyLong());
+
+        final PendingIntent idleUntilPi6 = getNewMockPendingIntent();
+        setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, idleUntilPi6);
+
+        assertTrue(mService.mPendingIdleUntil.matches(idleUntilPi6, null));
+        assertEquals(mNowElapsedTest + 6, mTestTimer.getElapsed());
+        assertEquals(mNowElapsedTest + 6, mService.mPendingIdleUntil.getWhenElapsed());
+
+        final PendingIntent idleUntilPi2 = getNewMockPendingIntent();
+        setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 2, idleUntilPi2);
+
+        // The same mPendingIdleUntil should get updated, even with a different PendingIntent.
+        assertTrue(mService.mPendingIdleUntil.matches(idleUntilPi2, null));
+        assertEquals(mNowElapsedTest + 2, mTestTimer.getElapsed());
+        assertEquals(1, mService.mAlarmStore.size());
+
+        final PendingIntent idleUntilPi10 = getNewMockPendingIntent();
+        setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 10, idleUntilPi10);
+
+        // The same thing should happen even when the new alarm is in farther in the future.
+        assertTrue(mService.mPendingIdleUntil.matches(idleUntilPi10, null));
+        assertEquals(mNowElapsedTest + 10, mTestTimer.getElapsed());
+        assertEquals(1, mService.mAlarmStore.size());
+    }
+
+    @Test
+    public void nextWakeFromIdle() throws Exception {
+        assertNull(mService.mNextWakeFromIdle);
+
+        final PendingIntent wakeFromIdle6 = getNewMockPendingIntent();
+        final long trigger6 = mNowElapsedTest + 6;
+        setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, trigger6, wakeFromIdle6);
+
+        assertTrue(mService.mNextWakeFromIdle.matches(wakeFromIdle6, null));
+        assertEquals(trigger6, mService.mNextWakeFromIdle.getWhenElapsed());
+        assertEquals(trigger6, mTestTimer.getElapsed());
+
+        final PendingIntent wakeFromIdle10 = getNewMockPendingIntent();
+        final long trigger10 = mNowElapsedTest + 10;
+        setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, trigger10, wakeFromIdle10);
+
+        // mNextWakeFromIdle should not get updated.
+        assertTrue(mService.mNextWakeFromIdle.matches(wakeFromIdle6, null));
+        assertEquals(trigger6, mTestTimer.getElapsed());
+        assertEquals(trigger6, mService.mNextWakeFromIdle.getWhenElapsed());
+
+        final PendingIntent wakeFromIdle3 = getNewMockPendingIntent();
+        final long trigger3 = mNowElapsedTest + 3;
+        setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, trigger3, wakeFromIdle3);
+
+        // mNextWakeFromIdle should always reflect the next earliest wake_from_idle alarm.
+        assertTrue(mService.mNextWakeFromIdle.matches(wakeFromIdle3, null));
+        assertEquals(trigger3, mTestTimer.getElapsed());
+        assertEquals(trigger3, mService.mNextWakeFromIdle.getWhenElapsed());
+
+        mNowElapsedTest = trigger3;
+        mTestTimer.expire();
+
+        assertTrue(mService.mNextWakeFromIdle.matches(wakeFromIdle6, null));
+        assertEquals(trigger6, mTestTimer.getElapsed());
+        assertEquals(trigger6, mService.mNextWakeFromIdle.getWhenElapsed());
+
+        mService.removeLocked(wakeFromIdle6, null);
+
+        assertTrue(mService.mNextWakeFromIdle.matches(wakeFromIdle10, null));
+        assertEquals(trigger10, mTestTimer.getElapsed());
+        assertEquals(trigger10, mService.mNextWakeFromIdle.getWhenElapsed());
+
+        mService.removeLocked(wakeFromIdle10, null);
+        assertNull(mService.mNextWakeFromIdle);
+    }
+
+    @Test
+    public void idleUntilBeforeWakeFromIdle() {
+        doReturn(0).when(mService).fuzzForDuration(anyLong());
+
+        final PendingIntent idleUntilPi = getNewMockPendingIntent();
+        final long requestedIdleUntil = mNowElapsedTest + 10;
+        setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, requestedIdleUntil, idleUntilPi);
+
+        assertEquals(requestedIdleUntil, mService.mPendingIdleUntil.getWhenElapsed());
+
+        final PendingIntent wakeFromIdle5 = getNewMockPendingIntent();
+        setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, wakeFromIdle5);
+        assertEquals(mNowElapsedTest + 5, mService.mPendingIdleUntil.getWhenElapsed());
+
+        final PendingIntent wakeFromIdle8 = getNewMockPendingIntent();
+        setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 8, wakeFromIdle8);
+        assertEquals(mNowElapsedTest + 5, mService.mPendingIdleUntil.getWhenElapsed());
+
+        final PendingIntent wakeFromIdle12 = getNewMockPendingIntent();
+        setWakeFromIdle(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 12, wakeFromIdle12);
+        assertEquals(mNowElapsedTest + 5, mService.mPendingIdleUntil.getWhenElapsed());
+
+        mService.removeLocked(wakeFromIdle5, null);
+        assertEquals(mNowElapsedTest + 8, mService.mPendingIdleUntil.getWhenElapsed());
+
+        mService.removeLocked(wakeFromIdle8, null);
+        assertEquals(requestedIdleUntil, mService.mPendingIdleUntil.getWhenElapsed());
+
+        mService.removeLocked(idleUntilPi, null);
+        assertNull(mService.mPendingIdleUntil);
+
+        setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 15, idleUntilPi);
+        assertEquals(mNowElapsedTest + 12, mService.mPendingIdleUntil.getWhenElapsed());
+    }
+
     @After
     public void tearDown() {
         if (mMockingSession != null) {
@@ -1149,4 +1275,12 @@
         }
         LocalServices.removeServiceForTest(AlarmManagerInternal.class);
     }
+
+    private void dumpAllAlarms(String tag, ArrayList<Alarm> alarms) {
+        System.out.println(tag + ": ");
+        IndentingPrintWriter ipw = new IndentingPrintWriter(new PrintWriter(System.out));
+        AlarmManagerService.dumpAlarmList(ipw, alarms, mNowElapsedTest,
+                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"));
+        ipw.close();
+    }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmStoreTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmStoreTest.java
index 9e43b4a..f0490ce 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmStoreTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmStoreTest.java
@@ -16,6 +16,9 @@
 
 package com.android.server.alarm;
 
+import static com.android.server.alarm.Constants.TEST_CALLING_PACKAGE;
+import static com.android.server.alarm.Constants.TEST_CALLING_UID;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
@@ -35,9 +38,6 @@
 @Presubmit
 @RunWith(AndroidJUnit4.class)
 public class AlarmStoreTest {
-    private static final int TEST_CALLING_UID = 12345;
-    private static final String TEST_CALLING_PACKAGE = "android.alarm.unit.test";
-
     private AlarmStore mAlarmStore;
 
     @Before
@@ -45,22 +45,22 @@
         mAlarmStore = new BatchingAlarmStore(null);
     }
 
-    private static Alarm createAlarm(long whenElapsed, long windowLength, PendingIntent mockPi,
+    private static Alarm createAlarm(long whenElapsed, long windowLength,
             AlarmManager.AlarmClockInfo alarmClock) {
-        return createAlarm(AlarmManager.ELAPSED_REALTIME, whenElapsed, windowLength, mockPi,
+        return createAlarm(AlarmManager.ELAPSED_REALTIME, whenElapsed, windowLength,
                 alarmClock);
     }
 
     private static Alarm createWakeupAlarm(long whenElapsed, long windowLength,
-            PendingIntent mockPi, AlarmManager.AlarmClockInfo alarmClock) {
-        return createAlarm(AlarmManager.ELAPSED_REALTIME_WAKEUP, whenElapsed, windowLength, mockPi,
+            AlarmManager.AlarmClockInfo alarmClock) {
+        return createAlarm(AlarmManager.ELAPSED_REALTIME_WAKEUP, whenElapsed, windowLength,
                 alarmClock);
     }
 
     private static Alarm createAlarm(int type, long whenElapsed, long windowLength,
-            PendingIntent mockPi, AlarmManager.AlarmClockInfo alarmClock) {
-        return new Alarm(type, whenElapsed, whenElapsed, windowLength, whenElapsed + windowLength,
-                0, mockPi, null, null, null, 0, alarmClock, TEST_CALLING_UID, TEST_CALLING_PACKAGE);
+            AlarmManager.AlarmClockInfo alarmClock) {
+        return new Alarm(type, whenElapsed, whenElapsed, windowLength, 0, mock(PendingIntent.class),
+                null, null, null, 0, alarmClock, TEST_CALLING_UID, TEST_CALLING_PACKAGE);
     }
 
     private void addAlarmsToStore(Alarm... alarms) {
@@ -71,11 +71,11 @@
 
     @Test
     public void add() {
-        final Alarm a1 = createAlarm(1, 0, mock(PendingIntent.class), null);
+        final Alarm a1 = createAlarm(1, 0, null);
         mAlarmStore.add(a1);
         assertEquals(1, mAlarmStore.size());
 
-        final Alarm a2 = createAlarm(2, 0, mock(PendingIntent.class), null);
+        final Alarm a2 = createAlarm(2, 0, null);
         mAlarmStore.add(a2);
         assertEquals(2, mAlarmStore.size());
 
@@ -86,17 +86,17 @@
 
     @Test
     public void remove() {
-        final Alarm a1 = createAlarm(1, 0, mock(PendingIntent.class), null);
-        final Alarm a2 = createAlarm(2, 0, mock(PendingIntent.class), null);
-        final Alarm a5 = createAlarm(5, 0, mock(PendingIntent.class), null);
+        final Alarm a1 = createAlarm(1, 0, null);
+        final Alarm a2 = createAlarm(2, 0, null);
+        final Alarm a5 = createAlarm(5, 0, null);
         addAlarmsToStore(a1, a2, a5);
 
-        ArrayList<Alarm> removed = mAlarmStore.remove(a -> (a.whenElapsed < 4));
+        ArrayList<Alarm> removed = mAlarmStore.remove(a -> (a.getWhenElapsed() < 4));
         assertEquals(2, removed.size());
         assertEquals(1, mAlarmStore.size());
         assertTrue(removed.contains(a1) && removed.contains(a2));
 
-        final Alarm a8 = createAlarm(8, 0, mock(PendingIntent.class), null);
+        final Alarm a8 = createAlarm(8, 0, null);
         addAlarmsToStore(a8, a2, a1);
 
         removed = mAlarmStore.remove(unused -> false);
@@ -110,10 +110,10 @@
 
     @Test
     public void removePendingAlarms() {
-        final Alarm a1_11 = createAlarm(1, 10, mock(PendingIntent.class), null);
-        final Alarm a2_5 = createAlarm(2, 3, mock(PendingIntent.class), null);
-        final Alarm a6_9 = createAlarm(6, 3, mock(PendingIntent.class), null);
-        addAlarmsToStore(a2_5, a6_9, a1_11);
+        final Alarm a1to11 = createAlarm(1, 10, null);
+        final Alarm a2to5 = createAlarm(2, 3, null);
+        final Alarm a6to9 = createAlarm(6, 3, null);
+        addAlarmsToStore(a2to5, a6to9, a1to11);
 
         final ArrayList<Alarm> pendingAt0 = mAlarmStore.removePendingAlarms(0);
         assertEquals(0, pendingAt0.size());
@@ -121,24 +121,24 @@
 
         final ArrayList<Alarm> pendingAt3 = mAlarmStore.removePendingAlarms(3);
         assertEquals(2, pendingAt3.size());
-        assertTrue(pendingAt3.contains(a1_11) && pendingAt3.contains(a2_5));
+        assertTrue(pendingAt3.contains(a1to11) && pendingAt3.contains(a2to5));
         assertEquals(1, mAlarmStore.size());
 
-        addAlarmsToStore(a2_5, a1_11);
+        addAlarmsToStore(a2to5, a1to11);
         final ArrayList<Alarm> pendingAt7 = mAlarmStore.removePendingAlarms(7);
         assertEquals(3, pendingAt7.size());
-        assertTrue(pendingAt7.contains(a1_11) && pendingAt7.contains(a2_5) && pendingAt7.contains(
-                a6_9));
+        assertTrue(pendingAt7.contains(a1to11) && pendingAt7.contains(a2to5) && pendingAt7.contains(
+                a6to9));
         assertEquals(0, mAlarmStore.size());
     }
 
     @Test
     public void getNextWakeupDeliveryTime() {
-        final Alarm a1_10 = createAlarm(1, 9, mock(PendingIntent.class), null);
-        final Alarm a3_8_wakeup = createWakeupAlarm(3, 5, mock(PendingIntent.class), null);
-        final Alarm a6_wakeup = createWakeupAlarm(6, 0, mock(PendingIntent.class), null);
-        final Alarm a5 = createAlarm(5, 0, mock(PendingIntent.class), null);
-        addAlarmsToStore(a5, a6_wakeup, a3_8_wakeup, a1_10);
+        final Alarm a1to10 = createAlarm(1, 9, null);
+        final Alarm a3to8wakeup = createWakeupAlarm(3, 5, null);
+        final Alarm a6wakeup = createWakeupAlarm(6, 0, null);
+        final Alarm a5 = createAlarm(5, 0, null);
+        addAlarmsToStore(a5, a6wakeup, a3to8wakeup, a1to10);
 
         // The wakeup alarms are [6] and [3, 8], hence 6 is the latest time till when we can
         // defer delivering any wakeup alarm.
@@ -155,11 +155,11 @@
 
     @Test
     public void getNextDeliveryTime() {
-        final Alarm a1_10 = createAlarm(1, 9, mock(PendingIntent.class), null);
-        final Alarm a3_8_wakeup = createWakeupAlarm(3, 5, mock(PendingIntent.class), null);
-        final Alarm a6_wakeup = createWakeupAlarm(6, 0, mock(PendingIntent.class), null);
-        final Alarm a5 = createAlarm(5, 0, mock(PendingIntent.class), null);
-        addAlarmsToStore(a5, a6_wakeup, a3_8_wakeup, a1_10);
+        final Alarm a1to10 = createAlarm(1, 9, null);
+        final Alarm a3to8wakeup = createWakeupAlarm(3, 5, null);
+        final Alarm a6wakeup = createWakeupAlarm(6, 0, null);
+        final Alarm a5 = createAlarm(5, 0, null);
+        addAlarmsToStore(a5, a6wakeup, a3to8wakeup, a1to10);
 
         assertTrue(mAlarmStore.getNextDeliveryTime() <= 5);
 
@@ -168,24 +168,22 @@
     }
 
     @Test
-    public void recalculateAlarmDeliveries() {
-        final Alarm a5 = createAlarm(5, 0, mock(PendingIntent.class), null);
-        final Alarm a8 = createAlarm(8, 0, mock(PendingIntent.class), null);
-        final Alarm a10 = createAlarm(10, 0, mock(PendingIntent.class), null);
+    public void updateAlarmDeliveries() {
+        final Alarm a5 = createAlarm(5, 0, null);
+        final Alarm a8 = createAlarm(8, 0, null);
+        final Alarm a10 = createAlarm(10, 0, null);
         addAlarmsToStore(a8, a10, a5);
 
         assertEquals(5, mAlarmStore.getNextDeliveryTime());
 
-        mAlarmStore.recalculateAlarmDeliveries(a -> {
-            a.whenElapsed += 3;
-            a.maxWhenElapsed = a.whenElapsed;
+        mAlarmStore.updateAlarmDeliveries(a -> {
+            a.setPolicyElapsed(Alarm.REQUESTER_POLICY_INDEX, a.getWhenElapsed() + 3);
             return true;
         });
         assertEquals(8, mAlarmStore.getNextDeliveryTime());
 
-        mAlarmStore.recalculateAlarmDeliveries(a -> {
-            a.whenElapsed = 20 - a.whenElapsed;
-            a.maxWhenElapsed = a.whenElapsed;
+        mAlarmStore.updateAlarmDeliveries(a -> {
+            a.setPolicyElapsed(Alarm.REQUESTER_POLICY_INDEX, 20 - a.getWhenElapsed());
             return true;
         });
         assertEquals(7, mAlarmStore.getNextDeliveryTime());
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmTest.java
new file mode 100644
index 0000000..efcfae3
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.alarm;
+
+import static android.app.AlarmManager.ELAPSED_REALTIME;
+
+import static com.android.server.alarm.Alarm.APP_STANDBY_POLICY_INDEX;
+import static com.android.server.alarm.Alarm.REQUESTER_POLICY_INDEX;
+import static com.android.server.alarm.Constants.TEST_CALLING_PACKAGE;
+import static com.android.server.alarm.Constants.TEST_CALLING_UID;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import android.app.PendingIntent;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class AlarmTest {
+
+    private Alarm createDefaultAlarm(long requestedElapsed, long windowLength) {
+        return new Alarm(ELAPSED_REALTIME, 0, requestedElapsed, windowLength, 0,
+                mock(PendingIntent.class), null, null, null, 0, null, TEST_CALLING_UID,
+                TEST_CALLING_PACKAGE);
+    }
+
+    @Test
+    public void initSetsOnlyRequesterPolicy() {
+        final Alarm a = createDefaultAlarm(4567, 2);
+        assertEquals(4567, a.getPolicyElapsed(REQUESTER_POLICY_INDEX));
+        assertEquals(0, a.getPolicyElapsed(APP_STANDBY_POLICY_INDEX));
+    }
+
+    @Test
+    public void whenElapsed() {
+        final Alarm a = createDefaultAlarm(0, 0);
+
+        a.setPolicyElapsed(REQUESTER_POLICY_INDEX, 4);
+        a.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 10);
+        assertEquals(10, a.getWhenElapsed());
+
+        a.setPolicyElapsed(REQUESTER_POLICY_INDEX, 12);
+        assertEquals(12, a.getWhenElapsed());
+
+        a.setPolicyElapsed(REQUESTER_POLICY_INDEX, 7);
+        assertEquals(10, a.getWhenElapsed());
+
+        a.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 2);
+        assertEquals(7, a.getWhenElapsed());
+
+        a.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 7);
+        assertEquals(7, a.getWhenElapsed());
+    }
+
+    @Test
+    public void maxWhenElapsed() {
+        final Alarm a = createDefaultAlarm(10, 12);
+        assertEquals(22, a.getMaxWhenElapsed());
+
+        a.setPolicyElapsed(REQUESTER_POLICY_INDEX, 15);
+        assertEquals(27, a.getMaxWhenElapsed());
+
+        a.setPolicyElapsed(REQUESTER_POLICY_INDEX, 2);
+        assertEquals(14, a.getMaxWhenElapsed());
+
+        a.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 5);
+        assertEquals(14, a.getMaxWhenElapsed());
+
+        a.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 16);
+        assertEquals(16, a.getMaxWhenElapsed());
+
+        a.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 12);
+        assertEquals(14, a.getMaxWhenElapsed());
+    }
+
+    @Test
+    public void setPolicyElapsed() {
+        final Alarm exactAlarm = createDefaultAlarm(10, 0);
+
+        assertTrue(exactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 4));
+        assertTrue(exactAlarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 10));
+
+        assertFalse(exactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 8));
+        assertFalse(exactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 10));
+        assertFalse(exactAlarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 8));
+
+        assertTrue(exactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 7));
+
+        final Alarm inexactAlarm = createDefaultAlarm(10, 5);
+
+        assertTrue(inexactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 4));
+        assertTrue(inexactAlarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 10));
+
+        // whenElapsed won't change, but maxWhenElapsed will.
+        assertTrue(inexactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 8));
+        assertTrue(inexactAlarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, 10));
+
+        assertFalse(inexactAlarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, 8));
+    }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/BackgroundRestrictedAlarmsTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/BackgroundRestrictedAlarmsTest.java
index 6465739..5bb6a42 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/BackgroundRestrictedAlarmsTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/BackgroundRestrictedAlarmsTest.java
@@ -45,7 +45,7 @@
         }
         uidAlarms.add(new Alarm(
                 removeIt ? RTC : RTC_WAKEUP,
-                0, 0, 0, 0, 0, null, null, null, null, 0, null, uid, name));
+                0, 0, 0, 0, null, null, null, null, 0, null, uid, name));
         return all;
     }
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/Constants.java b/services/tests/mockingservicestests/src/com/android/server/alarm/Constants.java
new file mode 100644
index 0000000..2552db8
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/Constants.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.alarm;
+
+public interface Constants {
+    String TEST_CALLING_PACKAGE = "com.android.framework.test-package";
+    int TEST_CALLING_UID = 67890;
+}
diff --git a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
index 59d4e2a..058794a 100644
--- a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
@@ -16,7 +16,7 @@
 
 package com.android.server.devicestate;
 
-import static com.android.server.devicestate.DeviceStateManagerService.INVALID_DEVICE_STATE;
+import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertThrows;
diff --git a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
index b69cc47..ec747ac 100644
--- a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
@@ -83,8 +83,8 @@
                 BRIGHTNESS_MAX_FLOAT, DOZE_SCALE_FACTOR, LIGHT_SENSOR_RATE,
                 INITIAL_LIGHT_SENSOR_RATE, BRIGHTENING_LIGHT_DEBOUNCE_CONFIG,
                 DARKENING_LIGHT_DEBOUNCE_CONFIG, RESET_AMBIENT_LUX_AFTER_WARMUP_CONFIG,
-                mAmbientBrightnessThresholds, mScreenBrightnessThresholds, mContext,
-                mDisplayDeviceConfig);
+                mAmbientBrightnessThresholds, mScreenBrightnessThresholds, mContext
+        );
         controller.setLoggingEnabled(true);
 
         // Configure the brightness controller and grab an instance of the sensor listener,
diff --git a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
index d0a5644..ecbfac8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
+++ b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
@@ -163,12 +163,6 @@
     }
 
     @Override
-    public SurfaceControl.Transaction setOverrideScalingMode(SurfaceControl sc,
-            int overrideScalingMode) {
-        return this;
-    }
-
-    @Override
     public SurfaceControl.Transaction setColor(SurfaceControl sc, float[] color) {
         return this;
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
index dc85904..db5c796 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -197,19 +197,19 @@
     }
 
     @Override
-    public void screenTurningOn(ScreenOnListener screenOnListener) {
+    public void screenTurningOn(int displayId, ScreenOnListener screenOnListener) {
     }
 
     @Override
-    public void screenTurnedOn() {
+    public void screenTurnedOn(int displayId) {
     }
 
     @Override
-    public void screenTurningOff(ScreenOffListener screenOffListener) {
+    public void screenTurningOff(int displayId, ScreenOffListener screenOffListener) {
     }
 
     @Override
-    public void screenTurnedOff() {
+    public void screenTurnedOff(int displayId) {
     }
 
     @Override
diff --git a/telecomm/java/android/telecom/CallerInfo.java b/telecomm/java/android/telecom/CallerInfo.java
index fb6f994..aff2f01 100644
--- a/telecomm/java/android/telecom/CallerInfo.java
+++ b/telecomm/java/android/telecom/CallerInfo.java
@@ -405,7 +405,8 @@
         // Change the callerInfo number ONLY if it is an emergency number
         // or if it is the voicemail number.  If it is either, take a
         // shortcut and skip the query.
-        if (PhoneNumberUtils.isLocalEmergencyNumber(context, number)) {
+        TelephonyManager tm = context.getSystemService(TelephonyManager.class);
+        if (tm.isEmergencyNumber(number)) {
             return new CallerInfo().markAsEmergency(context);
         } else if (PhoneNumberUtils.isVoiceMailNumber(null, subId, number)) {
             return new CallerInfo().markAsVoiceMail(context, subId);
diff --git a/telecomm/java/android/telecom/CallerInfoAsyncQuery.java b/telecomm/java/android/telecom/CallerInfoAsyncQuery.java
index 4a81a8e..a9e1a8f 100644
--- a/telecomm/java/android/telecom/CallerInfoAsyncQuery.java
+++ b/telecomm/java/android/telecom/CallerInfoAsyncQuery.java
@@ -34,6 +34,7 @@
 import android.provider.ContactsContract.PhoneLookup;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 
 import java.util.ArrayList;
@@ -481,7 +482,8 @@
         cw.subId = subId;
 
         // check to see if these are recognized numbers, and use shortcuts if we can.
-        if (PhoneNumberUtils.isLocalEmergencyNumber(context, number)) {
+        TelephonyManager tm = context.getSystemService(TelephonyManager.class);
+        if (tm.isEmergencyNumber(number)) {
             cw.event = EVENT_EMERGENCY_NUMBER;
         } else if (PhoneNumberUtils.isVoiceMailNumber(context, subId, number)) {
             cw.event = EVENT_VOICEMAIL_NUMBER;
diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
index 9bf6b6f..6662b0e 100644
--- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
+++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
@@ -27,6 +27,7 @@
 import static org.junit.Assume.assumeTrue;
 
 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.ddmlib.Log;
 import com.android.tradefed.device.DeviceNotAvailableException;
 import com.android.tradefed.device.IFileEntry;
 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@@ -53,6 +54,7 @@
  */
 @RunWith(DeviceJUnit4ClassRunner.class)
 public class StagedRollbackTest extends BaseHostJUnit4Test {
+    private static final String TAG = "StagedRollbackTest";
     private static final int NATIVE_CRASHES_THRESHOLD = 5;
 
     /**
@@ -556,16 +558,18 @@
         return String.format("/data/user_de/%d/%s", userId, apexName);
     }
 
-    private List<String> getSnapshotDirectories(String baseDir) {
-        try {
-            return getDevice().getFileEntry(baseDir).getChildren(false)
-                    .stream().filter(entry -> entry.getName().matches("\\d+(-prerestore)?"))
-                    .map(entry -> entry.getFullPath())
-                    .collect(Collectors.toList());
-        } catch (Exception e) {
-            // Return an empty list if any error
+    private List<String> getSnapshotDirectories(String baseDir) throws Exception {
+        IFileEntry f = getDevice().getFileEntry(baseDir);
+        if (f == null) {
+            Log.d(TAG, "baseDir doesn't exist: " + baseDir);
             return Collections.EMPTY_LIST;
         }
+        List<String> list = f.getChildren(false)
+                .stream().filter(entry -> entry.getName().matches("\\d+(-prerestore)?"))
+                .map(entry -> entry.getFullPath())
+                .collect(Collectors.toList());
+        Log.d(TAG, "getSnapshotDirectories=" + list);
+        return list;
     }
 
     private void assertDirectoryIsEmpty(String path) {